Road to Clojure Survey

481 views
Skip to first unread message

Kenneth Tilton

unread,
Feb 10, 2009, 2:30:04 AM2/10/09
to
In 25 words or less, why is Clojure better than Common Lisp?

In 100 words or less, why is Clojure better than Common Lisp?

Have you switched to Clojure? If so, from what?


Kaz Kylheku

unread,
Feb 10, 2009, 3:46:54 AM2/10/09
to
On 2009-02-10, Kenneth Tilton <kent...@gmail.com> wrote:
> In 25 words or less, why is Clojure better than Common Lisp?

It has more kinds of parentheses. And symbols have to prove themselves
worthy before they are interned.

> In 100 words or less, why is Clojure better than Common Lisp?

That constraint I can't deal with. I only ``do'' 25 words or less.

And anyway, in this world, by the time your ad execs throw together a monstrous
100 word sound bite, the competition has eaten your lunch.

> Have you switched to Clojure? If so, from what?

NewLisp, mostly. In fact, I switched from NewLisp to Clojure about six times
just today alone! Well, no four. One of those times I went to Scheme first,
then Clojure, and another time I was actually using Common Lisp and /thought/
it was Clojure, until I misspelled some names. The misspellings scrolled off
the screen, and so I didn't know what to unintern to get back to a clean state.
I ended up rebooting the machine.

Pascal J. Bourguignon

unread,
Feb 10, 2009, 5:31:27 AM2/10/09
to
Kaz Kylheku <kkyl...@gmail.com> writes:

> On 2009-02-10, Kenneth Tilton <kent...@gmail.com> wrote:
>> In 25 words or less, why is Clojure better than Common Lisp?
>
> It has more kinds of parentheses. And symbols have to prove themselves
> worthy before they are interned.

This is why it's worse.


>> In 100 words or less, why is Clojure better than Common Lisp?
>
> That constraint I can't deal with. I only ``do'' 25 words or less.

And 25 is not less than 100 anymore?


> And anyway, in this world, by the time your ad execs throw together a monstrous
> 100 word sound bite, the competition has eaten your lunch.


--
__Pascal Bourguignon__

glenn....@gmail.com

unread,
Feb 10, 2009, 6:14:30 AM2/10/09
to

I guess I've switched, from Common Lisp, mostly because I changed jobs
last November and I couldn't take my CL code base with me, so I was
able to examine Clojure from a fresh perspective.

I'm exploring Clojure for my simulation work. The biggest plus for me
in my domain is Clojure's concurrency model: immutable data
structures, agents, STM, and NO USER LOCKS!. This makes it very easy
to spread model calculations across cores without having to protect
against improper concurrent data sharing either with hard to develop/
debug locks or by "convention". Even though Clojure has no built-in
distributed support, it'll eventually get one and until then, it
appears that one can use any of the mechanisms available through the
JVM.

The second big thing for me is the Java interoperability, as my domain
needs access to lots of different math and there's lots of math
libraries for Java that are accessible through Clojure's very nice
Java interop facilities. Additionally, it's very easy to tell Clojure
what the types are of data items (like various CL declarations,
although easier to use) which speed things up. CL's numeric tower is
more featureful, but Clojure's is certainly adequate. There's no
native complex number support, although you can do that in the Java
layer. I haven't yet needed to use complex numbers in my work so
that's not a big deal for me but I have seen some postings of math
types who miss native complex numbers. There's no problem with
Clojure functions being the callbacks for Java code, as Clojure
functions implement all the right Java interfaces to make that work.

The HotSpot JVM seems speedy enough for me and it has a JIT so things
that run a while automatically speed up. For some micro benchmarks in
the areas that I care about, Clojure compares well with SBCL once the
JIT has had a chance to optimize things. The last time I had done any
serious work in Java was in 1997 so I was very pleasantly surprised at
how far JVM performance has progressed.

I initially thought I was going to miss CLOS because my prior code
base heavily depended on CLOS, especially method combination to help
make a lot of boilerplate disappear (in addition to removing the rest
of the boilerplate with a very high-level abstract model definition
language implemented with macros on steroids), but the way maps
(hashmaps), multi-methods, meta-data, and ad-hoc hierarchies work
together mostly make up for the lack of CLOS.

The big step for me here was getting past "it doesn't have CLOS, how
can I model essentially object-oriented simulation models without
something like CLOS?" to "with what's available in Clojure, what's the
Clojure-idiomatic way of creating the model building abstractions I
need?" Once I got past that hang-up, I was able to proceed quite
nicely and am happy with the result. My user-level model building
code will be as nice, concise, and high-level as my CL version was
(this is all work in progress).

