Hacker Newsnew | past | comments | ask | show | jobs | submit | brentshields's commentslogin

Own Up | https://www.ownup.com | Boston or REMOTE (US) | Senior Software Engineer

Own Up helps people save money on their mortgage when purchasing or refinancing a home. We're a ~50 person company based in Boston with on-site product development teams and an all-remote backend/infrastructure team. We're currently hiring senior-level candidates for all of these teams.

Tech Stack: React and Redux on the frontend, Node on AWS Lambda on backend. Typescript throughout. All serverless, using many different AWS services. Deployment via Cloud Formation.

Job postings:

- On-site in Boston (full stack): https://angel.co/company/rategravity/jobs/224210-senior-soft...

- Remote (backend-focused): https://angel.co/company/rategravity/jobs/733507-senior-back...


"So, any minor divergence in features of Clang and Visual C++ will cause you as a developer to have to worry about these compiler differences or limit you to using the smallest subset of the two compiler features"

In other words, the set of vc++ features.


Yes. We know we are behind on conformance.


Regarding bluffing: I've seen it happen where the company has asked for a pay stub as part of the final paperwork to confirm that the stated current salary was legit. So yeah that could be a downside to bluffing if you want the job.


I've never heard of such a thing but it undoubtedly happens. Your pay stub is really just showing the floor though. For many positions, there are fairly regular bonuses, variable comp, etc. So, in reality, there's usually some wiggle room in providing current salary info while still being essentially truthful.


I've been recruiting engineers for almost 20 years, and I have probably had a dozen cases where a client asked for a pay stub around the time an offer is presented. It's obviously rare, and most of the time it was for high-ticket talent that seemed to be paid noticeably above market rate.


I have to say, I find that sorta weird. At that point, I would think if the pay stub didn't square with the claimed salary (and there was no convincing explanation for the difference), they'd almost have to not hire the person. And, if it did square, it's like they'd already decided the price tag was too rich for their blood.


Excellent points, and I'm not necessarily condoning the practice (I don't control that). It does seem they are trying to call a bluff where you either expose the bluffer or get locked in to a rate above market. I can't recall an instance where the stub was provided and the client didn't make a competitive offer, but my data set isn't large.


Maybe it's a "There must be a reason they value them so much" (even though we don't see it) sort of thing. Hardly an uncommon situation. Doesn't mean it worked out in the end :-)


I've seen colleagues in Sales offer to show W-2 information, to disclose all compensation.


It sorta makes sense in that context given variable sales comp plans. "I really am that good. Here are the audited numbers to prove it."


Photoshop is a wonderful thing :)


You can get fired if they figure out you have been fudging the figures and 'lying' to them. I'm not sure how they would know, but if they do, it can create problems for you.


Error-level analysis of the Jpeg. As you say, if it comes out later that could have bad legal consequences - the term is 'detrimental reliance' and the dishonest person could conceivably face fraud charges. Even if not, it could easily become a a career-damaging topic of gossip.


Re: error analysis—it's a "picture of line-art" kind of document, isn't it? Not even a watermark. So: scan it at super high resolution, blow out the contrast, countour-vectorize it to SVG (effectively equivalent to recovering the original PDF), edit that, print the result, and then scan the print.

(It just occurred to me that if there was "an app for that" in this case, no parent would ever be able to trust their child's report card again.)


Don't even both with all of that.. Just make a reproduction from scratch.

Make it look more or less like the original. As long as nobody sees the original next to the mock-up, who's ever going to notice that one or two digits changed?


I have yet to find any case law where this occurs.

Regarding gossip, "Would you trust a company who checks up on someone's previous paycheck?" seems to quell that pretty quickly.


Scan pay slip, edit in photoshop, print out doctored image, take photo with digitial camera. :)


You can use GADTs for this. For example:

  data Showable where
    Showable :: Show a => a -> Showable
This allows you to create a polymorphic container like [Showable 5, Showable "hello"] where the polymorphic type is constrained to be a member of the Show typeclass.


Note that GADTs are a bit overkill for this. All you really need is ExistentialQuantification. GADTs are ExistentialQuantification + TypeEqualities.


As someone who knew Haskell first and then learned Clojure, I can tell you that this assumption is incorrect. It's so completely philosophically opposite from Haskell in so many ways that it's a very good mental exercise to really grok them both. It will make you appreciate how much you're paying for that fantastic type system. Understanding this cost will allow you to make better decisions in the future about which technologies are a better fit for a given project.


Sir, your comment is intriguing and I want to hear more about it.

What is this philosophically opposite that you mention? Haskell is good at creating domain-specific languages, so I think the differences must be around the superior meta-programming facilities in lisp languages. So, what would you do with Clojure that you couldn't do in Haskell easily?


It's an oversimplification, but the basic philosophical difference from my point of view is that Haskell values correctness above all and Clojure is above all pragmatic. I think all of these major differences in the languages are reflections of this:

- static vs. dynamic typing

- pure vs. allowing side effects

- native vs. hosted

- focus on syntax vs. rejection of syntax

Depending on the problem, you may get big benefits out of one side or the other.

One particular thing that is much easier in Clojure is dealing with heterogeneous, hierarchical data. This is just so effortless because of the combination of dynamic typing and the wonderful built-in persistent data structures. This is possible but takes a lot more work to do in Haskell and is much slower to iterate on when your data changes.


