e.g.:
http://www.kreuzwerker.de/en/blog/posts/why-clojure-rocks-2/
e.g.:
http://www.kreuzwerker.de/en/blog/posts/why-clojure-rocks-2/
Clojure devs are willing to compromise a bit to allow a good integration within the JVM and other implementations, thus allowing some shops to buy into Clojure.
Whereas many in the Common Lisp community will not, no matter what.
So, Rich has been thinking of the practicalities of Java interop for a long time.
Common Lisp on the JVM: http://abcl.org/
Common Lisp/Java bridge: http://foil.sourceforge.net/
Also the direct use of Javas API instead of more Lispy ones everywhere.
Perhaps a nitpick, but sometimes nomenclature is important. Clojure (like all Lisps) is an imperative programming language. "Imperative" languages are contrasted with "declarative" languages[1]. Where does functional fit in and what is the name for "non-functional"? Well, that's not clear, as "functional" (in the PL sense) doesn't even have an agreed upon definition. Is Clojure "functional", then? Well, it's certainly not pure like Haskell is (and it has explicit loops etc.), but it does encourage more uses of function composition than, say, Java, it's more declarative, and it also isn't object-oriented, but that doesn't make it not imperative. Actually, I think even Haskell still qualifies as imperative.
But Clojure can certainly be contrasted with OO and procedural languages (even though at least one of its core abstractions -- protocols -- is borrowed from OO).
Haskell does not have a function that performs IO. For instance, `putStrLn "hello world"` returns an IO action, but it does not print anything to the screen.
In order to "perform IO" you have to name an IO action 'main'. Then the compiler understands that you want that action to take place in the Real World. But Haskell does not know about the Real World and so it cannot do IO.
This difference is important, otherwise there is a misunderstanding that Haskell is just "minimizing IO". It's not - there's no IO.
I would say a language which relies on functional composition as its primary abstraction is "functional." Immutable data is a side effect of that.
[1] http://existentialtype.wordpress.com/2013/07/18/what-if-anyt...
Wikipedia, and probably everybody, defines truly functional programming languages (which includes Clojure and the other Lisps) to be declarative, not imperative. [1]
This is wrong. I don't know how to say this... Lisps do usually support functional programming paradigms, but most Lisps are indeed anything but functional (in the ML sense).
That was then and this is now. Today, functional programming means side-effect-free with a strong type system, and efficient use of higher-order abstractions over functions, including things like typeclasses to define entire morphisms given a few functions which establish relationships between objects. Lisp doesn't really support this effectively. Arguably, with concepts C++14 is more functional than Lisp.
Functional programming has always meant the style or paradigm of programming that prefers side-effect-free declarative code that can be modelled in the substitution model; type systems have always been (and remain) orthogonal concerns. A functional language is one that supports the functional paradigm, but it has never been most commonly used for languages that exclusively support that paradigm. Pure functional code is the term that has been used for code that is exclusively in that style, and pure functional language is the term that is generally used for a language that has exclusive support for that style.
It's also not really historically accurate. People were referring to languages based on the untyped lambda calculus as "functional" before things like Hindley-Milner appeared (in the 70s). Were they (and I'm talking about PL researchers) all speaking incorrectly?
OTOH, that doesn't mean it is impossible to have imperative code in Lisp.
How so?
This is different from other languages in that saying "what to print" is an actual command (hence, imperative) and not a value, as it is in Haskell (things that "will be commands when the program is run" are values in Haskell, as numbers and strings are).
This is a rather meaningless distinction -- indeed, you can say the same thing about any other language on the planet. Programs written in C, Python, Ruby, ML, R, and Brainfuck only have side effects when you execute them. Obviously a C program just sitting on your hard drive unexecuted doesn't have any side effects.
Compare:
Ruby:
will_print = puts "hello world" # it already print to the screen! and will_print does not have any meaningful value -- indeed it's nil
Haskell (demonstrated on the repl, which runs inside the IO monad):
let willPrint = putStrLn "hello world" -- nothing gets printed!
willPrint -- now the string gets printed (only because the repl is inside the IO monad which promises to execute action values)
Haskell (not in the repl):
willPrint = putStrLn "hello world" -- nothing gets printed!
willPrint -- this returns the same that 'putStrLn "hello world"' returns - an action value that, when run inside the IO monad, will execute its actions - so this still doesn't print anything, and we can pass willPrint around without side-effects, and compose values with willPrint
main = willPrint -- now the compiler will make good on its promise to execute any action value that is named 'main', and "hello world" will be printed to the screen.
The point of this is that you cannot print inside the Haskell language (nor do any other side-effect) - when you try to print you get this "action value" thing that you as a programmer cannot execute. Only the compiler can. So you can pass Ruby's equivalent of "puts 'hello world'" around, which you can't in Ruby.
So the distinction is quite clear.
> Programs written in C, Python, Ruby, ML, R, and Brainfuck only have side effects when you execute them.
They clearly don't. That's why when I write in Ruby:
puts "hello world"
Then the next line of code will be executed in a world where 'hello world' has already been printed to the screen.
Likewise, when in Ruby I write:
a = 5
a += 1
Then the next line of code will be executed in a world where a is 6.
So every line of code you write depends on the side-effects that came before it. Therefore, Ruby and most other languages have side-effects before code is executed. This is not the case in Haskell. Hence, no side-effects.
I don't, however, like the ecosystem surrounding it. I find Leiningen (while an excellent tool) far too heavy for the majority of my purposes. I much prefer other functional languages (e.g. OCaml, Haskell) that don't need such an intricate project structure.
With OCaml & Haskell, I can start with one source file in one directory and gradually build up to a more sophisticated layout as needed, rather than have a complicated layout imposed upon me by the project.
[1] http://clojuredocs.org/clojure_core/clojure.core/-%3E [2] http://clojuredocs.org/clojure_core/clojure.core/-%3E%3E
Yes, you can get started easily with Haskell - but then Cabal is such a complete piece of shit that people felt the need for a Haskell distribution with batteries included. And it is my feeling that you're mixing the cause and the effect here.
Now if by heavy, you mean the folders structure lein generates, then I disagree. Those folders actually keep the task of understanding any lein project easy.
If by heavy, you mean the JVM: You can compile the thing into a jar that runs on any jvm, or a js file using clojurescript. JVM, web browsers and Node.JS are very likable cross-platform layers, and I don't see why binary executable that are OS dependent compares.