Live data from Hacker News

Things Java Programmers can learn from Clojure

lispcast.com

51–58 of 58 posts

Re: Things Java Programmers can learn from Clojure

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

You are thinking about both dates and appointments the wrong way. Dates never change, they are fixed points in time. A date is not an appointment; an appointment has a date associated with it, and many other things. Appointments do not change either: they are canceled and rescheduled (which means making a new appointment).

The problem with C and C++ having the const keyword is that it is overly restrictive and is not flexible enough. What you are trying to express with const is that the value of an object before a computation is equivalent to its value after the computation, under some definition of equivalence. What const actually says is that the object will not change at all. C++ tries to mitigate this with mutable, but this is too rigid: the same things are mutable or immutable regardless of the context.

What we really need is what you see in specification languages: the ability to declare precisely how a value is modified by an operation. Maybe I have an object with a stream member, and I want to say that nothing will be written to the stream without saying that the stream will not flush its buffer for one operation, whereas in another operation I want to ensure that the buffer will not be flushed.

Re: Things Java Programmers can learn from Clojure

#52
post #15

Earlier quoted context omitted.

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 rea…

> this makes it possible to have many data access/manipulation functions that work on all objects. This is not actually true. Add proper type inference and structural typing, and it's perfectly possible to have all those generic data manipulation functions while also having strong static typing.

How would you write a general function that prints out the values of all fields of any object (without reflection)?

Re: Things Java Programmers can learn from Clojure

#53
post #42

Earlier quoted context omitted.

> 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. This doesn't strike me as true. In a statically-typed language like C# or Java I can ask objects (and in C#, primitives) what they are all day long. Could you expand what you mean a bit? (I also don't find Java particularly onerous regarding its lack of…

"In a statically-typed language like C# or Java I can ask objects (and in C#, primitives) what they are all day long." Which shows that Java and C# are a hybrid of static and dynamic features. Using reflection and introspection to invoke behavior at run time is dynamic-language behavior. More strongly typed languages such as Haskell won't allow you to do this, as far as I know.

>More strongly typed languages such as Haskell won't allow you to do this, as far as I know.

Haskell has Data.Typeable. It'll let you reify some types for run-time reflection.

Re: Things Java Programmers can learn from Clojure

#54
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 it's possible the error wasn't caught till it was in production.

Statically typed languages have plenty of errors that aren't caught until production. If you're really serious about compile-time guarantees, you'll want to use something like Haskell, Agda or Coq (in ascending order of extreme guarantees).

Of course, even formal verification won't protect you from an incorrect specification of your program.

Re: Things Java Programmers can learn from Clojure

#55
post #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…

Not the author, but I'd say he's referring to two Clojure features that make programming with concurrency so nice, specifically STM (Software Transactional Memory) and immutability by default. STM is much better (IMO) approach to concurrency than locking, but it's really only viable (as far as I know) in a language like Clojure where values are immutable by default.

The great thing about STM is that it's easily composable, while locking isn't.

Re: Things Java Programmers can learn from Clojure

#56
post #52

Earlier quoted context omitted.

> this makes it possible to have many data access/manipulation functions that work on all objects. This is not actually true. Add proper type inference and structural typing, and it's perfectly possible to have all those generic data manipulation functions while also having strong static typing.

How would you write a general function that prints out the values of all fields of any object (without reflection)?

http://www.haskell.org/haskellwiki/Template_Haskell

Re: Things Java Programmers can learn from Clojure

#57
post #55
post #36

Earlier quoted context omitted.

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…

Not the author, but I'd say he's referring to two Clojure features that make programming with concurrency so nice, specifically STM (Software Transactional Memory) and immutability by default. STM is much better (IMO) approach to concurrency than locking, but it's really only viable (as far as I know) in a language like Clojure where values are immutable by default. The great thing about STM is that it's easily compo…

It can be done at the page level in an OS if you want. It's not efficient, but then it hasn't been shown to be that efficient in a controlled functional language yet either. Locking still wins on clock cycles, unfortunately.

Re: Things Java Programmers can learn from Clojure

#58
post #52

Earlier quoted context omitted.

How would you write a general function that prints out the values of all fields of any object (without reflection)?

http://www.haskell.org/haskellwiki/Template_Haskell

I'm not quite sure, but I don't think this has anything to do with structural typing.
Post reply on HN