Live data from Hacker News

Things Java Programmers can learn from Clojure

lispcast.com

11–20 of 58 posts

Re: Things Java Programmers can learn from Clojure

#11
I think that the article's defense of immutability is a bit poor. Making a date mutable means that it won't always reference the same point in time: yeah, a birthday will remain constant, but an appointment may not; the same goes for a lot of types. That's why C and C++ gives us the "const" keyword: the same object can now be used as mutable or immutable, depending on circumstances.

The other points, especially the second, are spot on, although they have a lot more to do with the Java culture than with the language itself.

Re: Things Java Programmers can learn from Clojure

#12
Tangential:

OP reminded me of Google Testing Blog [1]. Misko Hevery used to share lots of great insights there. Awesome yet practical stuff on coding in Java world, which anybody will greatly benefit from but not many are aware of. I hope more people read his stuff. I wish he stayed a bit longer before moving on to the AngularJS project - Java needed him more than the script.

Another Google Testing Blog star was James Whittaker, who's now moved on to Microsoft. Google Testing Blog doesn’t seems the same exciting place any more. And to add to that the crazy new design of blogspot - some stuff keeps happening on the page that's beyond one's control.

[1] http://googletesting.blogspot.com/

Re: Things Java Programmers can learn from Clojure

#13
post #7
post #6

Nice article. It does, however, trigger a thought: > By making values mutable, this magical-changing-at-a-distance is always a possibility. I agree, very much so. However, I could also simply promise that none of my code, nowhere, will modify that DateTime. On top of that, I'll ask all my colleagues to not mistreat it either. Now, that's what many of us are doing now, and the entire point if the OP's first section is…

Yeah, replying to myself. I'm not sure if that's considered weird but ok. According to this logic, most mainstream languages don't make sense. Notably, Java, C#, C, C++, Clojure are all screwed up. Not sure about other lisps. Ruby, PHP, JavaScript, Python, F#, Scala and Haskell have it right though. (yeah sure, you can do mutability in Scala and immutability in Java, but the languages and their community lean toward…

> it feels like Clojure went all liberal on one end, just to get super-conservative on the other.

In the brief time that I used Clojure, I also thought that the contrast between immutability and dynamic typing was very strange. Ultimately, I think it makes more sense than having the entire language be highly dynamic (or highly static).

I think Clojure's choice is not inconsistency, but that there is a kind of budget for craziness in a language. In Clojure, you can go crazy with dynamic types on the foundation of immutability, transactions, etc. In Haskell, you can go crazy with really awesome static typing tricks that would be utterly unfathomable if the language wasn't very rigid in every other way -- immutable, referentially transparent, side-effect-tracking. These two pack all their craziness into one corner of the language.

On the other hand, other languages -- Python, Javascript, Ruby -- seem to spread the craziness (I am not sure I picked the best word for this!) around, instead of having one super dynamic feature and everything else very inflexible. These languages tend to lack the really big flashy features: macros, typeclasses, etc.

It seems that you have a lot of flexibility as a language designer on how you spend your craziness budget, as long as you don't go too high (and become incomprehensible) or too low (Java?).

Re: Things Java Programmers can learn from Clojure

#14
post #8

I thought that classes+methods were meant to transform an object from one consistent state to another consistent state. So why is immutability suddenly a big deal? (I.e., if it's a big deal, may it be because encapsulation is lacking? IOW, is immutability a rediscovered "private" keyword, just much more cumbersome to use?)

Java's private is class based, not object based, so it's not really private. That is sort of broken.

Closure actually has truly local mutability, in its "transients" feature

Re: Things Java Programmers can learn from Clojure

#15
post #7
post #6

Nice article. It does, however, trigger a thought: > By making values mutable, this magical-changing-at-a-distance is always a possibility. I agree, very much so. However, I could also simply promise that none of my code, nowhere, will modify that DateTime. On top of that, I'll ask all my colleagues to not mistreat it either. Now, that's what many of us are doing now, and the entire point if the OP's first section is…

Yeah, replying to myself. I'm not sure if that's considered weird but ok. According to this logic, most mainstream languages don't make sense. Notably, Java, C#, C, C++, Clojure are all screwed up. Not sure about other lisps. Ruby, PHP, JavaScript, Python, F#, Scala and Haskell have it right though. (yeah sure, you can do mutability in Scala and immutability in Java, but the languages and their community lean toward…

Clojure's dynamic typing is somewhat different from other languages, though, as it really just has two non-atom types: seqs for collections and maps for data objects. Virtually all collections and objects can be manipulated as one of these two types. So "calling a method" on an inappropriate type is basically passing an inappropriate map to a function. You might want to disallow it, but Clojure allows it for good reason: this makes it possible to have many data access/manipulation functions that work on all objects. So the question is, do you want to forbid passing an argument that doesn't make sense to a function or open the door to lots of useful functions that would work on all objects. Clojure simply chose the latter.

Re: Things Java Programmers can learn from Clojure

#16
post #13
post #7

Earlier quoted context omitted.

Yeah, replying to myself. I'm not sure if that's considered weird but ok. According to this logic, most mainstream languages don't make sense. Notably, Java, C#, C, C++, Clojure are all screwed up. Not sure about other lisps. Ruby, PHP, JavaScript, Python, F#, Scala and Haskell have it right though. (yeah sure, you can do mutability in Scala and immutability in Java, but the languages and their community lean toward…

> it feels like Clojure went all liberal on one end, just to get super-conservative on the other. In the brief time that I used Clojure, I also thought that the contrast between immutability and dynamic typing was very strange. Ultimately, I think it makes more sense than having the entire language be highly dynamic (or highly static). I think Clojure's choice is not inconsistency, but that there is a kind of budget…

Maybe constraints rather than craziness? Constraints tailor a language, make it fitter for one purpose or another. But you have a limited constraint budget - overspend and everything is difficult.

As an old boss of mine (hi Paul Earwicker) used to say - "flexibility is just design decisions you haven't taken yet."

Re: Things Java Programmers can learn from Clojure

#17
post #11

I think that the article's defense of immutability is a bit poor. Making a date mutable means that it won't always reference the same point in time: yeah, a birthday will remain constant, but an appointment may not; the same goes for a lot of types. That's why C and C++ gives us the "const" keyword: the same object can now be used as mutable or immutable, depending on circumstances. The other points, especially the s…

[deleted]

Re: Things Java Programmers can learn from Clojure

#18
post #9

Why these things in stay in books and blogs and never make their way into Java web apps: 1. Use immutable values: Models used in client server communication need to follow Java Bean spec which is like the exact antagonistic concept to immutability. Service methods that implement business logic are stateless. As objects are not shared across threads, nobody feels the need for immutability. The most popular frameworks…

> 2. Do no work in the constructor

> Are constructors still used? All services are wired using dependency injection. Models are either DTOs or Hibernate POJOs - both dumb and anyways don't do any work.

Guice encourages constructor injection.

> 3. Program to small interfaces:

> Interfaces are dictated by functionality they provide and not size. They can have hundreds of methods. This is how it looks: DocumentService - put every document related method in here, FinancialInstrumentService - put every instrument related method in here

Surely, by the point you reach hundreds of methods, you can refactor your service into several different, smaller services.

Re: Things Java Programmers can learn from Clojure

#19
Re >2. Do no work in the constructor

The author doesn't propose a solution here, so I'm worried he's thrown out the baby with the bath water. Yes, it's true that you should have no File IO in a constructor when it violates the SRP. At the same time (and as the author notes), it's very convenient to have Foo.fromFile(String path) or similar.

Here's what I think the compromise looks like:

   public static OptimizedPage fromFile(String path) throws IOException {
      return OptimizedPage.from(path, FileReader.readFile(path));
   }
Which seems like having your cake and eating it too.

Or to put it another way: that File IO needs to happen either way -- forcing the caller do write:

   OptimizedPage foo = OptimizedPage.from(path, FileReader.readFile(path));
whenever they mean

   OptimizedPage foo = OptimizedPage.fromFile(path);
Is a subtle violation of DRY.

Re: Things Java Programmers can learn from Clojure

#20
post #3
post #2

If Java programmers would only apply the concept of immutability the world be such a better place... Every time I log from within a setter to see who's calling this and when, a little fairy falls from the sky.

I have hacked Haskell just to be able to see what goes on inside a particular method chain.

Do you mean you have trouble with seeing what's going on inside a long function composition? I wrote a cool function to examine it with almost no code changes:

  module TraceCompose where

  import Debug.Trace

  -- | Trace a value, resulting in the value itself
  idTrace :: Show a => a -> a
  idTrace x = trace (show x) x

  traceCompose :: (Show a, Show b, Show c) =>
    (b -> c) -> (a -> b) -> a -> c
  traceCompose f g = h f . h g . h id
    where h f x = idTrace (f $ seq x x)

  -- Replace "normal" function composition using traceCompose.
  test = (+1) . (*10) $ 4
    where (.) = traceCompose
When you run "test", it will print:

4 40 41

(i.e., the outputs of each function at each point in the composition in order of execution.)

Post reply on HN