To be poignant at the risk of sounding stupid, I thought Rich had some
great ideas.
I've been trying to mine through the group postings via google groups
but with little success besides the odd off-hand mention of Clojure.
So in order to quiet my confusion and keep myself on the path to true
Nirvana, I was hoping to illicit some feedback from the CL community
on some of the features of Clojure and whether they may ever find their
way into CL itself or some implementation thereof.
1. seqs -- Seems like a great idea. PCL suggests I should only ever
consider using first/last anyway so it seems only a natural extension
to me that CL would consider unifying all sequence types behind an
abstracted API.
I'm not asserting that this should happen, but I'm curious why it
hasn't or if there is a good reason not to.
2. Namespaces -- I'm just starting to grok packages which, to me, seem
like a bit of a headache. Rich mentioned in his talk that the package
system prevents CL from loading lisp source files without implementing
a reader in the application which prevents the interning of
symbols... okay...
Is this a big deal in the CL community or is there a justification for
packages that keeps them around?
I think those are the main points that caught my interest in Clojure.
The concurrency stuff looks nice and neat, but isn't really all that
important to me at this point (though feel free to discuss it if you
feel it's an impportant idea to consider).
I'm trying to stay focused on learning pure CL before I worry about
different implementations... however, Clojure seems to offer some
fundamental differences that appear to someone new to Lisp as being
rather "cool." Any assistance in clearing the air would be greatly
appreciated. :)
You misread. Or miswrote. The names are archaic (and we like them that
way), not the things themselves.
>
> To be poignant at the risk of sounding stupid, I thought Rich had some
> great ideas.
>
> I've been trying to mine through the group postings via google groups
> but with little success besides the odd off-hand mention of Clojure.
>
> So in order to quiet my confusion and keep myself on the path to true
> Nirvana, I was hoping to illicit some feedback from the CL community
> on some of the features of Clojure and whether they may ever find their
> way into CL itself or some implementation thereof.
>
> 1. seqs -- Seems like a great idea. PCL suggests I should only ever
> consider using first/last anyway so it seems only a natural extension
> to me that CL would consider unifying all sequence types behind an
> abstracted API.
Good lord, no. A linked list is not a vector.
>
> I'm not asserting that this should happen, but I'm curious why it
> hasn't or if there is a good reason not to.
>
> 2. Namespaces -- I'm just starting to grok packages which, to me, seem
> like a bit of a headache. Rich mentioned in his talk that the package
> system prevents CL from loading lisp source files without implementing
> a reader in the application which prevents the interning of
> symbols... okay...
>
> Is this a big deal in the CL community
no.
> or is there a justification for
> packages that keeps them around?
Big applications, where names would start to clash?
>
>
> I think those are the main points that caught my interest in Clojure.
> The concurrency stuff looks nice and neat, but isn't really all that
> important to me at this point (though feel free to discuss it if you
> feel it's an impportant idea to consider).
>
> I'm trying to stay focused on learning pure CL before I worry about
> different implementations... however, Clojure seems to offer some
> fundamental differences that appear to someone new to Lisp as being
> rather "cool." Any assistance in clearing the air would be greatly
> appreciated. :)
Well, you are not the first person to like Clojure, if that helps.
I am not having any problems with CL, so I do not look around much.
kt
> I just finished watching Rich Hickey's presentation on his new Lisp
> dialect and it provoked some thought in me.
I watched that presentation recently too. I think Clojure has a lot of
neat stuff, but until I'm looking to do some concurrent programming or
want to be on the JVM, I don't think I'll mess with it. Though I am more
impressed by Clojure now than I was initially. Its generification of
sequences, its literal notation for vectors, hashes, and more, its (:key
hash-table) / (hash-table :key) syntax for lookups, the addition of
metadata, and other features are all pretty cool. But even taken all
together, they don't strike me as cause to migrate. And I have a nagging
feeling that I would miss some things (CLOS, conditions, CL's iteration
constructs, perhaps) if I did. Clojure may be killer for some
applications though, and I do hope I get an excuse to do a project in
it.
He does.
> I've been trying to mine through the group postings via google groups
> but with little success besides the odd off-hand mention of Clojure.
So far, I thought Hans Hubner's summary was best:
http://netzhansa.blogspot.com/2008/10/trying-clojure.html
> So in order to quiet my confusion and keep myself on the path to true
> Nirvana, I was hoping to illicit some feedback from the CL community
> on some of the features of Clojure and whether they may ever find their
> way into CL itself or some implementation thereof.
>
> 1. seqs -- Seems like a great idea. PCL suggests I should only ever
> consider using first/last anyway so it seems only a natural extension
> to me that CL would consider unifying all sequence types behind an
> abstracted API.
FSet is a CL approximation of Clojure's data structures. It doesn't
enjoy the tight integration with the reader; but it provides
"immutable" data structures in CL much as Clojure provides them in Java.
http://common-lisp.net/project/fset/
> 2. Namespaces -- I'm just starting to grok packages which, to me, seem
> like a bit of a headache. Rich mentioned in his talk that the package
> system prevents CL from loading lisp source files without implementing
> a reader in the application which prevents the interning of
> symbols... okay...
>
> Is this a big deal in the CL community or is there a justification for
> packages that keeps them around?
CL has a bunch of things that rely on each other, sometimes in a
haphazard manner; but they do work -- once you figure out what they do
and how to use them. While namespaces were developed for static
systems (e.g. C++ and Java), packages were developed for dynamic ones;
certain static behaviors like "use f() from one of my enclosing
namespaces" lose their luster when you recompile code and a different
f() gets used. I still think the inability to *purely* (i.e. without
function trampolines or reader macros) rename (or alias) a symbol is a
defect in CL.
As for Rich's note about packages and the reader: I consider that to
be a (hindsight) defect in the CL reader, not in packages per se. As
each symbol is parsed, the reader eagerly evaluates it, binding it to
symbols in the current package, creating new symbols as needed. This
is an old standard (affecting shell scripts, perl, BASIC, etc.) of
declaring variables upon first use, and it can be a pain in certain
situations. Thus Rich's comment. But this doesn't affect most
programs much at all.
This reader issue reminded me of one of Pitman's stories:
http://www.nhplace.com/kent/PS/Ambitious.html
The ideal reader might be easier to implement with immutable data
structures...
> I think those are the main points that caught my interest in Clojure.
> The concurrency stuff looks nice and neat, but isn't really all that
> important to me at this point (though feel free to discuss it if you
> feel it's an impportant idea to consider).
Java's concurrency work (e.g. JSR 133) distills many lessons. A major
one being "locks (mutexes) are bad -- atomic operations (e.g.
compare-and-swap) are better". Immutability makes structure sharing
easier, thus decreasing the cost of CAS operations (change the "head"
pointer to the current shallow copy of the old structure). This comes
through in Clojure as refs, commutes, etc.
- Daniel
Sequences are great as well. Use the same api for cons cells, arrays,
name/value collections ... that's pretty cool.
Part of the gigantic CL library isn't there, and it's really missing.
Acces to the java library helps, but it's not quite the same, and a bit
ugly too. That provide a standard way to do gui which just plain works.
Lots of freely available libraries around too.
No reader macros.
Need to define a function before calling it. Or just its name, but still
that's not very friendly.
Namespaces, they do the job. The whole thing isn't as dynamic as CL but
it's very manageable. Multimethods are kind of cool, i still prefer CL
on this.
Documentation is skinny, a lot is missing, no examples, no central index.
All in all very well thought out, but not as deeply as CL.
Sacha
Thanks for the plug!! BTW I am diligently working on the 1.2 release
of FSet, which along with (koff koff) bug fixes and some new features
will finally have a proper tutorial.
Also -- your first sentence risks being misinterpreted as suggesting
that FSet was in some way inspired by Clojure, which is not the case.
FSet was very much inspired by Refine (hmm, I see there's no Wikipedia
page on Refine... must remedy that) which was in turn inspired by
SetL.
-- Scott
> I still think the inability to *purely* (i.e. without
> function trampolines or reader macros) rename (or alias) a symbol is a
> defect in CL.
(define-symbol-macro new-name old-name)
(let ((old-name 42))
new-name)
--> 42
--
__Pascal Bourguignon__ http://www.informatimago.com/
ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.
Indeed, Clojure has a number of very good ideas. The multithreading
model seems especially well thought through. On the downsides, I am not
convinced that access to Java APIs works as smoothly as advertized,
because Java's multithreading follows a very different approach, and I
don't believe you can just blindly throw the two together.
Additionally, Clojure focuses on one paradigm only and neglects others -
it's mostly a purely functional language, and support for other
programming styles is quite limited, at least so far. Some may see this
as an advantage, some as a disadvantage. In that respect, Clojure is
closer to Scheme than to Common Lisp.
A new language with good support for parallel programming which is much
closer in spirit to Common Lisp is Fortress, except for that fact that
it's not a Lisp. ;)
Pascal
--
Lisp50: http://www.lisp50.org
My website: http://p-cos.net
Common Lisp Document Repository: http://cdr.eurolisp.org
Closer to MOP & ContextL: http://common-lisp.net/project/closer/
>
> 1. seqs -- Seems like a great idea. PCL suggests I should only ever
> consider using first/last anyway so it seems only a natural extension
> to me that CL would consider unifying all sequence types behind an
> abstracted API.
There are a tradeoffs. But it's actually easy to do it in cl. Make a
generic function and overload it for various containers.
Actually it ahs already been done in Gary Kings excellent cl-
containers http://common-lisp.net/project/cl-containers/ and Gary has
a far more firepower:
http://common-lisp.net/project/cl-containers/images/containers.pdf
>
> I'm not asserting that this should happen, but I'm curious why it
> hasn't or if there is a good reason not to.
>
> 2. Namespaces -- I'm just starting to grok packages which, to me, seem
> like a bit of a headache. Rich mentioned in his talk that the package
> system prevents CL from loading lisp source files without implementing
> a reader in the application which prevents the interning of
> symbols... okay...
>
> Is this a big deal in the CL community or is there a justification for
> packages that keeps them around?
>
> I think those are the main points that caught my interest in Clojure.
> The concurrency stuff looks nice and neat, but isn't really all that
> important to me at this point (though feel free to discuss it if you
> feel it's an impportant idea to consider).
I found unmutable languages annoying at best, when I think of
something that in my model needs to be mutated I want it to mutate it
not jump through hoops because someone promised me a Nirvana if I keep
my code mutate free.
>
> I'm trying to stay focused on learning pure CL before I worry about
> different implementations...
Smart move
> however, Clojure seems to offer some
> fundamental differences that appear to someone new to Lisp as being
> rather "cool." Any assistance in clearing the air would be greatly
> appreciated. :)
As someone who's working on his own lisp-like language my advice to
learn cl first (or scheme if that's your thing), and learn it good
before you start criticizing it. It's a mature language with a lot
documentation, libraries and great community.
It's far from ideal, there a lot of things I don't like about it, but
all the languages have their problems, because every language designer
must make a compromises. It's up to you what kind of compromises would
you choose to accept. And don't worry to much about lack of something
in cl it's usually not a big deal, and has been solved someway. For
everything you get you pay with something else.
bobi
Ideal world is a left as an exercise for a reader.
pg
bobi
It's multiparadigm, has a library-provider API which makes the language
extensible, and provides syntactic extensibility (in a very weird way,
but nonetheless...)
It's also strongly influenced by some of the 'historical' extensions for
Common Lisp for parallel programming, like Connection Machine Lisp,
StarLisp and Paralation Lisp.
Ok. Just a theoretical question. If the language is based on s-
expressions is it necessarily lisp?
For example what if Prolog decides to change into something like:
(deffact Father (john tim))
(deffact Father (tim marc))
>(Father john tim)
t
>(Father tim X)
marc
(defrule GrandFather (X Y)
(father X Z)
(father Z y))
(GrandFather john X)
marc
Is the new language lisp or prolog?
bobi
>
> Pascal
>
> --
> Lisp50:http://www.lisp50.org
>
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
> Closer to MOP & ContextL:http://common-lisp.net/project/closer/- Hide quoted text -
>
> - Show quoted text -
Can you treat programs as data?
>> For example what if Prolog decides to change into something like:
>> (deffact Father (john tim))
>> (deffact Father (tim marc))
>>
>>> (Father john tim)
>> t
>>
>>> (Father tim X)
>> marc
>> (defrule GrandFather (X Y)
>> (father X Z)
>> (father Z y))
>> (GrandFather john X)
>> marc
>> Is the new language lisp or prolog?
>
> Can you treat programs as data?
>
>
> Pascal
>
Or more succinctly "Are functions first order objects?"
--------------
John Thingstad
If it has sexps and macros (in addition to first order functions), you
could call it a lisp.
Just having sexps is nice to be able to process it with lisp, but if
it has no macros, it cannot be processed in itself easily.
--
__Pascal Bourguignon__
What functions? There are only facts and rules. Or rules only if you
take facts as rules without a body.
Why not:
(defrule related (Relation X Y)
(Relation X Y))
>(related Father john X)
tim
>(related GrandFather john X)
Marc
>
> --------------
> John Thingstad- Hide quoted text -
>
> - Show quoted text -
>
> --------------
> John Thingstad- Hide quoted text -
>
> Just having sexps is nice to be able to process it with lisp, but if
> it has no macros, it cannot be processed in itself easily.
>
> --
> __Pascal Bourguignon__- Hide quoted text -
This is a very vague question and is very hard to answer. The problem is
that there is no strict definition what is required to consider a
language an instance of the Lisp family. There are some elements that
many people seem to agree on are strictly necessary, but there are other
elements which are not so clear.
For example, it has been debated before whether Scheme is actually a
Lisp or not. (Some say it isn't.) On the other hand, some consider Dylan
an acceptable representative of the Lisp family, although it doesn't
even have an s-expression-based surface syntax.
Such questions are very similar to questions like: Is a chair with three
legs still a chair? What about a chair with two legs? Is the importance
in the function of the chair ("if you can sit on it, it's a chair"), or
is the importance of certain aspects of its appearance ("normally four
legs").
There are philosophical questions behind this: Do you believe in
idealized definitions of entities or concepts, of which concrete
entities are just flawed instances? Or do you believe that the
categories we use are just social constructs that we happen to agree on
for some possibly accidental reasons? Or do you have any other of the
possible views on epistemology? Depending on your view, you will have
different opinions in such matters.
What does that mean?
You said it had only defrule.
How do you expression ` and , in terms of rules?
You're saying that it as sexps.
What are the rules that you can apply on sexps?
Anything useful inside macros to build further rules?
--
__Pascal Bourguignon__
thanks to everybody for their thoughts
bobi
>
> Pascal
>
> --
> Lisp50:http://www.lisp50.org
>
> My website:http://p-cos.net
> Common Lisp Document Repository:http://cdr.eurolisp.org
Omigod, you are serious? About Prolog?!!!! Have you ever programmed
Prolog in anger? I think if you had picked C you would have a better
chance of making the case (but still would fall short). But unification???
I think the closest you could get would be to add lispy qualities to
prolog (macros, first-order rules closing over facts -- which would be
cool because it would make prolog even more impossible to code and I did
not think that was possible) but with an ineluctable paradigm like
unification it can never be anything other than prolog. I would accept
it being called Prolisp for taking the trouble to copy all the right
features, but that's as close as it can get.
my2,kxo
One language to rule them all :)
cheers
bobi
>
> I think the closest you could get would be to add lispy qualities to
> prolog (macros, first-order rules closing over facts -- which would be
> cool because it would make prolog even more impossible to code and I did
> not think that was possible) but with an ineluctable paradigm like
> unification it can never be anything other than prolog. I would accept
> it being called Prolisp for taking the trouble to copy all the right
> features, but that's as close as it can get.
>
> my2,kxo- Hide quoted text -
>
> Omigod, you are serious? About Prolog?!!!! Have you ever programmed
> Prolog in anger? I think if you had picked C you would have a better
> chance of making the case (but still would fall short). But
> unification???
>
> I think the closest you could get would be to add lispy qualities to
> prolog (macros, first-order rules closing over facts -- which would be
> cool because it would make prolog even more impossible to code and I did
> not think that was possible) but with an ineluctable paradigm like
> unification it can never be anything other than prolog. I would accept
> it being called Prolisp for taking the trouble to copy all the right
> features, but that's as close as it can get.
>
> my2,kxo
In all fairness Prolog is not impossible to program, just difficult to
learn. Kinda like putting your head in a food processor and pressing
blend.. Still after a couple a years people have been known to do useful
things with it.
--------------
John Thingstad
I would think, "Omigod! I have been time-transported back to early 2008
when I was using Franz's nice co-mingling of CL with Norvig's
Prolog-In-Lisp!!!!!"
You may be amused to learn I did in fact generate Prolog rules
programmatically /and/ tune the resulting larger scripts by de-duping
and re-ordering programmatically -- the larger scripts got generated
piecemeal and assembled into a larger form in no particular order, which
led to some howlers efficiency-wise--all by treating the Prolog as data.
Costanza will be along shortly to show how that can be done with after
methods in CLOS, but I do not mind learning new tools....hell, I am the
Mongo of technology: "No, no, no. Don't give him a tool he does not
know. It only makes him code faster."
hth,kt
No, I went pretty far with it. You can just look at the prolog classics
and see the language is unprogrammable. The key is how hard it is to do
the simple stuff. Occam's razor applies: why kill yourself doing
everything with unification when multi-paradigm languages are around?
Anyone productive I am sure has Greenspunned procedural forms out of
Prolog, which only proves my point.
my2,kzo
> I am not having any problems with CL, so I do not look around much.
Have you seen this?
http://groups.google.com/group/clojure/msg/069d1489c167ca67
(Not that you need it, I've heard there is a similar library for CL.)
--
-asbjxrn
Thanks Pascal. I'll need to reevaluate my thoughts on this topic.
- Daniel
I have watched fset with some interest. Two things that Rich always
highlights about clojure is the large amount of structure "changed"
collections share, and the shallowness of the implementation trees to
ensure fast lookups (O(log32N) for vectors).
How do you think fset compares?
Matt
--
You definitely intend to start living sometime soon.
I haven't looked closely at Clojure yet, but I can offer the
following.
First off, I would point out that it doesn't really make sense to
supply the base of the logarithm in "O(log n)". Changing the base of
the logarithm simply changes the value by a constant factor, and big-O
notation ignores constant factors. Still, I do understand what he's
saying -- he's using very wide nodes to keep the trees shallow, which
does reduce the cost of indexing by a constant factor compared to
simple binary trees.
Second, obviously that improvement applies only to sequence indexing;
it doesn't help access to the setlike types (sets, maps, and bags).
For the latter, you would still have to do a binary search on the root
node to figure out which subnode to look at, etc., and the comparison
time swamps the time to dereference a pointer. So for the setlike
types, you may as well use a binary tree.
Third, FSet takes a different approach to reducing the tree depth vis-
a-vis simple, homogeneous binary trees. While my nodes are binary, I
use a heterogeneous structure where the leaves are short vectors
(whose length is bounded to 8 normally). So, if D is the depth of a
simple binary tree, the depth of the same tree in Clojure is going to
be about D/5, and in FSet it will be about D-3 (well, between D-2 and
D-3). But I really do this to save space, not so much to save time.
Fourth, I think that random access into a sequence is not that common
a use case (though it does arise, obviously). Iterating over it is
probably more common. I put a fair amount of work into fast iterators
for FSet that give amortized constant time access to each element.
Fifth, I would be concerned that using very wide nodes might make
updates of small collections a lot more expensive. This would be
interesting to measure. Maybe it's not a big deal.
And finally, I expect FSet could be improved further. For instance, I
have seen a paper claiming that functional red/black trees have better
rebalancing performance than the weight-balanced trees I used. (Of
course, rebalancing is an issue only in update, not in access.)
-- Scott
The data structures Clojure uses are persistent variants of Bagwell's
hash array mapped tries [1]. They are suitable for maps and sets,
effectively acting as very shallow tree-based hash tables. Binary
search is not used at each node, instead a constant time bitmap lookup
is used. I've found them to be substantially faster than binary trees.
Rich
[1] http://en.wikipedia.org/wiki/Hash_array_mapped_trie
Ah, very interesting! Thanks for the link!
I suppose at some point I should try implementing HAMTs in CL and
seeing how they compare. I'm afraid it won't happen soon -- too much
else to do.
-- Scott
Thanks everyone for the interesting conversation -- Scott, Rich, and
everyone else.
Lisp claims to be designed in such a way that it can be extended to
provide features not provided by the primitives. This idea, a very
good one, is a bit of an esoteric concept to understand. The
immediately obvious syntactic examples are great and certainly good
enough to get someone new to the language moving forward in their
studies, but they don't really provide the concrete application that
leads to a deeper understanding.
F-set looks like a great example of the extensibility of CL. Of my
limited exposure to all the CL code in the world so far, F-set is
certainly a piece of code every newbie lisper should grok. It makes
the esoteric concept of extensibility concrete. Looking over it and
trying it out has certainly opened my eyes a little.
A very nice endorsement -- thanks! I agree, of course :)
I think the new tutorial I'm writing should make it easier to get
going with FSet. Should be done... well, maybe this weekend, maybe a
couple of weeks yet.
> It makes
> the esoteric concept of extensibility concrete. Looking over it and
> trying it out has certainly opened my eyes a little.
What in particular has stood out for you?
-- Scott
> (map (fn [x] (+ x 1)) '(1 2 3))
(2 3 4)
Even cooler, it works on all sequences:
> (map (fn [x] (+ x 1)) [1 2 3])
(2 3 4)
And you can even use the shorthand:
> (map #(+ % 1) '(1 2 3))
(2 3 4)
> Documentation is skinny, a lot is missing, no examples, no central index.
Couldn't agree with you more there. Well, it's a new language, give it
time.
Regards,
--
Michel S.
He probably meant this:
CL-USER 1 > (mapcar #'f '(1 2 3))
Error: Undefined function F in form (FUNCTION F).
1 (continue) Take the function definition of another function name.
2 Try to take the function definition of F again.
3 Return a value from the call to (FUNCTION F).
4 Set the function definition of F to another function.
5 (abort) Return to level 0.
6 Return to top loop level 0.
Type :b for backtrace, :c <option number> to proceed, or :? for other
options
CL-USER 2 : 1 > (defun f (x) (+ x 1))
F
CL-USER 3 : 1 > :c 2
(2 3 4)
Pascal
--
An interesting related article:
http://briancarper.net/2008/10/31/qt4-in-lisp/
-PM
Actually no, I mean this :
cara.users> (defn atest-function-1 [] (atest-function-2))
java.lang.Exception: Unable to resolve symbol: atest-function-2 in this
context
cara.users> (defn atest-function-2 [] 1)
#=(var cara.users/atest-function-2)
cara.users> (defn atest-function-1 [] (atest-function-2))
#=(var cara.users/atest-function-1)
cara.users> (atest-function-1)
1
So for mutually recursive functions, you would need to def the symbol
atest-function-2 before defining atest-function-1.
Like this :
cara.users> (def test1)
#=(var cara.users/test1)
cara.users> (defn test2 [] (test1))
#=(var cara.users/test2)
cara.users> (defn test1 [] (test2))
#=(var cara.users/test1)
Err don't run this of course =)
Sacha
Er, right. I had your example in mind, but screwed up when writing it
down. ;)
Says Lisp in the title, then talks about clojure! :p
Pretty cool that clojure by virtue of its implementation gets trivial
access to libraries such as Qt. It's a strong selling feature.
AFAIK, gui programming in Lisp is still a pain. If I am dead wrong,
someone please tell me. I'd love to have something that is (at least
conceptually, but hopefully practically) cross-platform.
I'm most of the way through PCL and am loving the language.
You sure did hear of Ltk, didn't you?
I never tried it myself, but (as they say) it seems good enough for
most situations.
-PM
It is, as is Cells-Gtk, Celtk, and Cello tho the latter two make you
want it.
Of course no one is allowed to mention Lispworks, that is a commercial
product, RMS would not be pleased.
hth,kt