
Python vs Clojure - fogus
http://blog.bestinclass.dk/index.php/2009/10/python-vs-clojure-evolving/
======
req2
As with most language comparisons, the author is clearly established on one
side of the fence and unwilling to investigate in any meaningful sense.

He begins with a somewhat spurious statement on how code must be arranged,
continues with a complete misunderstanding of what most people mean by scope,
and then accuses Python of innumerable memory leaks and associated bugs before
he even gets through his first set of comparisons. He claims Python
dictionaries abuse the term 'immutable', but they most decidedly never make
any such claim. You might learn something about Clojure, but take everything
he says about Python with a grain of salt.

(Anyone who is interested in concurrent Python should check out
multiprocessing, not threading.)

------
johnfn
What bugs me about this article is that the solutions he takes for project
euler are taken from a website which tries to make Python into a functional
language and are needlessly verbose. For instance, the normal way to solve
PE#1 is:

print sum([x for x in range(1001) if x%3==0 and x%5==0)]

Quite a bit shorter than the clojure solution.

Further, their "isPalindrome" function involves a "digits_from_num" call, and
is almost 10 lines in total. You could shorten that to one if you check pal ==
pal[::-1].

Essentially, the guy copied code from a website which wasn't really trying to
show off how succinct python could be.

~~~
jongraehl
TypeError: 'int' object is unsubscriptable

You have to use str(pal) first, I guess.

Your core point is right, though; his clojure uses number->string + reverse,
and the Python can too.

------
jacquesm
The author seems to be strongly biased against python.

I'm no great fan of some of pythons choices but I think if you find x things
wrong with python and 0 wrong with clojure that that is fairly indicative that
this is not a balanced review.

Which is a pity.

~~~
gaius
Not only that, he's wrong - Python is sensitive to _indentation_ , not
whitespace. As long as your block is at the right depth, you can have as much
whitespace as you want. I regularly format code so similar things line up.
This is perfectly valid Python:

    
    
        def foo():
            longvariable = 1
            x            = 2
    
    

Also on the subject of lambdas, this is also valid:

    
    
        def foo():
           def bar(x):
               return x + 5
    
            print bar(5)
    
    

With a nice clean syntax for nested functions, lack of multi line lambdas is
much less of an issue.

~~~
jacquesm
Interesting how your variable example is pretty much straight against the
python styleguide:

<http://www.python.org/dev/peps/pep-0008/>

I'd do it just like you do though.

I find it visually harder to fish those equals signs out of the 'noise'
otherwise.

~~~
gaius
In the wild, you're more likely to find Python that looks like:

    
    
        longvariable, x = 1, 2
    

However this won't work:

    
    
        longvariable, x = 1, foo(longvariable)
    

So I like to keep things uniform regardless of the rvalue. Also violating the
style guide, I like

    
    
        longvariable = "hello" # some description of longvariable
        x            = 1       # some descrption of x

------
clemesha
Every time I hear criticism of Python's whitespace (indentation), I am
reminded once again of how much I appreciate and enjoy it.

~~~
jacquesm
To me it's a mixed bag. It's like a 'price of admission', if you've been
conditioned a life long to look for matching braces (or at least begin, end
pairs), and if even languages that are strictly speaking markup languages seem
to feel the need for delimiting the end of a block in some way you alienate a
large number of people before they've even written a single line.

Compound that with the difficulty of passing code snippets using various media
and it is easy to see why so many people argue against this.

You can get used to it, sure. But that's not a very strong argument. I think
there would have been ways to get out of this.

Especially when programming using tabs you'd better be very careful not to hit
a delete by accident while walking near the end of a block of code. That can
really mess you up.

edit: also, for that reason alone any discussion about the relative merits of
python vs something else first has to get pas the 45% where we talk about the
whitespace. And some people will go to extreme lengths to prove its 'goodness'
even when clearly it is not _only_ good.

Being objective about something you like is very very hard.

