Sonic Soul
Sonic Soul

Reputation: 24899

clojure vs c# language

I am still trying to understand the clear benefits of clojure. I understand that it is a dynamic, [almost] purely functional language that lends itself well to unit testing, concurrency and rapid development.

I was watching this presentation by its founder Rich Hickey.

Around the 25th minute mark, you can see a lot of wonderful ways in which clojure makes programming easy by ability to define lists, and vectors dynamically:

( 123) [123]

ability to use those dynamically defined vectors as functions

([ 123] 0)

ability to call functions on newly defined strings

(.ToUpperCase "foo")

so as Rich puts it, "syntax for the literals is the syntax for the language".. beautiful.

but isn't it possible to do this style of programming in .net 4.0? (albeit more chatty)

(new[] {1,2,3})[0]
"foo".ToUpper()

etc.. .net could also be used to program in a functional way (although it is not enforced)

these are trivial examples, but seems like this is the basis of clojure. What are some features that set clojure more apart, and make it a better choice in some scenarios?

Upvotes: 17

Views: 8807

Answers (4)

mikera
mikera

Reputation: 106351

I personally think that Clojure's syntax is very effective, concise and even beautiful once you get the hang of it. However in my view that isn't the most compelling reason to select a language.

My personal reasons for preferring Clojure as my "general purpose development language of choice" after many years of Java and C# are:

  • Macro metaprogramming - Clojure is a Lisp and inherits the Lisp family "Code is Data" motto. Because the language itself is written in a form that is itself a data structure within the language (this is called Homoiconicity), it's trivial to write code that generates code in whatever form you choose . You basically never need to worry about "Design Patterns" ever again- if there's something missing in the language that you want to use, you just extend the language with a macro and move on.....

  • Dynamic by default - Clojure is a dynamic language by default, which means that it automatically "does the right thing" in a flexible way for most tasks. This has the effect of making you more productive. Examples are automatic overflow to BigInteger arithmetic, being able to put any object types you like in a collection, never needing to declare parameter types etc. At the same time, you can specify type information to improve performance if needed (by directly using primitives or providing type hints for example) - so you can get really fast performance when required.

  • Emphasis on functional programming with persistent, immutable data structures and lazy evaluation - in particular all the core Clojure library is designed to support this style of development by default. Once you get the hang of it (I admit it's not easy...) FP is exceptionally powerful. While you can emulate "FP-style" code in almost any language, you only really get the full advantages when it is a pervasive feature of the language (Clojure, Haskell, ML spring most obviously to mind)

  • Excellent multi-core concurrency. Thanks to a very novel STM system, I believe Clojure has the best concurrency story of any language at the moment (see this video for more elaboration by Rich Hickey himself)

  • Open source library ecosystem - I'm a big fan of open source and Clojure is very much an "open source" friendly language. The language itself and pretty much every library is open source, and if that isn't enough for you then it's trivial to call Java libraries. Given the breadth of the whole Java/JVM open source ecosystem, this means that pretty much anything you want to do is readily available in a library (a big advantage over most new languages!)

  • JVM interoperability - you may or not care about this, but personally it's an important feature for me to be able to integrate with libraries and tools in the Java/JVM universe. Clojure makes this very easy - Clojure objects are JVM objects under the hood and calling a Java method is usually as simple as (.someMethod someObject someParameter)

  • Interactive development at the REPL - typical Clojure development style is to interact with a running Clojure program at the REPL. You can redefine virtually anything on the fly without having to do a compile / build / test cycle. It's an amazingly productive way of working - I basically build a running program at the REPL and then copy the right commands into a source file to run in the future. Stupid example - I have a one-liner that is able to visualise various data structures from a running program in a chart using Incanter. I can immediately see in a visual way if something is going wrong and this alone has saved me weeks of debugging....

  • Community - I personally like the Clojure community, which is small but fast-growing. It's got the right mix of pragmatism (i.e. getting things done), helpfulness and caring about doing things well which I think is important.

Upvotes: 23

mamboking
mamboking

Reputation: 4637

([1 2 3] 0) is not equivalent to (new[] {1,2,3})[0] because in clojure [1 2 3] can be passed to a function that takes any function that takes an int and returns a value. For example:

(defn do-something [mylist myfunc]
  (map myfunc mylist))

(do-something [0 2] [1 2 3])

=> (1 3)

This allows you to reuse do-something with any function that takes 1 arg and returns a value.

Upvotes: 7

mqp
mqp

Reputation: 71937

Clojure's primary conveniences over C# roughly ordered by level of convenience, with the hugest improvements at the top:

  • More pleasant syntax for literal collections, as you observed. Primarily for literal hash maps, which are sufficiently ugly in C# (you need to write out the generic type) that you wouldn't define one inline. C#'s new Dictionary<string, int> { { "Joe", 6" }, { "Steve", 18" } } becomes {"joe" 6, "steve" 18}.

  • Powerful destructuring for function arguments that works well with aforementioned collection literal syntax.

  • Keywords make it easy to refer to things symbolically without having to take time out to define enums.

  • The core library has many useful built-ins for functional programming which LINQ lacks.

  • The core library has really nice immutable vectors and maps that work nicely together with aforementioned built-ins.

  • Thanks to the core data structures being immutable, the language has really convenient STM transactions for managing concurrency that just work without a lot of extra effort.

  • Metadata is extremely convenient; it allows you to "tack on" information that rides along with other data in a way that's much easier than e.g. defining a throwaway type representing original-data-plus-other-stuff.

  • Often you want to use an abstraction with types that you don't control; Clojure protocols make it easy to do so, whereas it's almost impossible in C# since you can't extend someone else's type to implement an interface. (You can't even do trivial things like make an INumeric interface.)

  • Macros are easier to use and more powerful than C# expression trees for extending the language.

You can find more information about most of the stuff mentioned above at Clojure.org.

Upvotes: 11

Jeff Foster
Jeff Foster

Reputation: 44696

The Clojure rationale gives much better details than I can, but my reasons for learning Clojure were:

  • Macros - Code is data, data is code (homoiconic). Macros give you the ability to write new code at compile time and that can allow you to add new syntax to the language.
  • Software Transactional Memory - STM allows you to write code without worrying about low level concurrency details. In a software transaction, the Clojure runtime detects whether two transactions are accessing the same data and backs one off and retries.
  • Integration with existing VM - By being able to use Java, Clojure automatically has access to millions of lines of well tested code.

Upvotes: 11

Related Questions