Hacker News new | past | comments | ask | show | jobs | submit login

Not really. There may be some larger idioms and concepts that are more expressive than scala, but simpler language? A case in point:

scala

   if (x > 0) ...
clojure

   if (> x 0) ...
The clojure syntax here is a bit absurd, IMHO.



It's only "absurd" if you're quite new to programming and math.

In fact, it has been with us in programming for over 6 decades, and is a classic mathematical syntax called Polish Notation ( http://en.wikipedia.org/wiki/Polish_notation ).

For one, it makes all method invocations the same: the method name followed by the arguments. Here the method is operator plus (addition).


I'm not sure the precedence of syntax makes it simpler, though. In the end, it's just syntax, but the primary posit that's been put forth is that Clojure is simpler to use than languages such as Scala. And Polish notation, while existent, is not the common form of expression in mathematics.

I find it "absurd" in that it requires adaptation to a form of syntax that's more niche than anything. I don't see that adding to the argument of simplicity in this particular scenario.


And hence the productivity self-selection bias...

I'd guess that, for you, Clojure _wouldn't_ have the same kind of efficiency that some others see. Lisp, in general, appeals to people who think "A is really the same thing as B. Cool!" They see treating all functions the same as a really worthwhile thing, in and of itself. Others, such as yourself, aren't really excited by that. It's a style thing.

Fanatical generalization can be a really effective trait in some circumstances. A small team of generalizers working on a reasonably-defined problem (such as a re-implementation) can turn out amazingly simple and compact code, since they tend to factor out common things.

On the other hand, a generalizer might not be as tactically-focused as someone else. A tactical person might be more inclined to make a surgical change, whereas a generalizer might wind up with a "toolbox enhancement".

A tactical person is going to get more mileage out of tools that already take care of a lot of common cases, and do them in common ways. A generalizer will do better with tools that are more "meta".


All this from an assertion about the simplicity of Clojure syntax?

Because this is just syntax, "A 'looks' the same as B. Cool!" is a more definitive statement. After all, it's just getting compiled/translated to JVM byte code anyway.

Efficiency is an entirely different conversation and tangential to the one we've been having regarding syntax and simplicity. Nobody has asked to this point, but I have no problem with Clojure's syntax structure. I find it very compact, I like the explicitness of parentheses, and like that it works in the JVM. (Disclaimer: I've not deployed any Clojure-based code in a production environment, so my own experience is limited.)

I also find that it's syntax has its own quirks, much like every other language. And while some things 'look' the same in Clojure, other things don't -- and that's perfectly ok. It's relatively consistent enough that the syntax logically points to its idioms.

But I stand by my original comment: it's only as simple as the observer makes it out to be. I don't find the syntax of Clojure more or less simple than many other languages.


The fact that <, >, +, - and other operators are just functions brings alot of benefits.

- They are variadic functions, they work on a range of inputs. - Their names are valid identifiers, which allows for function names like list->vector - Precense is fairly self-evident. 2 * 2 / 5 - 1 vs (- (* 2 (/ 2 5)) 1). You could add parenthesees to the first, and most would, Lisp just forces you to. - They are consistent, a function is the first element of a list, no matter what - Closely related to the above point, they make writing macroes easier. Imagine if macroes had to take infix operators into account. Certain macroes would have to scan the syntax they receive for the presense of operators, or you would have to create special macroes for operators... - You would need special syntax for passing operators as values to other functions. ((dummy) < 5) ;; What should happen here if dummy returns another function instead of something orderable?


It's only absurd since we're so used to assuming that (some) math functions are special and deserve special notation. The notation for almost every other function you're going to use is f(x,0), why should the function '>' get a different notation?

I agree that it is uncommon and take getting used to, but it does have the advantage of being consistent, and consistency and lack of special cases is a part of simplicity.


> why should the function '>' get a different notation?

I think that the concept of standards is worthy of consideration. While '>' is an operator in scala and other languages, it's also an operator in basic mathematics. And in basic math, we're taught "if x is greater than zero" using the notation of "if x > 0" (parentheses notwithstanding.)

It's only consistent in terms of how clojure presents it, but it's inconsistent with treatment elsewhere. Consistency does go to simplicity, but if it takes some "getting used to", it can't be all that simple.


I think consistency with math doesn't make "if x > 0" simpler than "> x 0". Makes it easier, as it's already ingrained in the memory, yes.

For example, how would you express the "between?" in infix notation? In Clojure we can use the same function - "(> 1 x 0)".

I do agree that Clojure way takes some getting used to.


Yes, agreed. Although, what's the point of simplicity if things aren't any easier?


They actually are easier once you learn the (simple) novelties. Simplicity makes the learning process shorter.


>It's only consistent in terms of how clojure presents it, but it's inconsistent with treatment elsewhere.

Well, engineers using scientific calculators handled polish notation (and reverse polish notation, like 3 4 + for 3 + 4) just fine for half a century or so...


check: (> x y z 0) vs: if( x > y && y > z && z > 0)

Now the next question is: where do I need that for? Just let it soak in for a while: it is surprising how your solutions change if your tool works differently.

I've been busy with Scala for some time now, but the OO aspect also dominates the FP part. And that OO part is huge: traditional classes, case classes, traits (which are occasionally used standalone) static functionality not in the class but factored out in an object, structural typing just to name some.

There are many aspects I like of Scala, but simplicity is not among them. In teams you will have to have strong communication if you do not want to limit yourself to a subset of the language ("no fp" for instance)


But then, Clojure can also do this for an arbitrary number of operands

    (< 1 2 3 4 5 6)
    ;; true
Any function can also take arguments from a list,

    (apply < (range 1000))
    ;; true
Prefix notation really comes into it's own when you start looking at multiple arity functions. Please don't confuse unfamiliarity with absurdity.


Those are great examples, and I agree -- the compactness far exceeds something like Scala.

Although I think I could create a function in Scala that permits the same thing, yes? Mostly the arbitrary operands or range reference imply recursion & iteration, which I believe I could implement easily. (Check me if I'm wrong here, I might be missing something.)

I wouldn't have suggested that, except that Clojure (as I understand it) also encourages that one can "expand" the language. I would see adding this capability as a Scala function in the same light.


And yet nobody has issues with foo(a, b)

Which is basically the same as (foo a b) except the ( if one identifier later.

I've often seen stuff like this in languages without operator overloading: a.add(b.multiply(c) d.subtract(5)) and nobody complains about that, but a lot of people are hung up about (add a (multiply b c) (subtract d 5)) which is almost the exact same thing. Of course, in Lisp-like languages, you would be able to redefine functions, s it would actually look like this: (+ a (* b c) (- d 5))

I don't get why people have such big complaints about syntax. Whatever you are used to is easier to read. Obviously! But its not hard and does not take long to get used to this.

So once you are used to it, Lisp is simpler because it has one single rule that is followed by every language construct: (function params) - in other languages you have all kinds of flow control statements with different rules (if, else if, while, for, switch.. all have different rules). Then theres function calls and method calls. Precedence. That's a lot to have to remember.


Forgive my terrible macroing but, if your really must, you can:

    (defmacro ord-compare [a ord b]
      `(if (or (= > ~ord) (= < ~ord)) (~ord ~a ~b) "Use > or < to compare."))
  
    (ord-compare 3 > 2)
Edit: there's also incanter.inflix, which will translate inflix notation into clojure like notation.

https://github.com/liebke/incanter/blob/e1235cf9ffa2e528823e...

Check out the tests for how to use it:

https://github.com/liebke/incanter/blob/aa71f1135c3beb7bf7a4...

A good example:

    ; $= translates inflix to prefix notation. 
    ($= 3 <= (5 * 2/7))  ;will give you false.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: