Live data from Hacker News

Six Years of Professional Clojure

engineering.nanit.com

161–170 of 254 posts

Re: Six Years of Professional Clojure

#161
post #97

Earlier quoted context omitted.

Yeah, I had a fairly large (about a year of solo dev work) app that I maintained both Clojure and F# ports of, doing a compare and contrast of the various language strengths. One day I refactored the F# to be async, a change that affected like half the codebase, but was completed pretty mechanically via changing the core lines, then following the red squigglies until everything compiled again, and it basically worked…

Hey, so my my career path has been C# (many years) -> F# (couple years) -> Clojure (3 months). I understand multithreading primarily through the lens of async/await, and have been having trouble fully grokking the Clojure's multithreading. One of the commandments of async/await is don't block: https://blog.stephencleary.com/2012/07/dont-block-on-async-c... Which is why the async monad tends to infect everything. Cloj…

Not even. It was opening it, looking, realizing it would take a couple weeks, and going back to F#. I did this a couple times before fully giving up.

IIRC/IIUC, Clojure's async support is closer to Go's (I've never used go), in the form of explicit channels. Though you can wrap that in a monad pretty easily, which I did for fun one day (https://gist.github.com/daxfohl/5ca4da331901596ae376). But neither option was easy to port AFAICT before giving up.

Note it's possible that porting async functionality to Clojure may have been easier that I thought at the time. Maybe adding some channels and having them do their thing could have "just worked". I was used to async requiring everything above it to be async too. But maybe channels don't require that, and you can just plop them in the low level code and it all magically works. A very brief venture into Go since then has made me wonder about that.

Re: Six Years of Professional Clojure

#162

Earlier quoted context omitted.

It's your opinion though, there's nothing scientific about what you're saying. Take mocking for example, in Ruby/Rails it's a breeze. In Java you need to invent a dependency injection framework (Spring) to do it.

I think you are mistaken. Mocking and DI frameworks are two unrelated concepts. There is nothing in Java that forces you to use a DI framework, e.g., Spring if you want to use mocks during testing.

In theory, I agree, but I don't think that holds terribly true in practice.

One of the ideas behind IoC frameworks (which build on top of DI) is that you could swap out implementation classes. For a great deal of software (and especially in cloud-hosted, SaaS style microservice architecture) the test stubs are the only other implementations that ever get injected.

Most code bases could ditch IoC if Java provided a language-level construct, even if that construct were only for the test harness.

Re: Six Years of Professional Clojure

#163

Earlier quoted context omitted.

In 2021, I find it hard to justify using a dynamically typed language for any project that exceeds a few hundreds of lines. It's not a trade off, it's a net loss. The current crop of statically typed languages (from the oldest ones, e.g. C#, to the more recent ones, e.g. Kotlin and Rust) is basically doing everything that dynamically typed languages used to have a monopoly on, but on top of that, they offer performan…

I find immutability way more important. I don't pick Clojure for its dynamic typing, I pick it for other reasons. I've tried Haskell but it really doesn't seem to mesh with the way I tend to develop a program. But I would love to have more static languages with the pervasive immutability of Clojure.

I really like F# for this, it's like Haskell-lite

Re: Six Years of Professional Clojure

#164

Walmart Labs was a step in this direction.. but we need some big companies to standardize around Clojure to jumpstart the ecosystem of knowledge, libraries, talent, etc. I’ve spoken to engineering hiring managers at fairly big companies and they’re not willing to shift to a niche language based only on technical merits but without a strong ecosystem. If we don’t get some big companies to take on this roll the languag…

> If we don’t get some big companies to take on this roll

- Cisco - has built their entire integrated security platform on Clojure

- Walmart Labs and Sam's club - have some big projects in Clojure

- Apple - something related to the payment system

- Netflix and Amazon, afaik they use Clojure as well

even NASA uses Clojure.

I think the language "is going somewhere"...

Re: Six Years of Professional Clojure

#165

Earlier quoted context omitted.

I think you are mistaken. Mocking and DI frameworks are two unrelated concepts. There is nothing in Java that forces you to use a DI framework, e.g., Spring if you want to use mocks during testing.

Let's say I have a class called User and in it a method that says the current time. So User#say_current_time which simply accesses the Date class (it takes no arguments). Can you show me how you would mock the current time of that method in Java? It's one line of Ruby/Javascript code to do that.

I'll take clean contractual interfaces (aka actual principle of least surprise) over "I can globally change what time means with one line of code!" on large projects every time.

Re: Six Years of Professional Clojure

#166

Earlier quoted context omitted.

> E.g. you could express something like "the parameter must be a date within the next 5 business days" - there's no static restriction Hm, I don't follow. If I were to write this in F#, there would be a type `Within5BusinessDays` with a private constructor that exposes one function/method `tryCreate` which returns a discriminated union: either an `Ok` of the `Within5BusinessDays` type, or an `Error` type with some er…

> If I were to write this in F#, there would be a type `Within5BusinessDays` That’s not really the same thing - it’sa valid alternative approach but you’ve lost the benefits of a simple date - from (de)serialisation to the rich support for simple date types in libraries and other functions, the simple at-a-glance understanding that future readers could enjoy. Now the concept of date has been complected with some othe…

> but you’ve lost the benefits of a simple date

I see what you mean - thanks!

> you could further choose to turn it off or to substitute your own types / schema without making changes to the system / code

This is still unclear to me. How can you make changes (turning off gradual typing/substituting your own schema) without making changes to code?

Re: Six Years of Professional Clojure

#167

Earlier quoted context omitted.

The purpose of Maybe is to explicitly represent the possible non-existence of a value which in Haskell is the only option since there's no null value which inhabits every type. The existence of the monad instance is convenient but it's not fundamental. The type of getConfigurationDirectories could be changed to MaybeT IO (NonEmpty FilePath) to avoid the match but I don't think it would make such a small example clear…

There are numerous ways to redesign the function signatures, but I would imagine the simplest would be (again, idk Haskell syntax): getConfigurationDirectories: unit -> Maybe [FilePath] nonEmpty: [a] -> Maybe [a] head: [a] -> Maybe a initializeCache: FilePath -> unit Notice `nonEmpty` isn't really necessary because `head` could to the work. The above could be chained into a single, cohesive stack of calls where the r…

On the contrary the The NonEmpty type is fundamental to the approach in that example since it contains in the type the property being checked dynamically (that the list is non-empty). The nonEmpty function is a simple example of the 'parse don't validate' approach since it goes from a broader to a more restricted type, along with the possibility of failure if the constraint was not satisfied. The restriction on the NonEmpty type is what allows NonEmpty.head to return an a instead of a (Maybe a) and thus avoid the redundant check in the second example. The nonEmpty in your alternative implementation is only validating not parsing since after checking the input list is non-empty, it immediately discards the information in the return type. This forces the user to deal with a Nothing result from head that can never happen. Attempting to clean the code up by propagating Nothing values using bind is just hiding the problem that the validating approach avoids entirely.

Re: Six Years of Professional Clojure

#168

Walmart Labs was a step in this direction.. but we need some big companies to standardize around Clojure to jumpstart the ecosystem of knowledge, libraries, talent, etc. I’ve spoken to engineering hiring managers at fairly big companies and they’re not willing to shift to a niche language based only on technical merits but without a strong ecosystem. If we don’t get some big companies to take on this roll the languag…

> If we don’t get some big companies to take on this roll - Cisco - has built their entire integrated security platform on Clojure - Walmart Labs and Sam's club - have some big projects in Clojure - Apple - something related to the payment system - Netflix and Amazon, afaik they use Clojure as well even NASA uses Clojure. I think the language "is going somewhere"...

role* lol we made the same mistake. There is some adoption to be sure. But look at Google Trends for clojure.

Re: Six Years of Professional Clojure

#169

Earlier quoted context omitted.

Question: 1. Can a GET request have a non-empty request body? 2. Assuming you don’t know the answer to that question, will the type system you use be able to tell you the answer to that question? This is a pretty simple constraint one might want (a constraint that only certain requests have a body) but already a lot of static type systems (e.g. the C type system) cannot express and check it. If you can express that c…

Any statically-typed language with generics can express that by parameterising the request type with the body type. A bodiless request is then just Request[Nothing] (or Request[Unit] if your type system doesn't have a bottom type). Accessing the headers just requires an interface which all static languages should be able to express.

(1) note that “statically-typed language with generics” excludes a lot of statically typed languages, including C and Go (at least pre generics).

(2) this misses the meat of the question which is how to express that (eg) a GET request doesn’t come with a body and a POST request does. I suppose that you’re suggesting that one registers a url handler with a method type and that forces the handler to accept responses of a certain type. Or perhaps you are implicitly allowing for sun types (which aren’t a thing in many static type systems.)

(3) even in C++, isn’t this suggestion hard to work with. That is, isn’t it annoying to write a program which works for any request whether or not it has a body because the type of the body must be a template parameter that adds templates to the type of every method which is generic to it. But maybe that is ok or I just don’t understand C++.

Re: Six Years of Professional Clojure

#170
post #87

Earlier quoted context omitted.

Question: 1. Can a GET request have a non-empty request body? 2. Assuming you don’t know the answer to that question, will the type system you use be able to tell you the answer to that question? This is a pretty simple constraint one might want (a constraint that only certain requests have a body) but already a lot of static type systems (e.g. the C type system) cannot express and check it. If you can express that c…

1. Yes. It's weird, but it's legal HTTP. 2. Sure. The request type has a body property.

Does “the request type has a body property” actually imply (1) though? In a language like C or C++ or Java, you could have a protocol like “body is always null on GET requests.” The question isn’t really about HTTP, that was just an easy-to-reach-for example, it is really about what having explicit types allows one to deduce about a program.
Post reply on HN