~~~
brodie
Increased readability and code clarity are well worth the price of admission.

~~~
jacquesm
Readability is a subjective thing.

I find C dead easy to read, that's because I've read lots and lots of it. Any
other language is harder for me.

edit: on another note, in a delimited language the indentation can be created
fully automatic, in python it can not, placing most of the burden of making
sure the indentation is correct on the human.

This lack of 'redundancy' has bitten me several times already.

~~~
brodie
Right, it is subjective, but requiring indentation imposes a higher baseline
level of readability: what you see is what you get.

This is important when you're working with more than just your own code. It's
like a forced style guideline, and it gets even better when everyone conforms
to Python's other optional style guidelines. It reduces friction.

~~~
jacquesm
> It reduces friction.

Between python programmers, yes.

But it increases friction between those that are 'in' and those that are not
(yet). And even some of those that are 'in' have their reservations.

I completely understand the reasoning behind it, but the number of times that
I've run in to practical problems because of having some kind of delimiter is
0, the number of times that I've run into some kind of trouble with python
because of not having delimiters is starting to add up.

This may be a factor of inexperience, time will tell. But it is definitely a
new 'source' of bugs, and sources of bugs are in my opinion things that you
avoid like the plague when designing a programming language.

Even in 'C' (or C++, or anything that derived it's syntax from those
languages) I always found it both wrong and inconsistent to be able to say:

    
    
        if (a) 
            b++;
    

To me that's asking for misery, you could remove that whole if(a) line and the
whole thing would remain syntactically correct.

I think of the { } just like I think of guardrails on the highway. They don't
make stuff prettier, sometimes you can't look across, but they certainly keep
you safer.

~~~
jbellis
> Between python programmers, yes.

Optimizing for any other audience would be ... strange, especially at this
point in python's lifecycle.

~~~
jacquesm
True, it is absolutely beyond that. But I think that it would have helped
significantly in an earlier stage, I even think that PHP would have been run
into the ground.

In the long run that may still happen, there definitely is shift happening.

------
bretthoerner
I posted this there, but I feel more people prefer to read comments here.

\---

First, I love both Python and Clojure, and completely agree that Clojure is
more functional and aimed towards concurrency (this was its goal, after all).
But I feel like you're doing Python wrong here.

> I think this should make a Pythonist a little jealous

No, I think you misunderstood the whitespace rules for Python. First, it isn't
set to "4 spaces", it just has to be uniform. You could use 8 tabs if you
wanted, or 2 spaces, or 7 spaces. Also, inside of data structures, strings,
function calls, etc you can go whitespace crazy. This is valid Python:

    
    
        users = (# name ,      id,    age,     phone
                 ("Frank",     200,    22,     "555-1234"),
                 ("Johnathan", 201,    24,     "555-3213"),
                 ("Peter ",    202,   101,     "555-2312"))
    

> The last print statement outputs "10" which is surprising to me, since y has
> never been declared in that given scope.

But it _wasn't_ declared in that scope, there is no scope for 'if'. It may not
be what you're used to but you can't blame Python for your assumption of what
should have it's own scope or not.

> To resolve it you have to manually call 'del y'

What do you mean to resolve it? Why are you deleting the reference at all? You
very rarely see 'del' in real Python code.

> but I can't count the number of C app's that have suffered from memory-leaks
> and what not, based on the lack of automated garbage collection

What does that have to do with Python? It is reference counted, those values
will be deleted when they go out of all scopes, just like in Clojure.

> But this is very different from Clojures concept where immutable means: 'x'
> never changes.

That isn't what it means in Clojure at all.

    
    
        user=> (def x 1)
        #'user/x
        user=> x
        1
        user=> (def x 5)
        #'user/x
        user=> x
        5
    

I just changed 'x'. What immutability means is that the _value_ 'x' points to
does not change. And that's _exactly_ what it means in Python, too, but
dictionaries _are_ mutable (and this is documented). For example, strings in
Python are immutable, just as in Clojure. If two things reference the same
string and one "changes" it only means that it references a wholly new string.

> Guido is not preparing to transition into modern programming

That's a little extreme. Concurrent programming is valuable, but there will
_also_ be many programs that fit single process / thread models very well
until the end of time.

~~~
dreish
I agree for the most part, but incidentally you would never (def x 1) and then
(def x 5) in a running program -- you would use an atom, ref, or var instead.
Redefinition of a symbol is permitted so you don't have to quit and restart
your REPL every time you rewrite a function.

A more meaningful objection is that you can shadow a local with a different
local in Clojure, like this:

    
    
      (let [a (some-calculation)
            b (something-else)
            a (some-function-of a b)]
        a)
    

which is essentially what is being done in the Python code.

I don't think there are many strong arguments to make in favor of Clojure over
Python other than concurrency and macros, and maybe the immutable hashes.

~~~
bretthoerner
> you would never (def x 1) and then (def x 5) in a running program

Right, I understand. It was the way the author stated 'x never changes' that
made me believe he doesn't understand the difference between binding a name
and changing a _value_.

------
icey
I like Clojure, but this whole article strikes me as thinly veiled language
trolling. It's not a comparison, it's a long blog posting talking about how
Lau thinks Clojure is better than Python.

~~~
jacquesm
What's veiled about it ?

~~~
icey
I am willing to give him some benefit of the doubt because I've had
interactions with the author in #clojure on irc in the past and I don't think
he's got bad intentions. He just has strong opinions about things.

~~~
jacquesm
I'm cool with that, but if you have strong opinions pro one language and
contra another, and _lots_ of experience in one language and almost none in
the other (even I can tell that, and I'm pretty much a newbie to both python
_and_ clojure) then you shouldn't make comparisons.

It is a disservice to clojure as well, because it makes people think that
clojure proponents are thinking about clojure in terms of religious dogma,
instead of rationality.

------
megaman821
This comparison isn't very good.

He is basically dinging Python for setting up some pretty basic functions like
ireduce(). Wouldn't you do the same in Clojure if something didn't exist? If
its just about have short code, I would suggest the line 'import numpy'.

Also for the concurrency parts, if you are talking strictly about the
languages and not their implementation, why not compare Jython to Clojure?

~~~
jacquesm
Because then the comparison would come out less in favour of clojure ?

Because the author isn't aware of jython ?

It could be anything really, but if you plan on putting down a language I
guess you're not going to go out of your way to create a level playingfield.

Let's compare interpreted basic with compiled C for an encore.

------
pHezy
It seems more like a "I suck at python and I try to be cool using clojure"
than any other things. Oh, and btw, palindrome: x==x[::-1] or reversed

------
kljensen
Clojure seems super cool. But, 99% of my tasks \- are simple & easily
accomplished in Python; and \- do not require any concurrency.

It seems like Clojure would be super useful in number crunching like
scientific computing, etc.

------
alrex021
Who is up-voting this?

If you read this article you can clearly see the lack of knowledge the author
holds in Python language itself. If you gonna do a ... VS ... you better know
both sides pretty damn well otherwise it leads to being a somewhat worthless
comparison IMHO.

------
japherwocky
tl;dr: author without much python experience writes a tedious article in
Clojure's favor.

------
tsally
Off topic, but anyone have any idea what that color scheme is?

~~~
mqt
It's "charcoal black" from the emacs color theme package.

[http://gnuemacscolorthemetest.googlecode.com/svn/html/charco...](http://gnuemacscolorthemetest.googlecode.com/svn/html/charcoal-
black-c.html)

------
d0mine
There is a bug in the fibonacci example: it sums odd numbers instead of even.

    
    
      from itertools import takewhile
      
      def ifibonacci(a=1, b=1):
          while True:
              yield a
              a, b = b, a + b
      
      candidates = takewhile(lambda n: n < 4000000, ifibonacci())        
      print sum(n for n in candidates if n % 2 == 0)