The other things I miss in Clojure in addition to the above mentioned
method combination are symbol macros, macrolet, and LOOP (!), but
there are ways around most of these things so their ommision aren't
too painful. For day-to-day programming, LOOP is probably the thing I
miss the most, as any looping has to be done through recursion.
There's a language construct to make tail-recursive calls efficient on
the TCO-less JVM, but I do miss some of the more powerful features of
LOOP (yes, I'm LOOP-evil). However, the Clojure community is very
active so I expect that over time these will be filled in with
libraries.

When I was doing my initial investigation last December, what really
cinched it for me was watching Rich's Clojure for Lisp Programmers
videos and the concurrency video. They are very good and should
answer any questions about whether Clojure is suitable for any
particular task. The concurrency video is particularly good and goes
into technical depth discussing Clojure's concurrency support, the
design decisions Rich faced and why he made certain choices, and an in-
depth code walkthrough of an ant-colony food gathering simulation
using agents. Very cool stuff. Even though the video wasn't
specifically about Java interoperability, he does show building up a
graphical UI to show the ants speeding around in the REPL. Very, very
cool stuff.

My opinion after watching these videos is that Rich has *very* good
design taste. Starting with the goals he wanted, in my opinion, he's
made the right decision every time. It's obvious from the videos that
he has a deep command of programming language theory, which has led
him to choose a lot of semantics and implementation techniques that
fit together well, instead of that "groping in the dark" feeling you
get from say, certain languages.

In summary, I'm not going to say that Clojure is better or worse than
Common Lisp. For my particular domain, I can do some things easier
than I can do in the Common Lisp implementations I have available to
me (an important qualifier!) so it's useful for me. Your mileage may
and will vary.

Oh, I should add that I've purchased the beta of Stuart Halloway's
"Programming Clojure" book from Pragmatic Programmer's and it covers
the language nicely. I was able to breeze through the book in several
hours and came away with a good command of the language. Keep in mind
that it's more geared towards a non-Lisp reader than a CL expert.

Glenn Ehrlich

Kenneth Tilton

unread,
Feb 10, 2009, 9:55:52 AM2/10/09
to
glenn....@gmail.com wrote:
> On Feb 10, 12:30 am, Kenneth Tilton <kentil...@gmail.com> wrote:
>> In 25 words or less, why is Clojure better than Common Lisp?
>>
>> In 100 words or less, why is Clojure better than Common Lisp?
>>
>> Have you switched to Clojure? If so, from what?
>
> I guess I've switched, from Common Lisp, mostly because I changed jobs
> last November and I couldn't take my CL code base with me, so I was
> able to examine Clojure from a fresh perspective.

<snip great response>

Thx! You gave me ideas for a lot of questions. New survey soon (all of
which you have already answered).


kt

Kenneth Tilton

unread,
Feb 10, 2009, 10:10:13 AM2/10/09
to
What is your Clojure Status?
- What is Clojure?
- Never looked at it.
- Looked but did not like because ___
- Will use for some work because ___ but not all because ___ but
continue to use ___ for ___ because ____.
- Will now use instead of ___ because ____
- Other ____


(I think the rest are for anyone who will be using Clojure)

If Java access was a big factor, why not ABCL or AllegroCL?

What do you miss from Common Lisp (or whatever the "from" language was).


Other _______

Raffael Cavallaro

unread,
Feb 10, 2009, 10:54:58 AM2/10/09
to
On 2009-02-10 05:31:27 -0500, p...@informatimago.com (Pascal J.
Bourguignon) said:

> Kaz Kylheku <kkyl...@gmail.com> writes:
>
>> On 2009-02-10, Kenneth Tilton <kent...@gmail.com> wrote:
>>> In 25 words or less, why is Clojure better than Common Lisp?
>>
>> It has more kinds of parentheses. And symbols have to prove themselves
>> worthy before they are interned.
>
> This is why it's worse.
>
>
>>> In 100 words or less, why is Clojure better than Common Lisp?
>>
>> That constraint I can't deal with. I only ``do'' 25 words or less.
>
> And 25 is not less than 100 anymore?

<http://en.wikipedia.org/wiki/Sarcasm>

--
Raffael Cavallaro, Ph.D.

Raffael Cavallaro

unread,
Feb 10, 2009, 11:16:27 AM2/10/09
to
On 2009-02-10 10:10:13 -0500, Kenneth Tilton <kent...@gmail.com> said:

> What is your Clojure Status?

is clojure about to vault into the tilton pantheon?!

> - What is Clojure?
> - Never looked at it.
> - Looked but did not like because ___
> - Will use for some work because ___ but not all because ___ but
> continue to use ___ for ___ because ____.

will use for some work but not all because of:

cross platform java libs, especially cross platform gui libs

integration with emacs/slime

active enthusiastic user community and much contributed code

mikel evins likes it!

built in ease of threading due to immutablility of clojure data
structures (i.e., pure functional semantics).

possiblility of easy web deployment via applets (though not currently
high on my list)


continue to use CCL because of excellent mac os x integration.


> - Will now use instead of ___ because ____
> - Other ____
>
>
> (I think the rest are for anyone who will be using Clojure)
>
> If Java access was a big factor, why not ABCL or AllegroCL?
>
> What do you miss from Common Lisp (or whatever the "from" language was).

maturity of the language. code from six months ago often doesn't work
because breaking changes are still being made to the language.

>
>
> Other _______


--
Raffael Cavallaro, Ph.D.

Kenneth Tilton

unread,
Feb 10, 2009, 12:02:38 PM2/10/09
to
Raffael Cavallaro wrote:
> On 2009-02-10 10:10:13 -0500, Kenneth Tilton <kent...@gmail.com> said:
>
>> What is your Clojure Status?
>
> is clojure about to vault into the tilton pantheon?!

No, just curious. Thx for the survey response. Mikel is indeed a big plus.

kt

Dimiter "malkia" Stanev

unread,
Feb 10, 2009, 1:49:20 PM2/10/09
to

I'm syncing to the daily builds of clojure, and doing some minor
benchmarks. I'm trying hard to reach the speed of Common Lisp or Java
(I'm running Clojure with the -server option).

Overall, the speed ain't bad, it's about 10x faster than perl, python,
ruby, but x10-x20 slower than most of the Common Lisp Compilers (SBCL,
CMUCL, LispWorks, ACL).

I'm using Lisp for heavy calculations, so I can't really use it, until I
learn to optimize it better.

My base benchmark was the pnpoly.lisp code (point-in-poly).

Other things that I'm missing from Common Lisp are some form of
"apropos" and some way of disassembling the functions - I'm doing this
regurarly with Common Lisp in order to learn the peculiarities of the
various implementations, and gather knowledge of best practices myself
(off course there are papers by Fateman, and others about single and
double floating points).

Another strange peculiarity is the tagging - sometimes you have to do
(#^Float number), sometimes (number (float 10.0)) - it seems not
consistent, but granted this is not where the language is shining.

I think it's not the language right now for my needs, but my become, as
soon as I start explore web development more and more.

The JAR file is rather small, compared to the ABCL (not fair comparison,
I know different things - but still to give you perspective).

It definitely looks useful, and can teach you how to write even more
functional code (still trying to prevent myself from imperative thinking).

Alex Mizrahi

unread,
Feb 10, 2009, 5:15:45 PM2/10/09
to
ge> I'm exploring Clojure for my simulation work. The biggest plus for me
ge> in my domain is Clojure's concurrency model: immutable data
ge> structures, agents, STM, and NO USER LOCKS!.
ge> This makes it very easy to spread model calculations across cores
ge> without having to protect

spreading across cores makes sense if it speed ups things, right?
even if there are no apparent locks, STM etc., etc. might have its
overhead. and it might be possible that Clojure running on all 8 cores
works actually slower than SBCL running on single one.

so, all these features are sort of "cool", but totally meaningless
without proper benchmarking data. (if we're speaking about CPU-bound
applications.)


Alex Mizrahi

unread,
Feb 10, 2009, 5:17:50 PM2/10/09
to
KT> - Looked but did not like because ___

i did not like it because it is not a Common Lisp!

plus, at time i was looking at it, it threw errors in Java backtrace format,
that is, you've misplaced paren, and it throws ton of bullshit at you.
very unpleasant. (it seems they've aldready fixed this)


André Thieme

unread,
Feb 10, 2009, 7:41:31 PM2/10/09
to
Dimiter "malkia" Stanev schrieb:

> Kenneth Tilton wrote:
>> In 25 words or less, why is Clojure better than Common Lisp?
>>
>> In 100 words or less, why is Clojure better than Common Lisp?
>>
>> Have you switched to Clojure? If so, from what?
>>
>>
>
> I'm syncing to the daily builds of clojure, and doing some minor
> benchmarks. I'm trying hard to reach the speed of Common Lisp or Java
> (I'm running Clojure with the -server option).
>
> Overall, the speed ain't bad, it's about 10x faster than perl, python,
> ruby, but x10-x20 slower than most of the Common Lisp Compilers (SBCL,
> CMUCL, LispWorks, ACL).
>
> I'm using Lisp for heavy calculations, so I can't really use it, until I
> learn to optimize it better.

In general one can suggest to give type hints to speed up things.
For a little test function that Rainer Joswig gave here in c.l.l some
weeks ago I got from x15 more runtime than sbcl to half the runtime of
sbcl with a few type hints.
But sometimes those won’t help. Currently the bignum lib from Java seems
to be pretty slow.
For Java 7 some drastic improvements are visible on the horizon:
http://markmail.org/message/7conncsespvrlazn

Another general suggestion is to run things in parallel.
This makes of course only sense if your algorithms are parallelizable.

If they are not, and if you are using Clojure datastructures (such as
sets, vectors, hashmaps, ...) instead of Javas it can also be in some
cases a disadvantage. The Clojure versions simply have to do more work
under the hood. These datastructures are not only threadsafe, but also
concurrency ready, which is even more expensive.

> Other things that I'm missing from Common Lisp are some form of
> "apropos"

So find-doc did not give you satisfying results?
It can also take a regex...


> and some way of disassembling the functions

There are many Java tools that can support you.
Did you try jad to decompile .class files into .java files?
(in that sense Java is the Assembler for the JVM :))
But you can also use bytecode viewer.


> Another strange peculiarity is the tagging - sometimes you have to do
> (#^Float number), sometimes (number (float 10.0)) - it seems not
> consistent, but granted this is not where the language is shining.

As you can see, float is just an ordinary function, but does implicitly
give a type hint:
http://code.google.com/p/clojure/source/browse/trunk/src/clj/clojure/core.clj#1813

And btw, (number (float 10.0)) produces an error, as the function number
does not exist. Did you mean number? maybe?
Type hints can be given very consistent with the reader macro #^
as in #^TYPE


> I think it's not the language right now for my needs, but my become, as
> soon as I start explore web development more and more.

I hope you did not base this on the one result of your poly test case.
Although you know of course much better your needs. If that benchmark is
what you are basically doing all the time, then it’s very understandable.


André
--
Lisp is not dead. It’s just the URL that has changed:
http://clojure.org/

André Thieme

unread,
Feb 10, 2009, 8:25:59 PM2/10/09
to
Pascal J. Bourguignon schrieb:

> Kaz Kylheku <kkyl...@gmail.com> writes:
>
>> On 2009-02-10, Kenneth Tilton <kent...@gmail.com> wrote:
>>> In 25 words or less, why is Clojure better than Common Lisp?
>> It has more kinds of parentheses. And symbols have to prove themselves
>> worthy before they are interned.
>
> This is why it's worse.

The question at this point could be why this is worse.
Honestly, I see only advantages here.
The [] and {} give some hold to the eye, which I find nice.
One can of course argue that it is less consistent, and that a „real
Lisper” will only want to use (). But let’s not forget that () them-
self are reader macros. And if we want to argue with consistency in
mind, then those people should not make use of other reader macros in
CL as well, such as ' #' ` , ,@
I however see that a few handselected reader macros are a great thing.
They should exist for the most commonly used tasks.
Lists are mostly used in Clojure to write code :)
Vectors have taken more or less the place of the list.
One can „cons” elements to it (the function really is conj) and traverse
it with the same performance as lists. But random access is done in near
constant time. Also reversing a vector is much faster, though this is
less often needed, as conj adds elements at the end of the vector, not
to the front (as with lists).

Passing around small hashmaps is so simple.
(some-function {:a 10, :b 20}) vs

(let ((temp (make-hash-table)))
(setf (gethash :a temp) 10
(gethash :b temp) 20)
(some-function temp))


And the other thing that Kaz said about interned symbols also makes sense.
For example Hans Hübner writes in his blog:
„Clojure wants to be a Lisp, but it explicitly does not try to be
backwards compatible. This opened a rather large design space to Rich
Hickey, and some of the choices he made really do make sense. He
specifies a reader, yet his reader does not intern symbols. That is a
big win, as it allows the reader to actually work with arbitary Clojure
source files. In Common Lisp, one needs to re-implement a full reader
which does not intern symbols if one wants to read Common Lisp source
files. This is kind of ironic, as the "Code is Data" mantra that we keep
repeating does not really reflect what is possible in practice.”
Soure: http://netzhansa.blogspot.com/2008/10/trying-clojure.html

Dimiter "malkia" Stanev

unread,
Feb 10, 2009, 8:48:59 PM2/10/09
to
[snipped a lot of useful information - keeping it for later to read]

> I hope you did not base this on the one result of your poly test case.
> Although you know of course much better your needs. If that benchmark is
> what you are basically doing all the time, then it’s very understandable.
>
>
> André

Thanks Andre!

No I'm not going away from it - rather I'm staying - i like the
interactivity of it, the funny thing about it running on JVM (for good
or bad, I can get this thing to run on almost any platform, because it
uses JVM).

Also Rich Hickey seems to know his stuff, and only following his
creation, is enough to grasp powerful ideas, even if I may not use his
language at the end professionally.

Definitely I'm staying, and I'm going to dabble into it even more...

For example ARC did not leave me with that impression - to me arc
sounded like Common Lisp in Rap Lyrics/Slogan... And fact is Paul Graham
is still my favourite lisp person (I've read his stuff). Maybe I'm
missing something from ARC too - but that's another topic.


Pascal J. Bourguignon

unread,
Feb 10, 2009, 10:06:28 PM2/10/09
to
André Thieme <address.good.un...@justmail.de> writes:

> Pascal J. Bourguignon schrieb:
>> Kaz Kylheku <kkyl...@gmail.com> writes:
>>
>>> On 2009-02-10, Kenneth Tilton <kent...@gmail.com> wrote:
>>>> In 25 words or less, why is Clojure better than Common Lisp?
>>> It has more kinds of parentheses. And symbols have to prove themselves
>>> worthy before they are interned.
>> This is why it's worse.
>
> The question at this point could be why this is worse.
> Honestly, I see only advantages here.
> The [] and {} give some hold to the eye, which I find nice.
> One can of course argue that it is less consistent, and that a „real
> Lisper” will only want to use (). But let’s not forget that () them-
> self are reader macros. And if we want to argue with consistency in
> mind, then those people should not make use of other reader macros in
> CL as well, such as ' #' ` , ,@

Let's say that it's a personal taste. (And indeed, I use (function x)
rather than #'x, and sometimes (eg for pedagogical reasons), I use
(quote x) instead of 'x.

Reducing the set of special characters used to write code let you
write it faster. Keying in English is fast, because you only use
letters, and a very small number of punctuation, compared to keying in
popular programming languages. If you resist the temptation of using
a lot of reader macros in lisp, then you can type lisp code as fast as
English text.


Also, it would be nice if the language didn't use all the characters,
and left some for user's reader macros. In Common Lisp, {}, [] , !?
and a few others are reserved to the user. (Of course, with unicode
this is less of a problem).

> Passing around small hashmaps is so simple.
> (some-function {:a 10, :b 20}) vs
>
> (let ((temp (make-hash-table)))
> (setf (gethash :a temp) 10
> (gethash :b temp) 20)
> (some-function temp))

This is crazy. Nobody write such a form!

(htable :a 10 :b 20)
--> #S(HASH-TABLE :TEST EXT:FASTHASH-EQL (:B . 20) (:A . 10))


>
>
> And the other thing that Kaz said about interned symbols also makes sense.
> For example Hans Hübner writes in his blog:
> „Clojure wants to be a Lisp, but it explicitly does not try to be
> backwards compatible. This opened a rather large design space to Rich
> Hickey, and some of the choices he made really do make sense. He
> specifies a reader, yet his reader does not intern symbols. That is a
> big win, as it allows the reader to actually work with arbitary Clojure
> source files. In Common Lisp, one needs to re-implement a full reader
> which does not intern symbols if one wants to read Common Lisp source
> files. This is kind of ironic, as the "Code is Data" mantra that we keep
> repeating does not really reflect what is possible in practice.”
> Soure: http://netzhansa.blogspot.com/2008/10/trying-clojure.html

We only need to add a CDR for a READTABLE-PARSE-TOKEN hook to be able
to read uninterned sources without reimplementing the reader.

But even with the current standard, the point is that reader macros
are not to be abused for lisp programs. It's better in lisp programs
or embeded DSL to use normal functions or macros such as (htable :a 10
:b 20) than to use a reader macro such as {:a 10 :b 20}.

Reader macros are designed to build user level DSL.

If you need to read a DSL source without "interning" it, then you
should use a normal parser.

--
__Pascal Bourguignon__

daniel....@excite.com

unread,
Feb 11, 2009, 10:48:56 AM2/11/09
to
On Feb 10, 10:06 pm, p...@informatimago.com (Pascal J. Bourguignon)
wrote:

> Reducing the set of special characters used to write code let you
> write it faster.  Keying in English is fast, because you only use
> letters, and a very small number of punctuation, compared to keying in
> popular programming languages.

I beg to point out that some folks can touch-type the non-letter
keys...
and although clearly farther away from home position and therefore
slower,
each non-letter used in a non-letter-rich syntax will generally
represent
many letters of lisp symbol. non-letter-rich syntax can be an
effective
compression for 1) reading, 2) thinking, and yes also 3) typing, if
one
touch-types the non-letters.

That said, the whole reason I like and use the CL type of Lisp syntax
is
because my preferences agrees with yours on:

Raffael Cavallaro

unread,
Feb 11, 2009, 11:09:16 AM2/11/09
to
On 2009-02-10 22:06:28 -0500, p...@informatimago.com (Pascal J.
Bourguignon) said:

> Also, it would be nice if the language didn't use all the characters,
> and left some for user's reader macros. In Common Lisp, {}, [] , !?
> and a few others are reserved to the user. (Of course, with unicode
> this is less of a problem).

This is not an issue for clojure:
from: <http://clojure.org/reader>
"The read table is currently not accessible to user programs."

Of course many common lisp users will think this more a bug than a feature...
--
Raffael Cavallaro, Ph.D.

Message has been deleted

TomSW

unread,
Feb 11, 2009, 12:21:36 PM2/11/09
to
On Feb 10, 4:10 pm, Kenneth Tilton <kentil...@gmail.com> wrote:
> What is your Clojure Status?

I'm using it to learn the Java libraries without having to use Java. I
don't think I'll be lucky enough to find another Lisp job soon:
finding IT jobs in Belgium with no Dutch is hard enough. So I'm
preparing for the worst...

> If Java access was a big factor, why not ABCL or AllegroCL?

Clojure in non-proprietary and has lots of interesting features built-
in, in particular, concurrency, abstract datatypes (collections,
mappings), lazy evaluation.

> What do you miss from Common Lisp (or whatever the "from" language was).

I haven't been using Clojure for long enough to miss much of Common
Lisp.

...

Another interesting approach to leveraging Java libraries is Jnil
(http://common-lisp.net/project/jnil/), which actually translates them
into Common Lisp. The maintainer could really do with some support.

cheers,
Tom

André Thieme

unread,
Feb 12, 2009, 7:15:48 PM2/12/09
to
Kenneth Tilton schrieb:

> In 25 words or less, why is Clojure better than Common Lisp?
> In 100 words or less, why is Clojure better than Common Lisp?

The word „better” is nothing objective, so people can disagree on what I
personally rate as better.
My list of things that I like in Clojure better than CL
(in no particular order):

1. It basically supports one major paradigm/style of programming,
the functional one. CL too does support it, but CL also supports
other styles, and it is even very idiomatic to do imperative
programming in CL.
People will disagree if offering a smaller number of programming
style is better or not, but I like it better. It means that most
developers will come up with more comparable/compatible solutions.
Whatever one may think about the Java programming language, it’s a
fact that it offers a very large set of libraries. This is due to
the limits which are built in into the language. There is basically
one way (few ways) to do it, instead of many ways, as in CL.
So, I prefer to have one major style in Clojure. It happens to be
the one I preffered since many years in CL too, the functional one.

2. Concurrency ready. I see basically 3 or 4 languages out of the
many hundreds in use, that are seriously capable of doing concurrent
programming: Clojure, Erlang, Haskell, and also going there, F#.
While it is not impossible to do it in other languages, Clojure does
make it really easy. It’s in some sense the argument that was in
favour of CL in the past 15-20 years: „Yeah, mathematically speaking
it is possible in other languages too. In principle one can solve any
problem in Assembler. It’s just that it is much easier in Lisp, as it
comes with powerful abstractions”.
Clojure has gone the evolutionary step into the right direction (in
my opinion), by providing standard tools for concurrency. Other langs
like CL or Python can also do functional programming. But the problem
is that they also offer an alternative way. As long that exists the
devs have to program by agreement, and they need to be very strict.
Currently not many languages have a good implementation of a STM with
Multiversion Concurrency Control. I think for F# one is currently
being developed. But this really should come with the lang itself,
as this would be an integral part. If this is an addon lib, then
other implementations may arise, which can (no doubt) also have ad-
vantages, but brings back incompatibility.

3. Modernized syntax. It makes totally sense to me (you might disagree
of course) to have some basic syntax support for the most common
operations. The CL committee had the same idea in mind and intro-
duced ' #' #+ #- ` , ,@ which, again, makes very much sense
to me. To make access to datastructures other than lists easier,
Clojure went a step further, and provides reader macros for vectors
(which can replace lists to a great part), hashmaps and sets, and
of course strings (and regular expressions).
I now hate it so much when I go back to CL that everything is so
chatty. It does not buy me anything that I have to bloat up my code
for typical tasks.
Clojures datastructures are fully integrated into the macro system.

4. Lazyness. In many places Clojure is very lazy :)
This is great. Not only does that improve performance greatly, no, it
also allows new idioms and a more elegant programming style. It’s
well integrated.

5. It runs on the JVM. Today many languages do run in a VM (like CL,
Python, C#, ...). Why develop your own when you can have the most
mature one?
Chosing the JVM brings also tons of advantages:

a) Operating system does not matter so much anymore. CLs are
available for most plattforms too, though this does not always
help. No recompilation needed. I can switch back between the OSes
and continue coding. The devs of the same team have the choice of
their OS. The employer would not have to force us anymore to use
something we don’t like. The plattform in the end is always the
JVM.

b) Giant lib. Want a server for RESTful applications? Integration
with SAP? The JVM can not do magic, but it really haves very
much to offer, library wise.

c) Will help to create much more Lisp jobs.
I personally left two times my home city to get a Lisp job. One
time I even left my country for it. As Java is the most popular
programming language it is more likely to find interesting pro-
jects in cities of my choice. Of course I don’t want to do Java
programming, but there will always be Java companies (probably
the not too big ones) that will accept you in their team as a
Clojure developer. True, it potentially can bring in some diffi-
culties if you are the only one who can read/write Clojure code.
But some companies will weight that against the 2x - 20x boost in
productivity that Lisp can bring over Java. Clojure brings me into
the position that I suddenly can negotiate something with the
company.


So, maybe a bit more than 100 words, but here you go.
The points that I listed will not be the ones that everyone else will
also find „better”. I however do.


> Have you switched to Clojure? If so, from what?

Yes, switched from CL to Clojure.
And if it is not necessary, I would not want to go back.
But sure, if Clojure is no option then CL would always be my next
choice.

André Thieme

unread,
Feb 12, 2009, 7:23:41 PM2/12/09
to
Francogrex schrieb:

> On 10 feb, 16:10, Kenneth Tilton <kentil...@gmail.com> wrote:
>> What is your Clojure Status?
>> - What is Clojure?
>> - Never looked at it.
>> - Looked but did not like because ___
>> - Will use for some work because ___ but not all because ___ but
>> continue to use ___ for ___ because ____.
>> - Will now use instead of ___ because ____
>> - Other ____
>
> I have looked at clojure but don't want to use it because simply it's
> not "common lisp" and it has that "unhealthy" connection to Java
> (either directly defined or not). In addition I am against the
> dispersal/waste of efforts that sprout different programming languages
> instead of concentrating it all to improve the already existing ones.
> I have more respect for an old language like lisp that has matured and
> evolved over the time (albeit to different dialects- of course I would
> have preferred that they stay united-). Now unless you think of
> clojure as an evolution and an extension of common lisp...

I respect your opinion, however, I would like to mention two things:
1) The connection to Java can be seen by some folks as very healthy.
2) When you argue about matureness and evolution, then Clojure could
be interesting. The language is much more simple than Lisp. And
some core parts of a Lisp were already provided by the JVM. For
example the GC, the Exception system and some tenthousand ready to
use methods. In that regard, Clojure can be seen as even more mature
than CL implementations. As Java is the most popular programming
language it gets on a daily basis more man hours of testing than
all CLs got in the past years. Billions were invested by the biggest
IT companies into the JVM, and it went through an evolutionary
process in which it got very mature.

