CAR, CDR, and Lisp...
mschaef.com
mschaef.com
In miniKanren the concept of a "pair" is useful because the right hand side of a sequence in miniKanren might be a logic variable and not a sequence.
What's lovely is how simple this is. I can define a custom iteration protocol (LogicSeq) which define two functions - lfirst, lnext. Then I create a custom sequence type that returns a legitimate Sequence or logic variable for lnext.
To bring all the other collections into this protocols is 4 lines of code:
(extend-protocol LConsSeq
clojure.lang.IPersistentCollection
(lfirst [this] (clojure.core/first this))
(lnext [this] (clojure.core/next this)))
Voila! Custom iteration!What's even more amazing is that there's hardly a perf hit. The JVM sees it's just a pass through call for real Clojure collections.
Fun stuff :)
When I first started learning scheme I was much more challenged by the rest of the cognitive assault - tail recursion is "free", call/cc or continuations, the shift to thinking in "higher order" mode, macros, being able to effectively define your own syntax.
Syntax isn't any more important than the other things you mention, but it's certainly as important. Syntax is not mere window dressing. Like punctuation in written language, there's good and bad, confusing and obvious, opaque and transparent, and it will be judged and analyzed like anything else.
See http://www.franz.com/support/documentation/8.2/ansicl/dicten...
I would have to stop and really try to grok what list item it was referring to. Not saying that that is a bad thing, just an observation.
Is there a common way of thinking that makes it easier to comprehend, or is it just something that comes with experience?
I've used Lisp for a while, and where I tend to wind up on these composite forms is that I use a few of the simpler composites, but tend to switch to either destructuring-bind or some other data type if it gets too complex. (Practically speaking, that means anything much beyond 'car', 'cdr', and 'cadr' gets refactored.)
I've heard of Common Lisp in passing, does it have a more friendly syntax?
It's also worth noting that the primary disadvantage of car and cdr, their arbitrariness, fades as one becomes familiar with the language.
In most implementations , I can do
(cadar (list (list 1 2 3))) -> 2
vs
(first (rest (first (list (list 1 2 3))))) -> 2
I find the car and cdrs in Racket very very convenient.
Reference:
http://docs.racket-lang.org/reference/pairs.html?q=pair%20ac...