Live data from Hacker News

Six Years of Professional Clojure

engineering.nanit.com

71–80 of 254 posts

Re: Six Years of Professional Clojure

#71
post #58
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

Except, of course, that specs are only tested correct, not proven correct like types would be. Types (in a reasonable static type system, not, say, C) are never wrong. In addition, specs do not compose, do they ? If you call a function g in a function f, there is no automatic check that their specs align.

> Except, of course, that specs are only tested correct, not proven correct like types would be.

Yes this is the fundamental tradeoff. Specs et al are undoubtedly more flexible and expressive than static type systems, at the expense of some configurable error tolerance. I don't think one approach is generally better than the other, it's a question of tradeoffs between constraint complexity and confidence bounds.

Re: Six Years of Professional Clojure

#72
post #58
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

Except, of course, that specs are only tested correct, not proven correct like types would be. Types (in a reasonable static type system, not, say, C) are never wrong. In addition, specs do not compose, do they ? If you call a function g in a function f, there is no automatic check that their specs align.

Yes, I think that is one of the big weaknesses of it. You can write specs that make no sense and it will just let you. So far there is also no way to automatically check whether you are strengthening a guarantee or weaken your assumptions relative to a previous spec. In a perfect world we would have this in my opinion.

Re: Six Years of Professional Clojure

#73
post #31

Earlier quoted context omitted.

Usually the approach in a statically-typed language is to transform your dynamic request into something that you know through parsing instead of validation. Here's a great article about this: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... .

This is the second time I've seen the link above. And while I agree with the premise, the author clearly does not understand how to properly use the `Maybe` monad (a term that does not make an appearance!). There is little use in wrapping a call in `Maybe` to then immediately unwrap the result on the next line. Doing so isn't really using the construct... One would expect the lines following the creation of `Maybe` t…

You might try re-reading it with some charity - the example's purpose isn't to teach the `Maybe` monad, but to remove the redundant check. To go into what `bind` does would be a diversion from the main topic (parsing vs validating).

FWIW SPJ has called this blog's author a "genius" so... I think they do know how `Maybe` works. https://gitlab.haskell.org/ghc/ghc/-/issues/18044#note_26617...

Re: Six Years of Professional Clojure

#74
post #37
post #33

Earlier quoted context omitted.

I think, the big issue with dynamic typing in popular languages like PHP and JavaScript are the automatic conversions.

Which is less of a concern considering Clojure's focus on immutability.

That's what I meant.

As far as I know, some dynamic languages like Python don't have that issue.

Re: Six Years of Professional Clojure

#75

Earlier quoted context omitted.

> didn't alert me until I tried running the program That's because that's not how Clojure developers normally work. You don't do changes and then "run the program". You start your REPL and send expressions from your editor to the REPL after you've made a change you're not sure about. So you'd discover the missing argument when you call the function, directly after writing it.

Interesting. How exactly that looks? Do you have files opened in your editor, change them then go into previously opened repl, and just call the functions and the new version of those function runs?

That's right. You typically would have your text editor/ide open, and the process you're developing would expose a repl port which your editor can connect to. As you edit the source code, that will automatically update the code running in the process you're debugging. See this demo of developing a ClojureScript React Native mobile app published yesterday: https://youtu.be/3HxVMGaiZbc?t=1724

Re: Six Years of Professional Clojure

#76
post #70

Earlier quoted context omitted.

> What you get here goes way beyond what a strict, static type systems gets you, such as arbitrary predicate validation, Is this refinement types, which most static languages provide? https://en.wikipedia.org/wiki/Refinement_type > freely composable schemas, My understanding is that you can compose types (and objects) https://en.wikipedia.org/wiki/Object_composition I'm assuming that types are isomorphic with schemas…

Right! I made the dumb, typical error to write: "You simply do not have that in a static world." When I should have written: "This type of expressiveness is not available in mainstream statically typed languages". With "freely composable" I mean that you can program with these schemas as they are just data structures and you only specify the things you want to specify. Both advantage and the disadvantage is that this…

Ah, well if you're going to shit on Go/Java/C#/C++ I won't stop you :)

Re: Six Years of Professional Clojure

#77

Earlier quoted context omitted.

> didn't alert me until I tried running the program That's because that's not how Clojure developers normally work. You don't do changes and then "run the program". You start your REPL and send expressions from your editor to the REPL after you've made a change you're not sure about. So you'd discover the missing argument when you call the function, directly after writing it.

Interesting. How exactly that looks? Do you have files opened in your editor, change them then go into previously opened repl, and just call the functions and the new version of those function runs?

Thanks to the dynamic nature of Clojure programs, experienced Clojure developers use the REPL-driven development workflow as demonstrated in this video [1].

[1] https://youtu.be/gIoadGfm5T8

Re: Six Years of Professional Clojure

#78
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

> What you get here goes way beyond what a strict, static type systems gets you, such as arbitrary predicate validation, Is this refinement types, which most static languages provide? https://en.wikipedia.org/wiki/Refinement_type > freely composable schemas, My understanding is that you can compose types (and objects) https://en.wikipedia.org/wiki/Object_composition I'm assuming that types are isomorphic with schemas…

>> Is this refinement types

Well it does include that kind of behaviour but it's quite a bit more than just that. E.g. you could express something like "the parameter must be a date within the next 5 business days" - there's no static restriction. I'm not necesarily saying you should but just to give an illustrative example that there's less restrictions on your freedom to express what you need than in a static system.

>> types are isomorphic with schemas

I don't think that's a good way to think of this, you're imagining a rigid 1:1 tie of data and spec yet i could swap out your spec for my spec so that would be 1:n but those specs may make sense to compose in other data use cases so really it's m:n rather than 1:1

Re: Six Years of Professional Clojure

#79
post #31

Earlier quoted context omitted.

Usually the approach in a statically-typed language is to transform your dynamic request into something that you know through parsing instead of validation. Here's a great article about this: https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... .

This is the second time I've seen the link above. And while I agree with the premise, the author clearly does not understand how to properly use the `Maybe` monad (a term that does not make an appearance!). There is little use in wrapping a call in `Maybe` to then immediately unwrap the result on the next line. Doing so isn't really using the construct... One would expect the lines following the creation of `Maybe` t…

Lexi absolutely understands how to properly use the Maybe monad. What you're saying to do here is the exact opposite of what this post is advocating for. You're talking about pushing the handling of the Maybe till later and the post is all about the advantages of handling it upfront and not having to worry about it anymore. You might want to read it one more time.

Re: Six Years of Professional Clojure

#80
post #3

I found one of the perceived weaknesses of Clojure (in this article), it being dynamically typed, is a tradeoff rather than a pure negative. But it applies that tradeoff differently than dynamic languages I know otherwise and that difference is qualitative: It enables a truly interactive way of development that keeps your mind in the code, while it is running. This is why people get addicted to Lisp, Smalltalk and si…

> ... such as arbitrary predicate validation, freely composable schemas, automated instrumentation and property testing ... Why static typing makes those things impossible?

They don't make these impossible, they typically just don't let you express these within the type system and they typically don't let you not specify your types.

I should have made clear that I'm emphasizing the advantages of being dynamic to describe and check the shape of your data to the degree of your choosing. Static typing is very powerful and useful, but writing dynamic code interactively is not just "woopdiedoo" is kind of the point I wanted to make without being overzealous/ignorant.

Post reply on HN