Speaking of evolution: Clojure learned from Lisp. So it is not a
new language that started from scratch. No, it inherited the DNA
of its parents. It took the efforts of research in the past 50
years and continued to evolve from that point. So, it is the next
step in evolution of Lisp.

André Thieme

unread,
Feb 12, 2009, 7:30:09 PM2/12/09
to
Kenneth Tilton schrieb:

> What is your Clojure Status?
> - What is Clojure?
> - Never looked at it.
> - Looked but did not like because ___
> - Will use for some work because ___ but not all because ___ but
> continue to use ___ for ___ because ____.
> - Will now use instead of ___ because ____
> - Other ____

It is: I use it daily for professional work, but also nearly every day
for personal programming fun.
I use Clojure now instead of CL mostly, and will port my code.


> (I think the rest are for anyone who will be using Clojure)
>
> If Java access was a big factor, why not ABCL or AllegroCL?

Because those are CL implementations which come with clos.
I like clos more than the object system of Java, but this is just my
opinion. A fact however is, that those object models are not compatible.
It is very ugly to work with Java from within CL.
So, if access to Java would be a big factor, then one should definitly
use a language which was designed with that idea in mind.


> What do you miss from Common Lisp (or whatever the "from" language was).

From CL I miss in principle nothing.
I am glad that Clojure has no object system, but instead goes the path
of functional programming.
What I miss though are features of specific CL implementations.
For example SBCLs type inference engine.