This comment is spot-on.

According to the Yegge programming axis, Haskell is extremist conservative (emphasizes safety above all) and Clojure is some notches down into a more moderate zone (merely "conservative") that balances safety against pragmatism.


I'm confused. In what sense is correctness not pragmatic?

Also, have you used lenses yet? Heterogenous hierarchical data in Haskell is quite easy now.


Guaranteed correctness has a cost in the form of extra specification needed to get things done. For example, many type errors are essentially noise: they do not catch real bugs, and they create needless busy-work for the programmer to correct them.

example:

function stringify(FooObj object): return object.toString()

Now suppose we do some refactoring somewhere, and we want to call stringify not with a FooObj but with a BarObj. Since we have defined stringify as taking a FooObj, the compiler whines until we update the definition. However, depending on your philosophy, this error is nothing more than noise, because stringify would work fine on a BarObj.

Pragmatists may wish to forgo such safety in favor of greater flexibility:

function stringify(object): return object.toString()

This is the essence of liberal programming: an emphasis on flexibility and minimal specification, at the cost of reduced safety guarantees.


That example is a straw man. First, all reasonably strong type systems support polymorphism well enough to handle that case trivially. Second, type inference is a thing, so a lot of code in strongly-typed languages even looks the same as your second code example.

I'm not saying you can't come up with a fair example to support your argument. I will say, though, that it's going to be a lot harder to do so, and that such examples only rarely come up in practice. The argument for flexibility at the cost of guarantees of correctness used to be a good one, but it has weakened significantly with time, and before long will cease to be valid at all.


The example cited makes two decisions which are not articulated explicitly but are decisions one can make and which have benefits and costs. They are:

1) The function correctly executes on the class of things for which (.toString thing) has a sensible run time invocation.

2) The function delays examination of the correct class of its argument from compile time to run time.

1 is a benefit, in that in a dynamic system it is possible that something which, at compile time, does not have a sensible .toString invocation, can gain it at run time and then participate in the function.

2 is a cost, in that you have to delay classification to the instant in which you try to invoke .toString

This tradeoff is elemental and there will be systems you can build by embracing it that will never be possible in strongly typed languages. You'll be able to build isomorphs of them, but doing so will involve expressing significantly more ideas to get there.


Terms like "straw man" imply that I'm trying to debate, but I'm not. You asked how correctness could be contrary to pragmatism, and I tried to provide an example.


Whether or not it's a debate has nothing to do with whether or not your example is valid. I was just pointing out that it isn't.


Out of curiosity, how would you define my example stringify function in Haskell with "no cost" safety around the argument type?


The typeclass that provides "toString" in haskell is "Show". It defines a few functions, of which the important one is "show", which takes the original type and returns a string. A function that is equivalent to the java-ish example is:

    stringify s = show s
No type definition is necessary, because the compiler can correctly infer the correct, most generic type:

   stringify :: (Show s) => s -> String
Or, for any s in type class Show, a function that makes s into a String. Note that dispatch is done statically.

Modern type systems eliminate most of the cost of type safety through good generics and type inference. Mainstream statically typed languages are just 20-30 years behind the state of the art.

(note that the example actually can be reduced to: stringify = show)


Guaranteed correctness has a cost in the form of extra specification needed to get things done.

This is simply untrue. Take an example in Haskell:

    > show 23
    "23"
    > show (4,5)
    "(4,5)"
    > show (Just 2.34, Nothing, [2..5], 'c')
    "(Just 2.34,Nothing,[2,3,4,5],'c')"
This works for all types which are members of the class Show. We can even derive new instances for Show for our own new data types automatically:

    > data Foo = Foo Int Float deriving (Show)
    > show (Foo 3 4)
    "Foo 3 4.0"
But what happens if we omit the instance of Show from our definition?

    > data Bar = Bar Char Bool
    > show (Bar 'a' True)

    <interactive>:12:1:
        No instance for (Show Bar) arising from a use of `show'
        Possible fix: add an instance declaration for (Show Bar)
        In the expression: show (Bar 'a' True)
        In an equation for `it': it = show (Bar 'a' True)
We get all the benefits of safety guarantees with minimal extra work. This form of automatic derivation works for many type classes in the standard libraries but in the cases where it doesn't work we simply define a few methods which are specified in the class's definition. None of this is any more than what you'd need to do in a dynamic language but you get all the extra benefits of compile time safety.


It was pretty easy before with generic traversals as well.

I think people give Haskell a bad rap for handling heterogenous data, but it's actually quite good at it. You just feel the pain of a poorly specific data domain more sharply and tend to want to reify it into something nicer quickly. No such option exists in Clojure unless you use Typed—and I say this as someone quite familiar with both languages.


I've discovered programming approaches in Clojure that I'm now looking for in other languages. For instance, two of the things I looked for straight away in Julia was if there were immutable types and map functions, since I've come to really appreciate them in Clojure. Haskell is on my list of languages to try out after Julia.


Having learnt a fair bit of Lisp, and dabbled with Haskell, it seems to me that a Haskell-like language should be implemented atop a Lisp-like language, rather than vice versa. Template Haskell puts macros atop Haskell, whereas it seems things like types and syntax should be atop Lisp.


Nice writeup. There's an error in one of the examples though:

(map :name people)

evaluates to a lazy sequence, not a vector.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: