Live data from Hacker News

Things Java Programmers can learn from Clojure

lispcast.com

31–40 of 58 posts

Re: Things Java Programmers can learn from Clojure

#31
Good article.

Writing immutable software is hard, when the language doesn't provide constructs for it. It will require some discipline. There are some good frameworks/tools for the JVM for Java programmers for this (the whole AKKA package is a good place to start).

I would highly recommend Venkat Subramaniam's book for Java programmers: "..Concurrency on JVM.."- http://pragprog.com/book/vspcon/programming-concurrency-on-t...

Re: Things Java Programmers can learn from Clojure

#32
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?)

Think about what immutability means. It means that there's no assignment statement. If there's no assignment statement, there can't be any side effects. If there are no side effects, you can't race conditions or concurrent update problems. You can't have resource leaks. You can't have order dependencies.

Does Clojure guarantee all these things? Not entirely; because Clojure allows you to invoke the java stack, which is decidedly not immutable; and because clojure provides mechanisms for changing state; albeit with significant discipline imposed.

The end result is that clojure is _much_ safer to use in complex and multi-threaded systems, and is likely much, _much_ safer in extreme multi-core applications.

Re: Things Java Programmers can learn from Clojure

#33
post #25
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…

Huh? If I do this: (defn to-rubles [x] (* x 1.2)) (to-rubles (java.util.Date.)) I get an error: ClassCastException java.util.Date cannot be cast to java.lang.Number How is this unreasonable?

The compiler didn't tell you it was broken. You had to run the program first.

Which means it's possible the error wasn't caught till it was in production.

Which means it's possible that a customer discovered a bug that a compiler could have discovered if you had used a language with a compiler capable of compile time static typing.

Re: Things Java Programmers can learn from Clojure

#34
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?)

BTW, immutability has nothing to do with encapsulation. Encapsulation is the hiding, or access restriction, of data structures from "foreign" functions. Those foreign functions may only manipulate the encapsulated data through a prescribed set of functions.

We achieve this in clojure through clojure's lovely typing mechanism which allows you to declare types that have publicly known functions without any data declarations; and private implementations of those functions that know the data they are manipulating.

One last note. C was much more encapsulated than C++, Java, or C# because in C you would declare your functions in a .h file, and your variables in a .c file. No other .c file could see your variables, so they _had_ to use your functions. The public/private keywords were added to C++, and then to Java and C# because the act of putting variable and function declarations in the same source file broke encapsulation, and we needed a way to re-assert it. That reassertion was only partially effective.

The bottom line is that all the C based OO languages are _less_ encapsulated than C.

Re: Things Java Programmers can learn from Clojure

#35
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…

The date of an appointment might change, but the date itself does not. Dates are values that refer to a fixed period of time; the meaning of "March 7th 2013" won't change if I move an appointment.

The correct way to handle an appointment is to have a reference to an immutable date. When you want to change the date the appointment is on, you change the reference to a different date, not the date itself.

Re: Things Java Programmers can learn from Clojure

#36

OK but these things are not enough. I'm a long time Java dev and all these were known in c.l.j.p. and IRC since a very long time. I was doing precisely that, even using the "functional Java" libs when they came out and doing even more radical things... And I can tell you that even when doing that switching to Clojure is pure joy. Because even when doing what TFA talks about, this still doesn't solve lots of very nast…

What do you mean by the totally outdated approach to concurrency? I'm also a longtime Java dev who's embraced these values for a long time, and I generally thought of using ExecutorServices and Callables as a very functional approach to concurrent programming. If you're referring to manually starting threads and using synchronized monitors to ensure thread-safety, then I agree, but java.util.concurrent really doesn't encourage that approach.

Re: Things Java Programmers can learn from Clojure

#37
post #23
post #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 fr…

So yes - static factory methods - or, if it gets complex enough, a distinct factory object - are the right place to do work that would otherwise need to be done in the constructor. Use package-private constructors to enforce that people don't bypass them.

Those are factory methods because I think

   OptimizedPage.fromFile(pathName);
reads cleaner than

   new OptimizedPage(pathName);
Do you think there's a real difference (besides readability) for preferring a factory method to a constructor in this context?

Re: Things Java Programmers can learn from Clojure

#38
post #26

What bothers me just a wee bit in section 1 of his example is that Date is more or less a simple container class for data - one that could be implemented as a HashMap. It is easy to make classes like Date immutable, but that does not help with a lot of problems. Date is super-easy to test, only state, no logic. Similarly, static methods are easy to test. The real pain in Java is when a class has both state and logic…

Not necessarily - take joda-time's DateTime class as an example, which contains plenty of methods for changing fields in the date, but all of which return new DateTime instances to caller. DateTime itself is immutable.

Re: Things Java Programmers can learn from Clojure

#39
post #33
post #25

Earlier quoted context omitted.

Huh? If I do this: (defn to-rubles [x] (* x 1.2)) (to-rubles (java.util.Date.)) I get an error: ClassCastException java.util.Date cannot be cast to java.lang.Number How is this unreasonable?

The compiler didn't tell you it was broken. You had to run the program first. Which means it's possible the error wasn't caught till it was in production. Which means it's possible that a customer discovered a bug that a compiler could have discovered if you had used a language with a compiler capable of compile time static typing.

[deleted]

Re: Things Java Programmers can learn from Clojure

#40
post #33
post #25

Earlier quoted context omitted.

Huh? If I do this: (defn to-rubles [x] (* x 1.2)) (to-rubles (java.util.Date.)) I get an error: ClassCastException java.util.Date cannot be cast to java.lang.Number How is this unreasonable?

The compiler didn't tell you it was broken. You had to run the program first. Which means it's possible the error wasn't caught till it was in production. Which means it's possible that a customer discovered a bug that a compiler could have discovered if you had used a language with a compiler capable of compile time static typing.

Which means you really, really, really need a good automated unit test suite. When you switch to a dynamically-typed language, you trade compile-time type guarantees for the ability to ask primitives and objects what type they are at runtime. So, you have to incorporate those questions into your unit tests. Especially when you are doing casting--which of course you should do only when there isn't a better option.

As an aside, static typing without type inference (a la Java) is just a pain. The compiler is just smart enough to enforce typing, but not smart enough to figure out what type anything is unless you explicitly tell it. This puts an extra burden on the programmer.

Fortunately Scala has type inference, so that's an option if you want to use a statically typed functional language on the JVM.

Post reply on HN