Raffael Cavallaro

unread,
Feb 12, 2009, 7:39:41 PM2/12/09
to
On 2009-02-12 19:23:41 -0500, André Thieme
<address.good.un...@justmail.de> said:

> And
> some core parts of a Lisp were already provided by the JVM. For
> example the GC, the Exception system and some tenthousand ready to
> use methods. In that regard, Clojure can be seen as even more mature
> than CL implementations.

Not really. This argues for the maturity of the *platform* on which
clojure is built (i.e., the jvm). Clojure itself is clearly still not
mature. There's a thread still running on how to fix mod:

user=> (mod -3 3)
3

So clojure, the language, not the platform it is built on, is still not
nearly as mature as common lisp.
--
Raffael Cavallaro, Ph.D.

Alex Mizrahi

unread,
Feb 13, 2009, 7:12:48 AM2/13/09
to
AT> 1) The connection to Java can be seen by some folks as very healthy.

oh yes, it is very healthy (for a functional language!) to have "recur"
special
operator instead of normal tail recursion because of JVM deficiency.

AT> In that regard, Clojure can be seen as even more mature
AT> than CL implementations.

platform maturity has nothing to do with language implementation maturity.
i have here a build labeled "2008-09-16", just few months ago error handling
was totally broken and weird as it was spitting java backtraces:

user=> (())(()))
java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot
be cast to clojure.lang.IFn
java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot
be cast to clojure.lang.IFn
at user.eval__2290.invoke(Unknown Source)
at clojure.lang.Compiler.eval(Compiler.java:3891)
at clojure.lang.Repl.main(Repl.java:75)

when considerable portions of implementation get reorganized in short
periods of time,
that is *not* called "mature"


Scott Burson

unread,
Feb 13, 2009, 2:07:18 PM2/13/09
to
On Feb 10, 7:10 am, Kenneth Tilton <kentil...@gmail.com> wrote:
> What is your Clojure Status?

I've looked at it, but I have a bunch of code in CL that I'm working
on and see no compelling reason to switch.

If I should decide I need my app to run on the JVM at some point --
which is possible -- I would consider Clojure, but I would also
consider Scala.

-- Scott

André Thieme

unread,
Feb 13, 2009, 2:41:14 PM2/13/09
to
Alex Mizrahi schrieb:

> AT> 1) The connection to Java can be seen by some folks as very healthy.
>
> oh yes, it is very healthy (for a functional language!) to have "recur"
> special operator instead of normal tail recursion because of JVM deficiency.

It’s true, it’s healthy to have recur.
I agree that it is not nice that the JVM does not have tail recursion
yet. But in practice that is not a real issue, as recur is available.

Let’s look at this unreadable mess in CL:

(DEFUN Y (F)
( (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))
#'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))))

(FUNCALL (Y #'(LAMBDA (FN)
#'(LAMBDA (X)
(IF (ZEROP X) 0 (+ X (FUNCALL FN (- X 1)))))))
200)
==> 20100

we can do this in Clojure:
((fn [n] (loop [x n, res 0]
(if (zero? x) res (recur (dec x) (+ x res)))))
12345678)

No Y-Combinator needed, much shorter, much more pleasant for the eye.
Plus: this call works.
When I gave the argument of 2000 in clisp on Windows it crashed.
Stack overflow I guess.


Or another example:
(defun fibonacci (n)
(labels ((fibo-helper (x result)
(if (zerop x)
result
(fibo-helper (1- x) (* x result)))))
(fibo-helper n 1)))

would be in Clojure (without recur):
(defn fibonacci [n]
((fn fibo-helper [x result]
(if (zero? x)
result
(fibo-helper (dec x) (* x result))))
n 1))

The labels is not needed, as fn can be given a name (fn in Clojure is
CLs LAMBDA). Anyway, this is not stack-safe right now, as the JVM does
not support tail call optimazation (though Jon mentioned that the team
of the OpenJDK is working on that).

Now in Clojure we simply replace the call of fibo-helper with recur:
(defn fibonacci [n]
((fn fibo-helper [x result]
(if (zero? x)
result
(recur (dec x) (* x result))))
n 1))

That’s the only change. It is still following the idiom that is needed
in all programming languages for tail recursive calls.
This would also allow us to eliminate the function name we gave to fn.
This makes it again shorter. And if we want to, we can put in a loop:
(defn fibonacci [n]
(loop [x n result 1]
(if (zero? x)
result
(recur (dec x) (* x result)))))

And although I am doing CL since 6 years and Clojure just 4 months or
so, this looks cleaner in my opinion than the CL version.


> AT> In that regard, Clojure can be seen as even more mature
> AT> than CL implementations.
>
> platform maturity has nothing to do with language implementation maturity.
> i have here a build labeled "2008-09-16", just few months ago error handling
> was totally broken and weird as it was spitting java backtraces:
>
> user=> (())(()))
> java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot
> be cast to clojure.lang.IFn
> java.lang.ClassCastException: clojure.lang.PersistentList$EmptyList cannot
> be cast to clojure.lang.IFn
> at user.eval__2290.invoke(Unknown Source)
> at clojure.lang.Compiler.eval(Compiler.java:3891)
> at clojure.lang.Repl.main(Repl.java:75)
>
> when considerable portions of implementation get reorganized in short
> periods of time,
> that is *not* called "mature"

Yes, I understand your position. And also thanks to Raffael, he is also
right.
In fact, Clojure did not reach 1.0 status, so yes, breaking changes can
still occur. But most of the time Rich adds more (very useful)
abstractions and tools to the language, instead of making breaking changes.

However, I also like to look at this from a more practical side.
Clojure is usable now. One can step with debuggers through the code
line by line, one can profile it, compile it into doubleclickable
.jar files (like .exe under Windows) or simply work in Emacs+Slime.
Nearly all parts of the language itself work perfectly. But when
writing real world applications one constantly can be in need of
libs, that already do parts of what you want to do.
Lisps like Allegro, Lispworks or sbcl are being worked on every
day. It’s similar to what happens to Clojure.
It is a bit unfair to make the comparison of what changes in the
core language. CLs is already defined and can not be changed.
Clojure is still open, and Rich can decide to add more to it.
So of course, this will result in more changes in the core when
compared to what happens to CLs.
I worked professionally with Allegro and also Lispworks.
In both I or my workmates discovered bugs in their libs, like
database stuff.
This is much more unlikely to happen when using Clojure, as it
simply offers some ten thousand more functions which still need
to be implemented in CL first, and which were tested some orders
of magnitude more intense than their CL equivalents.
And one could argue if it can be seen as a bug as well, if some
libs are simply not available (like a server for RESTful apps)
in CL. Although Jon writes a lot of provocative material here,
and sometimes explicitly enjoys to bring in some trolling, he
also mentioned very true things, such as that some CL libs have
like 80 users. Not 80k, but a mere 80. Development on important
stuff does not happen as much as I wish (are cursors already
available in sql libs?).
Clojure is actively and intensly used by some hundred people.
We test every new feature, and honestly, I did not stumble upon
lot’s of bugs. Rich fixes them so fast, it’s really nice.

So, if I see the whole variety of things that are available when
programming in Clojure, then only a tiny fraction of it is not
mature.
It’s true that there are some more bugs, but also check out what
SBCL changes:
http://www.sbcl.org/all-news.html

Just scroll down this list. SBCL exists since years, and not one
main developer is working on it, but 5-25.
When I look at this list I see not interesting additions to the
main language and libraries. Tons of bug fixes for core stuff.

Maybe it’s okay to call SBCL not mature, and only see the main
two commercial CLs (Allegro and Lispworks) this way.
I don’t know what they are doing, but they still do bugfixes
constantly. And although they had 15+ more years of time than
Clojure, they still need to fix core stuff. And in their libs
they have also several bugs that my companies uncorvered.

As much I understand the POV that Clojure is not mature, because
of the good reasons you and Raffaello gave, I see it differently
and would call it already mature.
It already offers right now basically everything that is needed
for professional and commercial development. What mostly happens
is that even better abstractions are added every few days.
For me it’s extremly difficult to go back doing CL, because I miss
so much. Kenny asked in this thread also what I miss from CL.
I have to think long to come up with maybe a few points.
But the other direction.. that is the real problem.

Raffael Cavallaro

unread,
Feb 13, 2009, 7:49:42 PM2/13/09
to
On 2009-02-13 14:41:14 -0500, André Thieme
<address.good.un...@justmail.de> said:

> we can do this in Clojure:
> ((fn [n] (loop [x n, res 0]
> (if (zero? x) res (recur (dec x) (+ x res)))))
> 12345678)

we can do this in common lisp:

((lambda (n) (loop for x from n downto 0 summing x)) 12345678)

and when we do it in Clozure Common Lisp (dx86cl64) it runs 10 times as
fast as your clojure code on the same machine.
--
Raffael Cavallaro, Ph.D.

André Thieme

unread,
Feb 13, 2009, 9:46:26 PM2/13/09
to
Raffael Cavallaro schrieb:

We were talking about recur and its advantages. The issue was not about
performance.

It’s likely that Clozure CL or also SBCL will run much faster, as
Clojure would use boxed numbers, which have to be unboxed first and then
boxed again.
One would have to give type hints, as in:

(loop [r (long 0) n (long 12345678)] (if (zero? n) r (recur (+ r n) (dec
n))))

Now that runs probably at very comparable speed.

Anyway, if I want to outperform your Clozure Cl code above by a factor
of 150 in Clojure, then this would do:
(defn sum [n] (+ (/ n 2) (/ (* n n) 2)))

Raffael Cavallaro

unread,
Feb 13, 2009, 11:06:45 PM2/13/09
to
On 2009-02-13 21:46:26 -0500, André Thieme
<address.good.un...@justmail.de> said:

> We were talking about recur and its advantages. The issue was not about
> performance.

[snip]


> (loop [r (long 0) n (long 12345678)] (if (zero? n) r (recur (+ r n) (dec n))))

The point is that there is no advantage to recur. It's a wart
necessitated by the jvm's lack of tail call optimization.

In any conforming scheme it's just a plain old recursive call. In any
conforming common lisp it's just a simple loop. And in most decent
common lisps, as long as you're not optimizing for debug to keep the
stack frames, if you really want to wear the scheme recursive hair
shirt, you can do it recursively too:

(labels ((loop (r n) (if (zerop n) r (loop (+ r n) (1- n)))))
(loop 0 12345678))

but of course a real loop, not recursion, is the common lisp norm:

(loop for i upto 12345678 summing i)


--
Raffael Cavallaro, Ph.D.

John Thingstad

unread,
Feb 14, 2009, 1:29:02 AM2/14/09
to
På Sat, 14 Feb 2009 05:06:45 +0100, skrev Raffael Cavallaro
<raffaelc...@pas.espam.s.il.vous.plait.mac.com>:

>
> but of course a real loop, not recursion, is the common lisp norm:
>
> (loop for i upto 12345678 summing i)
>
>

Depend what you call norm. (let ((j 0)) (dotimes (i 12345678 j) (incf j
i))) seems less offensive to loop haters. Some swear Lisp should be purely
functional. So pehaps series? ;) The style wars will never end.. I would
guess there are as many styles as Lispers. The developers at Clojure
dislike that you can mix and match styles. To me it is one of the things
that attracts me to the language.

--------------
John Thingstad

William James

unread,
Feb 14, 2009, 2:32:29 AM2/14/09
to
Raffael Cavallaro wrote:

> On 2009-02-13 14:41:14 -0500, André Thieme
> <address.good.un...@justmail.de> said:
>
> > we can do this in Clojure:
> > ((fn [n] (loop [x n, res 0]
> > (if (zero? x) res (recur (dec x) (+ x res)))))
> > 12345678)
>
> we can do this in common lisp:
>
> ((lambda (n) (loop for x from n downto 0 summing x)) 12345678)

Reduce:

for n:=1:12345678 sum n;

76207888812681


Marco Antoniotti

unread,
Feb 14, 2009, 2:49:44 AM2/14/09
to
On Feb 14, 8:32 am, "William James" <w_a_x_...@yahoo.com> wrote:
> Raffael Cavallaro wrote:
> > On 2009-02-13 14:41:14 -0500, André Thieme
> > <address.good.until.2009.may...@justmail.de> said:
>
> > > we can do this in Clojure:
> > > ((fn [n] (loop [x n, res 0]
> > >            (if (zero? x) res (recur (dec x) (+ x res)))))
> > >  12345678)
>
> > we can do this in common lisp:
>
> > ((lambda (n) (loop for x from n downto 0 summing x)) 12345678)
>
> Reduce:
>
> for n:=1:12345678 sum n;
>
> 76207888812681

In Reduce it should be

for n := 1:12345678 sum n;

In CL it is

(loop for n from 1 below 12345678 sum n)

Longer, but same thing.

Cheers
--
Marco

William James

unread,
Feb 14, 2009, 3:09:22 AM2/14/09
to
Raffael Cavallaro wrote:

> but of course a real loop, not recursion, is the common lisp norm:
>
> (loop for i upto 12345678 summing i)

Ruby:

sum=0;(1..12345678).each{|n| sum+=n}

Alexander Lehmann

unread,
Feb 14, 2009, 4:13:16 AM2/14/09
to

(/ (* 12345678 12345679) 2)

Longer, but faster :)

Slobodan Blazeski

unread,
Feb 14, 2009, 5:18:06 AM2/14/09
to
That's far worse than Raffael solution.Why do you need so many tokens
for such a simple thing?
Try this:
J:
+/i.12345679
bobi

Slobodan Blazeski

unread,
Feb 14, 2009, 5:21:00 AM2/14/09
to
On Feb 14, 10:13 am, Alexander Lehmann <lehma...@in.tum.de> wrote:
> William James wrote:
> > Raffael Cavallaro wrote:
>
> >> On 2009-02-13 14:41:14 -0500, André Thieme
> >> <address.good.until.2009.may...@justmail.de> said:
>
> >>> we can do this in Clojure:
> >>> ((fn [n] (loop [x n, res 0]
> >>>            (if (zero? x) res (recur (dec x) (+ x res)))))
> >>>  12345678)
> >> we can do this in common lisp:
>
> >> ((lambda (n) (loop for x from n downto 0 summing x)) 12345678)
>
> > Reduce:
>
> > for n:=1:12345678 sum n;
>
> (/ (* 12345678 12345679) 2)
>
> Longer, but faster :)

Cheater :)

cheers
bobi

Alex Mizrahi

unread,
Feb 14, 2009, 6:56:35 AM2/14/09
to
??>> oh yes, it is very healthy (for a functional language!) to have
??>> "recur" special operator instead of normal tail recursion because of
??>> JVM deficiency.

AT> It's true, it's healthy to have recur.
AT> I agree that it is not nice that the JVM does not have tail recursion
AT> yet. But in practice that is not a real issue, as recur is available.

this reminds me a soviet anecdote: when there is no meat in the butcher's
shop (it was often the case)
they place an announcement at the shop's door: "there is no necessity in a
meat today".
are you as brainwashed as soviet's?

recursion is not limited to the cases when you just call current function in
a tail-call fashion. in functional
programming often you need to call function in an alternating fashion -- foo
calls bar, bar calls foo back
etc. and recur simply cannot do this. it can only emulate simple loops.

educate yourself: http://en.wikipedia.org/wiki/Mutual_recursion

AT> Let's look at this unreadable mess in CL:

AT> (DEFUN Y (F)
AT> ( (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))
AT> #'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G))
AT> H)))))

this is a piece of cheap propaganda, i can't believe you're writing this
seriously.
you've tried hard to make it looks like an unreadable mess, and now you
claim it is unreadable mess.
whoa. NOBODY WRITES CODE LIKE THIS.

if you need to do recursive call of a local function in CL, use labels.

AT> (FUNCALL (Y #'(LAMBDA (FN)
AT> #'(LAMBDA (X)
AT> (IF (ZEROP X) 0 (+ X (FUNCALL FN (- X 1)))))))
AT> 200)
AT> ==> 20100

it is not tail recursive, btw. tail recursive version with labels:

(labels ((sum (x acc) (if (zerop x)
acc
(sum (- x 1) (+ acc x)))))
(sum 200 0))

AT> we can do this in Clojure:
AT> ((fn [n] (loop [x n, res 0]
AT> (if (zero? x) res (recur (dec x) (+ x res)))))
AT> 12345678)

AT> No Y-Combinator needed, much shorter, much more pleasant for the eye.

no Y combinator is needed in Common Lisp either, and code is quite similar
when you
remove it. you might argue that anonimous functions/loops are somehow
better, but i
find named ones more readable.

what would be even "more pleasant for the eye": (loop for i from 1 to n
summing i)

AT> Plus: this call works.
AT> Stack overflow I guess.

sure it does, because it was not tail calls. you should admit you know very
little
about functional programming, as you do not know even basics.

AT> When I gave the argument of 2000 in clisp on Windows it crashed.

CLISP does not optimize tail calls in debug mode, iirc.
in SBCL it works fine with in default mode:

CL-USER> (labels ((sum (x acc) (if (zerop x)
acc
(sum (- x 1) (+ acc x)))))
(sum 20000000 0))

200000010000000

AT> Or another example:
AT> (defun fibonacci (n)
AT> (labels ((fibo-helper (x result)
AT> (if (zerop x)
AT> result
AT> (fibo-helper (1- x) (* x result)))))
AT> (fibo-helper n 1)))

wow, so now you know about labels and tail recursion. good for you.
it is not fibonacci, it is factorial, btw.

AT> This would also allow us to eliminate the function name we gave to fn.

you say it like it is some unique feature of Clojure. with a simple macro
you can make recur like in Clojure in CL. but you cannot add support for
tail calls in Clojure in any way, until they fix it in JVM.

AT> This makes it again shorter. And if we want to, we can put in a loop:
AT> (defn fibonacci [n]
AT> (loop [x n result 1]
AT> (if (zero? x)
AT> result
AT> (recur (dec x) (* x result)))))

AT> And although I am doing CL since 6 years and Clojure just 4 months or
AT> so, this looks cleaner in my opinion than the CL version.

than version you've wrote in CL. i would write it like this:

(defun factorial (n)
(loop with p = 1
for i from 1 to n
do (setf p (* p i))
finally (return p)))

IMHO that's cleaner. or if i absolutely must use recursion:

(defun factorial (n &optional (result 1))
(if (zerop n)
result
(factorial (- n 1) (* n result))))

it is even shorter than your Clojure thing.

AT> However, I also like to look at this from a more practical side.
AT> Clojure is usable now.

many people find PHP usable and mature -- it does not bother them
that it lacks important features or that it often gets incompatible changes.

Alexander Lehmann

unread,
Feb 14, 2009, 7:13:59 AM2/14/09
to

SCNR *g*

André Thieme

unread,
Feb 14, 2009, 7:15:10 AM2/14/09
to
Raffael Cavallaro schrieb:

> On 2009-02-13 21:46:26 -0500, André Thieme
> <address.good.un...@justmail.de> said:
>
>> We were talking about recur and its advantages. The issue was not about
>> performance.
> [snip]
>> (loop [r (long 0) n (long 12345678)] (if (zero? n) r (recur (+ r n)
>> (dec n))))
>
> The point is that there is no advantage to recur. It's a wart
> necessitated by the jvm's lack of tail call optimization.

I see your point, however, I personally disagree.
First of all, I would like to mention that recur also has no disadvantages.
That is not enough to introduce something into a language. Otherwise one
could add recur1, recur2, ... recur24637, ...
They all would have no disadvantages (assuming they work exactly like
recur).
But the fact that the JVM currently does not support tail call opt.
under the hood is a very plausible reason to add it.
Besides that, recur does in fact have three advantages:
1. it allows anon functions to call recurse, they can call themselves
2. it blocks you from accidently not doing tail calls, because the
compiler can check if recur really is in the tail position
3. as a minor advantage I want to add, that it is easy to search in code
for occurrences of “recur”, or if you spot it somewhere while flying
over your sources, you immediately see “Ah, here we have a recursive
call”.

So even when the JVM will support one day tail call optimization, recur
will not go.
Jon Harrop indicated that this (adding TCO) is happening at the moment
for the OpenJDK, and as Sun works on their own functional programming
language “Fortress” I suppose they will also be interested in adding it.
I will definitly continue to use recur. What I will stop to use are
trampolines.


> but of course a real loop, not recursion, is the common lisp norm:
>
> (loop for i upto 12345678 summing i)

Yes, loop is nice. In principle it’s what I would do in CL as well,
although for this specific case I would really prefer to directly
calculate that number via (defn sum [n] (+ (/ n 2) (/ (* n n) 2))).
In Clojure I could do:
(apply + (range 12345678)))

or use reduce instead of apply.

André Thieme

unread,
Feb 14, 2009, 7:52:32 AM2/14/09
to
Alex Mizrahi schrieb:

> recursion is not limited to the cases when you just call current function in
> a tail-call fashion. in functional
> programming often you need to call function in an alternating fashion -- foo
> calls bar, bar calls foo back
> etc. and recur simply cannot do this. it can only emulate simple loops.
>
> educate yourself: http://en.wikipedia.org/wiki/Mutual_recursion

For that case Clojure offers trampolines.
Yes, one can argue that trampolines are a specific idiom which one needs
to learn. It’s true. But let us not forget that tail recursion itself
already is such an idiom. It is an optimization hack.
No programming system currently allows you to write recursion as in a
way that is closest to math.
We always need to apply the design pattern “Tail recursion”.
So there already is something complex that one needs to do. Now what is
different in Clojure is, that you don’t make the calll
(fun 1 2 3) but instead
#(fun 1 2 3) when you use trampolines, and it is stack-safe again.
It’s not that hard to remember. But yes, it is one key stroke more complex.
Still I would stop using trampolines as soon the JVM will introduce that
kind of optimization. I will however continue to use recur, for the
typical recursion, which makes like 99% of all recursion I usually use.


> AT> Let's look at this unreadable mess in CL:
>
> AT> (DEFUN Y (F)
> AT> ( (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))
> AT> #'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G))
> AT> H)))))
>
> this is a piece of cheap propaganda, i can't believe you're writing this
> seriously.
> you've tried hard to make it looks like an unreadable mess, and now you
> claim it is unreadable mess.
> whoa. NOBODY WRITES CODE LIKE THIS.

Well, it’s from Kent Pitman.
http://www.nhplace.com/kent/Papers/Technical-Issues.html


> if you need to do recursive call of a local function in CL, use labels.
>
> AT> (FUNCALL (Y #'(LAMBDA (FN)
> AT> #'(LAMBDA (X)
> AT> (IF (ZEROP X) 0 (+ X (FUNCALL FN (- X 1)))))))
> AT> 200)
> AT> ==> 20100
>
> it is not tail recursive, btw. tail recursive version with labels:
>
> (labels ((sum (x acc) (if (zerop x)
> acc
> (sum (- x 1) (+ acc x)))))
> (sum 200 0))

Where is the anonymous function here?
recur allows you anon functions to call themself.


> what would be even "more pleasant for the eye": (loop for i from 1 to n
> summing i)

Yes true, for that specific task it is much nicer.
I like it nearly as much as (apply + (range n)).

> AT> Plus: this call works.
> AT> Stack overflow I guess.
>
> sure it does, because it was not tail calls. you should admit you know very
> little about functional programming, as you do not know even basics.

I see no reason to admit that at this point, as I was fully aware about
this. What I was doing was talking about anon functions calling themselves.

> AT> Or another example:
> AT> (defun fibonacci (n)
> AT> (labels ((fibo-helper (x result)
> AT> (if (zerop x)
> AT> result
> AT> (fibo-helper (1- x) (* x result)))))
> AT> (fibo-helper n 1)))
>
> wow, so now you know about labels and tail recursion. good for you.
> it is not fibonacci, it is factorial, btw.

Yes right, how embarrassing :-/


> AT> This would also allow us to eliminate the function name we gave to fn.
>
> you say it like it is some unique feature of Clojure. with a simple macro
> you can make recur like in Clojure in CL. but you cannot add support for
> tail calls in Clojure in any way, until they fix it in JVM.

Let’s say you have a Lisp with no support for TCO.
Then you would also be forced to wait until your vendor fixes it.
Or you have an open source solution and do it yourself (as it currently
happens with the OpenJDK).
And of course one can add recur also in CL. Everything that Clojure has
can be done in CL and vice versa.


> AT> This makes it again shorter. And if we want to, we can put in a loop:
> AT> (defn fibonacci [n]
> AT> (loop [x n result 1]
> AT> (if (zero? x)
> AT> result
> AT> (recur (dec x) (* x result)))))
>
> AT> And although I am doing CL since 6 years and Clojure just 4 months or
> AT> so, this looks cleaner in my opinion than the CL version.
>
> than version you've wrote in CL. i would write it like this:
>
> (defun factorial (n)
> (loop with p = 1
> for i from 1 to n
> do (setf p (* p i))
> finally (return p)))
>
> IMHO that's cleaner.

After some months of functional programming I don’t like code with setf
anymore. But your solution is working perfectly, and it’s only my taste,
not a technical issue.

In Clojure I would probably do:
(defn factorial [n] (apply * (range 1 (inc n))))

or if I want the set of all factorials, then
(def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))

This is my favourite. No function needed, just a variable bound to an
infinite lazy sequence.
This also has the nice advantage of being automatically memoized.


> or if i absolutely must use recursion:
>
> (defun factorial (n &optional (result 1))
> (if (zerop n)
> result
> (factorial (- n 1) (* n result))))
>
> it is even shorter than your Clojure thing.

It’s true, but I don’t like this solution at all, because it introduces
an optional argument which can’t be used at the user site.
Peter Seibel calls this a leaky abstraction.
For hobby programming it is okay, but a clean solution would be
(defun factorial (n)
(labels ((helper (n result)
(if (zerop n)
result
(helper (1- n) (* result n)))))
(helper n 1)))

Slobodan Blazeski

unread,
Feb 14, 2009, 8:42:38 AM2/14/09
to

There was a joke about NASA(or RFSA) spending a lot of money for pens
that could write in zero gravity. When they announced their
masterpiece reporters asked them why they don't use pencils?

cheers
bobi

Slobodan Blazeski

unread,
Feb 14, 2009, 8:59:44 AM2/14/09
to
On Feb 14, 12:56 pm, "Alex Mizrahi" <udode...@users.sourceforge.net>
wrote:

>  ??>> oh yes, it is very healthy (for a functional language!) to have
>  ??>> "recur" special operator instead of normal tail recursion because of
>  ??>> JVM deficiency.
>
>  AT> It's true, it's healthy to have recur.
>  AT> I agree that it is not nice that the JVM does not have tail recursion
>  AT> yet. But in practice that is not a real issue, as recur is available.
>
> this reminds me a soviet anecdote: when there is no meat in the butcher's
> shop (it was often the case)
>  they  place an announcement at the shop's door: "there is no necessity in a
> meat today".
> are you as brainwashed as soviet's?
I'm afraid he is. If you still feel the urge to reason with him read
his posts in Making Lisp Popular thread.
http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/be5630a07e123df2/86c5dd4ef015ef37?#86c5dd4ef015ef37

>
> recursion is not limited to the cases when you just call current function in
> a tail-call fashion. in functional
> programming often you need to call function in an alternating fashion -- foo
> calls bar, bar calls foo back
> etc. and recur simply cannot do this. it can only emulate simple loops.
>
> educate yourself:http://en.wikipedia.org/wiki/Mutual_recursion
>
>  AT> Let's look at this unreadable mess in CL:
>
>  AT> (DEFUN Y (F)
>  AT>   (  (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G  G)) H)))
>  AT>    #'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G  G))
>  AT> H)))))
>
> this is a piece of cheap propaganda, i can't believe you're writing this
> seriously.
> you've tried hard to make it looks like an unreadable mess, and now you
> claim it is unreadable mess.
> whoa. NOBODY WRITES CODE LIKE THIS.
Above is just a Kent Pittman historical perspective code taken out of
context.The more I read Mr Thieme posts the more I believe that he has
a spamming frog disorder, uncurable desease I'm afraid.


cheers
bobi

Raffael Cavallaro

unread,
Feb 14, 2009, 9:54:11 AM2/14/09
to
On 2009-02-14 07:15:10 -0500, André Thieme
<address.good.un...@justmail.de> said:

> First of all, I would like to mention that recur also has no disadvantages.

It can't be used for mutual recursion. Common Lisp's labels can;
scheme's letrec can. Clojure needs a separate piece of
work-around-the-jvm syntax for mutual recursion.

--
Raffael Cavallaro, Ph.D.

Alex Mizrahi

unread,
Feb 14, 2009, 10:34:29 AM2/14/09
to
AT> First of all, I would like to mention that recur also has no
AT> disadvantages. .... But the fact that the JVM currently does not
support tail call opt.

if you compare Clojure without recur to Clojure with recur, obviously recur
will be seen as an advantage. but if you compare Clojure to CL, you will
find recur quite limited, and thus having recur INSTEAD of recursion is a
disadvantage.

AT> or if you spot it somewhere while flying
AT> over your sources, you immediately see “Ah, here we have a
recursive
AT> call”.

it is highly subjective, it seems to me that recur is less readable because
it
makes harder to see what is recur'ed -- one might think it calls outer
function
while it calls inner. typically explicit is better than implicit.


Alex Mizrahi

unread,
Feb 14, 2009, 10:38:29 AM2/14/09
to
AT> First of all, I would like to mention that recur also has no
AT> disadvantages.

btw, we might compare "recur" to a compiler that will automatically
detects such cases of recursion and optimizes them accordingly.
(i believe most compilers do this, even C ones). then one might argue
that recur has a disadvantage making code less readable, as it might
be hard to see what is called


André Thieme

unread,
Feb 14, 2009, 10:44:33 AM2/14/09
to
Slobodan Blazeski schrieb:

> On Feb 14, 12:56 pm, "Alex Mizrahi" <udode...@users.sourceforge.net>
> wrote:
>> ??>> oh yes, it is very healthy (for a functional language!) to have
>> ??>> "recur" special operator instead of normal tail recursion because of
>> ??>> JVM deficiency.
>>
>> AT> It's true, it's healthy to have recur.
>> AT> I agree that it is not nice that the JVM does not have tail recursion
>> AT> yet. But in practice that is not a real issue, as recur is available.
>>
>> this reminds me a soviet anecdote: when there is no meat in the butcher's
>> shop (it was often the case)
>> they place an announcement at the shop's door: "there is no necessity in a
>> meat today".
>> are you as brainwashed as soviet's?
> I'm afraid he is. If you still feel the urge to reason with him read
> his posts in Making Lisp Popular thread.
> http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/be5630a07e123df2/86c5dd4ef015ef37?#86c5dd4ef015ef37

I don’t understand why you are so angry.
You said some bullshit and were not able to defend it. Instead of going
back and correct yourself, such as:
"Ok ok, sorry. I wanted to say that it is easier to *implement* Lisps in
their own VM instead of the JVM".
But no, you need to stick with the word "better", although this makes no
sense at all.
I see that you are lurking around here since long time, abusing other
people, claiming that they know *nothing* about X and Y, even when this
is not correct. Why not trying to be more rational?


>> recursion is not limited to the cases when you just call current function in
>> a tail-call fashion. in functional
>> programming often you need to call function in an alternating fashion -- foo
>> calls bar, bar calls foo back
>> etc. and recur simply cannot do this. it can only emulate simple loops.
>>
>> educate yourself:http://en.wikipedia.org/wiki/Mutual_recursion
>>
>> AT> Let's look at this unreadable mess in CL:
>>
>> AT> (DEFUN Y (F)
>> AT> ( (LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G)) H)))
>> AT> #'(LAMBDA (G) #'(LAMBDA (H) (FUNCALL (FUNCALL F (FUNCALL G G))
>> AT> H)))))
>>
>> this is a piece of cheap propaganda, i can't believe you're writing this
>> seriously.
>> you've tried hard to make it looks like an unreadable mess, and now you
>> claim it is unreadable mess.
>> whoa. NOBODY WRITES CODE LIKE THIS.
> Above is just a Kent Pittman historical perspective code taken out of
> context.

OMG, the context is that recur allows anon functions to call themselves.
The y-combinator also allows this. This absolutely *is* context.


> The more I read Mr Thieme posts the more I believe that he has
> a spamming frog disorder, uncurable desease I'm afraid.

Again, nonsense.
You are angry and aggressive, and it simply is not needed.
This is a phenomenon that I observe with many people when they are out
of arguments. I invite you to join rational discussions about Lisp.
No reason to feel unsecure when a new and promising Lisp dialect shows up.
*That* would be really being brainwashed.
Defending CL for every price, no matter how bad it sucks.

Marco Antoniotti

unread,
Feb 14, 2009, 11:06:13 AM2/14/09
to
On Feb 14, 1:52 pm, André Thieme <address.good.until.
> Well, it’s from Kent Pitman.http://www.nhplace.com/kent/Papers/Technical-Issues.html

As in

(defun factorial (n) (apply '* (iota 1 n)))

It isn't very compelling...

> or if I want the set of all factorials, then
> (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))
>
> This is my favourite. No function needed, just a variable bound to an
> infinite lazy sequence.
> This also has the nice advantage of being automatically memoized.

As in

(defparameter fibs (streams:cat 0 1 (streams:map-stream '+ fibs
(streams:tail fibs)))

... again this is not very compelling either. This is SICP.

Cheers
--
Marco


André Thieme

unread,
Feb 14, 2009, 11:17:13 AM2/14/09
to
Alex Mizrahi schrieb:

> AT> First of all, I would like to mention that recur also has no
> AT> disadvantages. .... But the fact that the JVM currently does not
> support tail call opt.
>
> if you compare Clojure without recur to Clojure with recur, obviously recur
> will be seen as an advantage. but if you compare Clojure to CL, you will
> find recur quite limited, and thus having recur INSTEAD of recursion is a
> disadvantage.

Yes, Clojure with recur (TCO) vs Clojure without it (no TCO) looks better.
However, in my opinion, if I have to chose between:
a) Clojure with recur on a JVM that supports TCO
vs
b) Clojure without recur on a JVM that supports TCO,

then I vote for a).


> AT> or if you spot it somewhere while flying
> AT> over your sources, you immediately see "Ah, here we have a
> recursive
> AT> call".
>
> it is highly subjective, it seems to me that recur is less readable because
> it makes harder to see what is recur'ed -- one might think it calls outer
> function while it calls inner. typically explicit is better than implicit.

Recur jumps always to the most inner point, so it is always clear at the
first glimpse to where it will recur.
Also the compiler will make sure that one uses it only in tail position.
To me it happened already that I got an error message of not using recur
in TP.

Without talking specifically to you Alex, I observed that some CLers try
to jump on the recur issue, as this is in their eyes the weakest point.
The ironical thing about this is that at leats to my knowledge 100% of
those people actually never programmed in Clojure, and experience them-
selves how good/bad the situation really is.

While I fully agree that it is a weak point of the JVM that it does not
support TCO yet, I did not stumble upon any problematic situation yet.
Even when I asked people for creating artificial examples that can not
be easily solved with recur/trampolines, I did not see anything yet.

Lisp really has no easy stand today as it seems.
People see that it has a lot of parens and without trying it, they de-
cide it is nothing for them.
Clojure now reduced the amount of parens, but people now hear about
tail calls and argue that Clojure Lisp is not for them. What I find a
bit sad is that most of them are CLers.

Anyway, thanks for letting me know your opinions about recur.

Tamas K Papp

unread,
Feb 14, 2009, 11:27:52 AM2/14/09
to
On Sat, 14 Feb 2009 17:17:13 +0100, André Thieme wrote:

> Lisp really has no easy stand today as it seems. People see that it has
> a lot of parens and without trying it, they de- cide it is nothing for
> them.
> Clojure now reduced the amount of parens, but people now hear about tail
> calls and argue that Clojure Lisp is not for them. What I find a bit sad
> is that most of them are CLers.

I have only had cursory look at Clojure, so I don't know much about
it. My guess is that both Clojure/CL would make it into the top 5
languages for most CL/Clojure users. So one might prefer CL over
Clojure and argue about tail calls etc, but still strongly prefer
Clojure to, say, Java or (horribile dictu) F#. Given this, I don't
see anything sad with people preferring Clojure/CL over CL/Clojure --
not all changes are innovations for everyone.

Tamas

Alex Mizrahi

unread,
Feb 14, 2009, 11:31:22 AM2/14/09
to
AT> (fun 1 2 3) but instead
AT> #(fun 1 2 3) when you use trampolines, and it is stack-safe again.

how does it work? does it inline fun instead of calling it, or what?
if it works via inlining, that it is not a solution..

AT> Still I would stop using trampolines as soon the JVM will
AT> introduce that kind of optimization.

if trampolines somehow automagically fix the problem with "one
keystroke", then why compiler cannot detect such situation and insert
these "#"? it seems you're not saying all the truth.. ot Clojure's compiler
is dumb

??>> NOBODY WRITES CODE LIKE THIS.

AT> Well, it's from Kent Pitman.
AT> http://www.nhplace.com/kent/Papers/Technical-Issues.html

it was an example of code that is not elegant in Lisp2, this is not
a code in CL's style. btw, i haven't seen any practical use of Y combinator
so far, even in Haskell they just use their analog of LABELS.


??>> (labels ((sum (x acc) (if (zerop x)
??>> acc
??>> (sum (- x 1) (+ acc x)))))
??>> (sum 200 0))

AT> Where is the anonymous function here?
AT> recur allows you anon functions to call themself.

and why do we need one here? code is pretty readable as it is.

we could make anonymous functions with recur in CL
with a simple macro like this:

(defmacro lambdarec (args &body body)
`(labels ((recur (,@args) ,@body))
(function recur)))

and it will work just like in Clojure:

(funcall (lambdarec (x accum)
(if (zerop x)
accum
(recur (- x 1) (+ accum x))))
200 0)

(except in function position, unfortunately CL does not macroexpand it).
but i don't think this is even remotely useful..

??>> sure it does, because it was not tail calls. you should admit you know
??>> very little about functional programming, as you do not know even
??>> basics.

AT> I see no reason to admit that at this point, as I was fully aware about
AT> this.

why did you complain about stack overflow then? either you're an idiot,
or you're going to treat me like an idiot, i see no other possibilities
here.

if you write random bullshit like this into newsgroups, you'll get no
respect.

AT> What I was doing was talking about anon functions calling themselves.

"anon functions calling themselves" is not a benefit of itself, it is not
obvious
that it allows one to solve real programming tasks even a bit better.

AT> Let's say you have a Lisp with no support for TCO.
AT> Then you would also be forced to wait until your vendor fixes it.

if Lisp does not have support for TCO, then probably it has good support
for imperative programming -- like tagbody and mutable variables, that can
be used to implement quite a hairy stuff.

as i understand, Clojure does not have support for imperative programming
constructs, and neither it has good support for functional programming
constructs.
this makes me think that it is not such a good language.

AT> And of course one can add recur also in CL. Everything that Clojure has
AT> can be done in CL and vice versa.

emm, we can add recur from CL itself, but you cannot add TCO from Clojure
itself, can you?

perhaps you can write some smart compiler that will do it for you, but
that would be really hard (and thus impractical), while adding recur into CL
is trivial.

AT> or if I want the set of all factorials, then
AT> (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))

AT> This is my favourite.

why don't you use Haskell then? :)

AT> After some months of functional programming I don't like code with setf
AT> anymore.

one can do it with internal LOOP's variable rebinding feature, which i think
is semantically equivalent to recur's variable rebinding:

(loop for i from 1 to n

for result = 1 then (* result i)
finally (return result))

André Thieme

unread,
Feb 14, 2009, 11:40:40 AM2/14/09
to
Marco Antoniotti schrieb:

>> In Clojure I would probably do:
>> (defn factorial [n] (apply * (range 1 (inc n))))
>
> As in
>
> (defun factorial (n) (apply '* (iota 1 n)))
>
> It isn't very compelling...
>
>> or if I want the set of all factorials, then
>> (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))
>>
>> This is my favourite. No function needed, just a variable bound to an
>> infinite lazy sequence.
>> This also has the nice advantage of being automatically memoized.
>
> As in
>
> (defparameter fibs (streams:cat 0 1 (streams:map-stream '+ fibs
> (streams:tail fibs)))
>
> ... again this is not very compelling either. This is SICP.

All of my examples can of course be translated into CL, Scheme or
other turing complete programming langauges.
I would not be surprised if all CL programs could be translated into
Clojure as well.

Anyway, I see the strong point of Clojure in offering all these tools
in the core language. This means that everyone will use them.
The iota function has, no idea, 92 users in the world.
Probably 7 who use it regularily.
(I don’t mean these numbers literally, but I have not seen that anyone
used those, neither in open source, nor in my professional work).

If something ships with the language then in most cases everyone
will use that, instead of trying an alternative library.
Now there are 26 pattern matching libs for CL, and they have an
accumulated number of 17 users worldwide.
CLers like if the language offers already good bit of reusable code.
Otherwise they may have become Scheme users.
Clojure goes some steps forward. Unlike CL it is not bound to limit
itself with the functions defined by the HS.
Those functions are available to all Clojure developers, and there is
a big agreement to use them. This makes code and libs more compatible
and much easier to read.

Aatu Koskensilta

unread,
Feb 14, 2009, 11:37:36 AM2/14/09
to
"Alex Mizrahi" <udod...@users.sourceforge.net> writes:

> btw, i haven't seen any practical use of Y combinator so far, even
> in Haskell they just use their analog of LABELS.

What is the Haskell analogue of LABELS?

--
Aatu Koskensilta (aatu.kos...@uta.fi)

"Wovon man nicht sprechen kann, darüber muss man schweigen"
- Ludwig Wittgenstein, Tractatus Logico-Philosophicus

Tobias C. Rittweiler

unread,
Feb 14, 2009, 11:46:46 AM2/14/09
to
Aatu Koskensilta <aatu.kos...@uta.fi> writes:

> What is the Haskell analogue of LABELS?

A better question would be what is the Haskell analogue of FLET? :-)

-T.

André Thieme

unread,
Feb 14, 2009, 12:14:33 PM2/14/09
to
Alex Mizrahi schrieb:

> AT> (fun 1 2 3) but instead
> AT> #(fun 1 2 3) when you use trampolines, and it is stack-safe again.
>
> how does it work? does it inline fun instead of calling it, or what?
> if it works via inlining, that it is not a solution..

http://code.google.com/p/clojure/source/browse/trunk/src/clj/clojure/core.clj?=1276#3744


> AT> Still I would stop using trampolines as soon the JVM will
> AT> introduce that kind of optimization.
>
> if trampolines somehow automagically fix the problem with "one
> keystroke", then why compiler cannot detect such situation and insert
> these "#"? it seems you're not saying all the truth.. ot Clojure's compiler
> is dumb

http://groups.google.com/group/clojure/msg/3addf875319c5c10


> AT> I see no reason to admit that at this point, as I was fully aware about
> AT> this.
>
> why did you complain about stack overflow then? either you're an idiot,
> or you're going to treat me like an idiot, i see no other possibilities
> here.

No problem, I will tell you what the other possibility is:
I was making a sarcastic comment and you missed that. I gave an example
about how an anon function can call itself.


> if you write random bullshit like this into newsgroups, you'll get no
> respect.

I am sure that with "this" you were referring to your own sentence.
Btw, I am not here for getting respect from random people on c.l.l.
Some people though need that... at least one source of respect and
attention.
(not referring to you!)


> if Lisp does not have support for TCO, then probably it has good support
> for imperative programming -- like tagbody and mutable variables, that can
> be used to implement quite a hairy stuff.

Yes, for CL it’s good.
And even today some small programs can be written in imperative style.


> as i understand, Clojure does not have support for imperative programming
> constructs, and neither it has good support for functional programming
> constructs.
> this makes me think that it is not such a good language.

Ah oki, you never tried Clojure and heared some rumors somewhere.
It’s our human property to build up an opinion, although we don’t know
enough facts to have the right to have an opinion.
Just see the people who look into Lisp. Only a minority like us stayed.

I have no problems at all if people don’t like Clojure. I personally
just like it way more than CL. Basically every problem in my
professional programming I can solve in a more productive way. And this
does not always have to do with the sheer mount of code available for
the JVM.
But CL stays on rank 2, with a noticable distance to 1.
If Rich continues to work so hard on Clojure, it will soon outnumber the
CL users. Evolution in progress.


> AT> And of course one can add recur also in CL. Everything that Clojure has
> AT> can be done in CL and vice versa.
>
> emm, we can add recur from CL itself, but you cannot add TCO from Clojure
> itself, can you?
> perhaps you can write some smart compiler that will do it for you, but
> that would be really hard (and thus impractical), while adding recur into CL
> is trivial.

Yes.
I think it makes most sense to just use what is available today.
I have not met on person who used Clojure for a few months who complained
about any problems with recur or recursion in Clojure.
It is much more a fantasy issue of people who actually never
touched Clojure. Since I use it every day (be it professionally
or for private stuff) I find no way of going back to CL, which
by now feels really old to me.


> AT> or if I want the set of all factorials, then
> AT> (def fibs (lazy-cat [0 1] (map + fibs (drop 1 fibs))))
>
> AT> This is my favourite.
>
> why don't you use Haskell then? :)

Because I can do it in Lisp, which I like.
Lisp can be used more practical, as so many libs from the JVM are available.
But Haskell is very cool, and I am glad that Clojure learned some
concepts from it. Makes sense.

André Thieme

unread,
Feb 14, 2009, 12:34:09 PM2/14/09
to
Tamas K Papp schrieb:

What you present sounds very realistic to me.
I myself still have a nice CL project (about AI) that I will continue
to develop with SBCL.

What I find sad is that some CL users have a really negative opinion
about Clojure.
I can understand it when looking at it from this POV:
since years I am reading c.l.l, and every few weeks someone jumps in
and explains us how to improve Lisp, how to make it more popular, how
to remove parens, and such. Every few months some guy presents his own
Lisp. Those new Lisps basically all suck very very bad.
When I read about Clojure, I did not look at it all all. Why should I?
Another guy who thinks he can produce something useful!

We, who we read c.l.l know these situations, and they "reprogrammed"
us, so that we automatically think a new dialect of Lisp just has to
be bullshit, like the 37 others were, that were presented in the last
years.

Out of curiosity I visited one day the Clojure homepage, after a friend
suggested me to do it. It took only moments to get me hooked.
I watched the movies on the website and read it completely, and began
to install/use it. Over the course of some days I read the sources of
Clojure and realized that for me personally it is what I was waiting
for.
Immediately I understood that Clojure is the ticket for thousands of
Lispers to get a Lisp job. For now that can be done by sneaking into
small Java companies and offer them the productivity of a Lisp in their
environment. Only a subset of those companies will agree on that. But
a subset of hundreds to thousands of Java companies per (big) city
is still substantial enough to have a realistic chance.

So, back to the issue:
by repeating over years again and again that other Lisps suck and that
CL rules some here came to believe this, as if it were an objective
fact.
Some see a "danger" in Clojure. As long it is not CL, it must be bad.
This is too religious for me. Heck, programming languages are tools.

Obviously, I can’t speak for all CLers. Several experts already use
Clojure and have a different POV as I have.
Clojure is Lisp, it is an evolutionary step, CL does not suddenly
become bad only because Clojure exists, and Lispers should not be
scared by it, or "fight" against it without even having tried it out
for some time.

William James

unread,
Feb 14, 2009, 1:57:11 PM2/14/09
to
André Thieme wrote:

> Besides that, recur does in fact have three advantages:
> 1. it allows anon functions to call recurse, they can call themselves
> 2. it blocks you from accidently not doing tail calls, because the
> compiler can check if recur really is in the tail position
> 3. as a minor advantage I want to add, that it is easy to search in
> code for occurrences of “recur”, or if you spot it somewhere while
> flying over your sources, you immediately see “Ah, here we have a
> recursive call”.

+1

ANS Forth uses "recurse":

: fac dup 2 < if drop 1 else dup 1- recurse * endif ;


>
> So even when the JVM will support one day tail call optimization,
> recur will not go.
> Jon Harrop indicated that this (adding TCO) is happening at the moment
> for the OpenJDK, and as Sun works on their own functional programming
> language “Fortress” I suppose they will also be interested in adding
> it. I will definitly continue to use recur. What I will stop to use
> are trampolines.
>
>
> > but of course a real loop, not recursion, is the common lisp norm:
> >
> > (loop for i upto 12345678 summing i)
>
> Yes, loop is nice. In principle it’s what I would do in CL as well,
> although for this specific case I would really prefer to directly
> calculate that number via (defn sum [n] (+ (/ n 2) (/ (* n n) 2))).
> In Clojure I could do:
> (apply + (range 12345678)))
>
> or use reduce instead of apply.

Wouldn't it be inefficient to create a list or array of size 12345678?

Slobodan Blazeski

unread,
Feb 14, 2009, 2:30:34 PM2/14/09
to
On Feb 14, 4:44 pm, André Thieme <address.good.until.

2009.may...@justmail.de> wrote:
> Slobodan Blazeski schrieb:
>
>
>
>
>
> > On Feb 14, 12:56 pm, "Alex Mizrahi" <udode...@users.sourceforge.net>
> > wrote:
> >>  ??>> oh yes, it is very healthy (for a functional language!) to have
> >>  ??>> "recur" special operator instead of normal tail recursion because of
> >>  ??>> JVM deficiency.
>
> >>  AT> It's true, it's healthy to have recur.
> >>  AT> I agree that it is not nice that the JVM does not have tail recursion
> >>  AT> yet. But in practice that is not a real issue, as recur is available.
>
> >> this reminds me a soviet anecdote: when there is no meat in the butcher's
> >> shop (it was often the case)
> >>  they  place an announcement at the shop's door: "there is no necessity in a
> >> meat today".
> >> are you as brainwashed as soviet's?
> > I'm afraid he is. If you still feel the urge to reason with him read
> > his posts in Making Lisp Popular thread.
> >http://groups.google.com/group/comp.lang.lisp/browse_thread/thread/be...

>
> I don’t understand why you are so angry.
> You said some bullshit and were not able to defend it. Instead of going
> back and correct yourself, such as:
> "Ok ok, sorry. I wanted to say that it is easier to *implement* Lisps in
> their own VM instead of the JVM".
> But no, you need to stick with the word "better", although this makes no
> sense at all.
Yes it does.
http://www.mindspring.com/~mfpatton/sketch.htm

> I see that you are lurking around here since long time, abusing other
> people, claiming that they know *nothing* about X and Y, even when this
> is not correct. Why not trying to be more rational?
Rational? I don't want spammers and fundamentalists who can't defend
their positions with code, but instead are going for under the belt
tricks spread nonsense in this group. What could be more rational
then that? You don't want to hear anything except only the best about
Clojure. Ok Clojure has some nice things, I agree, but its a frickin'
language it has flaws too. And recur and stupid tarmplones are one of
them. Instead of writing nonsense go and help Hinley with fixing the
implementation. The problem could be fixed, you could use CPS or some
other technique that are used by implementations running on JVM but
still manage to use recursion without jumping through hoops.

>
>
>
> >> recursion is not limited to the cases when you just call current function in
> >> a tail-call fashion. in functional
> >> programming often you need to call function in an alternating fashion -- foo
> >> calls bar, bar calls foo back
> >> etc. and recur simply cannot do this. it can only emulate simple loops.
>
> >> educate yourself: