This SO answer uses the following syntax in its code snippet:
(lambda (template . ids)
...)
As I understand it, the dot notation is an infix equivalent of cons, and allows to create pairs of values. However I can't understand it in this scenario. Is it a way to pattern-match a pair, e.g. like possible in OCaml?
It seems to be a way to treat a function's arguments as a list, as we can see in the REPL:
> ((lambda (a . b) a) 1 2 3)
1
> ((lambda (a . b) b) 1 2 3)
'(2 3)
Related
I am going through a lisp book and I am looking at mapcar, my question is why is that this is valid:
> (mapcar #'+ '(1 2) '(3 4))
but this one isn't:
(mapcar + '(1 2) '(3 4))
in other words, is there a reason it was decided in lisp that the first argument to mapcar cannot be the function itself, and has to be its name? what purpose does this serve?
is there a reason it was decided in lisp that the first argument to mapcar cannot be the function itself, and has to be its name? what purpose does this serve?
It's just that in something like Common Lisp, the identifier + has multiple different purposes. It is a variable, a function, plus various other things.
writing + means the variable. It is used by the read eval print loop. The value of + is the last form that was evaluated, the value of ++ is the previous value of +, and the value of +++ is the previous value of ++.
To tell Common Lisp that you want to use the function value of an identifier +, one has to write (function +) or shorter #'+.
Thus
(mapcar (function +) '(1 2) '(3 4))
or shorter
(mapcar #'+ '(1 2) '(3 4))
actually means call mapcar with the function + and the lists (1 2) and (3 4)
There are two other ways to use the function +.
(mapcar '+ '(1 2) '(3 4))
Above will have Lisp retrieve the global function value of the symbol +.
Fourth, we can also have the function object be a part of the source code.
#'+ is a function. Common Lisp is what's called a 'lisp 2', which means that it has two namespaces: during evaluation of a compound form, like (+ a b), the function position is looked up in the function namespace while the other positions are looked up in the value namespace. This means that, for instance (append list list) does not make a list whose two elements are the list function: it makes a list whose two elements are whatever list happens to be bound to as a value.
But sometimes you need to get the function value of a name in a value position: an example is in the first argument of mapcar. To do that there is a special operator, function: (mapcar (function +) x y) adds the elements of two lists. Like quote, function has a read macro, which is #'.
(To make this more fun, mapcar actually expects a function designator so you can use the nsme of a function: (mapcar '+ x y) will work, although it is a bit horrid.)
Here is simplified example from book On Lisp by Paul Graham (scheme like syntax).
(define-macro (bar)
(let ((x 10) (y '(1 2 3)) (z 'foo))
`(list ,x `(,',z ,,#y))))
I know how ,,#y should work but not sure exactly how ,',z should work what should be evaluated first and in what order. (I know it should evaluate to symbol foo because it return (10 (foo 1 2 3)) in guile, but I'm not sure what are exact steps).
I need this for my lisp in JavaScript where I have result:
(10 ((unquote z) 1 2 3))
because it just evaluate it form left to right (I'm only handling specially ,, and more commas). How should you evaluate this expression.
There is also this example in the book:
(defmacro propmacro (propname)
`(defmacro ,propname (obj)
`(get ,obj ',',propname)))
how ',', should be evaluated? What are the steps in this case?
Are there any other weird edge cases with backquote/quasiquote? Can you show examples of those and how they should be evaluated and in what order?
How ,',z works is that:
`(list ,x `(,',z ,,#y))))
^ ^
| `- this comma
`- belongs to this backquote
The above comma interpolates, into the inner backquote, the expression ',z or (quote ,z). And that ,z, in turn, belongs to the outer backquote.
Thus the value of z is inserted into (quote ,z) to make (quote <value-of-z>).
Then, effectively, the inner backquote then behaves like `(,'<value-of-z>).
Concretely, suppose z contains the list (+ 2 2). Then we can understand it in terms of the outer backquote inserting (+ 2 2) into the inner one to produce `(,'(+ 2 2) ...). This is now straightforward to understand: when the inner backquote is evaluated, the (+ 2 2) is protected from evaluation, resulting in the object ((+ 2 2) ...).
The pattern ,',',', ... ,',expr is used to obtain a single evaluation of expr during the evaluation of the outermost backquote, such that this value is then propagated through any number of evaluation rounds of the remaining backquote nestings without undergoing further evaluation. There is a kind of "backquote algebra" at play here in which the "commas and quotes cancel out".
You can also visualize the ,',','... as a kind of drill bit that digs through the layers of nesting to allow you plant a literal value anywhere in the structure. E.g.
(defmacro super-nested-macro (arg)
`(... `(.... `(.....`(we simply want arg down here ,',',',arg)))))
The author of super-nested-macro just wants to stick the value of arg into the template, in a position that is buried in three other backquotes. Thus the usual ,arg cannot be used: that comma would be misinterpreted as belonging to the inner-most backquote.
Are there any other weird edge cases with backquote/quasiquote?
One weird edge case in backquote is trying to splice into a dot position:
`(a b c . ,#foo) ;; not allowed
`(a b c . ,foo) ;; OK: equivalent to `(a b c ,#foo)
Not sure how various implementations deal with a backquote in a dot position:
`(a b c . `(d e f))
It doesn't really make sense, and I suspect that the actual result obtained will depend on the backquote implementation internals.
Not all objects are traversed for unquoting:
`#c(,(sin theta) ,(cos theta)) ;; Not required by ANSI CL, oops!
This could work via an implementation's extension.
I'm recently implementing a scheme interpreter using scheme itself. I know that single dot notation means constructing a pair or defining a lambda with multiple parameters. But then I discover that
'(3 . 4 . 5)
evaluates to
'(4 3 5)
and
(define (a . b . c) (displayln b) (displayln c))
(a 4 3)
it will print (weird that #\newline is not printed)
(4 3)>
Can somebody explain the meaning of double dot notation?
From http://docs.racket-lang.org/reference/reader.html
If the reader finds three or more data between the
matching parentheses, and if a pair of delimited .s
surrounds any other than the first and last elements,
the result is a list containing the element surrounded
by .s as the first element, followed by the others in
the read order. This convention supports a kind of
infix notation at the reader level.
Racket provides the double dot syntax for the purpose of infix function calls:
(2 . + . 3) => 5
Considered that I have a procedure (plus x y) witch takes exactly two args. And now I also have a list which contains two objects like (list 1 2). So, if there's any magic way to expand the list as two arguments. We have a dot notion version, but that isn't what i want. I just want to expand the list to make Scheme believe I passed two arguments instead of a list.
Hope those Ruby codes help:
a = [1, 2]
def plus(x,y); x+y; end
plus(*a)
# See that a is an array and the plus method requires
# exactly two arguments, so we use a star operator to
# expand the a as arguments
(apply your-procedure your-list)
This is Scheme's equivalent code:
(define (plus x y)
(+ x y))
(plus 1 2)
=> 3
(define a (list 1 2))
(apply plus a)
=> 3
The "magic" way to expand the list and pass it as arguments to the procedure, is using apply. Read more about it your interpreter's documentation.
I discovered that special forms can not be passed as arguments or saved in variables, both in Clojure:
user=> (defn my-func
[op]
(op 1 2 3))
#'user/my-func
user=> (my-func +)
6
user=> (my-func if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:5)
user=> (def my-if if)
java.lang.Exception: Unable to resolve symbol: if in this context (NO_SOURCE_FILE:9)
and in Racket/Scheme:
> (define (my-func op)
(op 1 2 3))
> (my-func +)
6
> (my-func if)
if: bad syntax in: if
> (define my-if if)
*if: bad syntax in: if
That's cool, I'm fine with that, I know that I can just write a function to wrap a special form and then pass that function.
But I'd like to know why Lisps have this restriction, and what negative consequences allowing this would have. Are they any major dialects that do allow that?
It makes evaluation more complicated and compilation hard.
If you have a form (a b c), then you need to resolve at runtime the value of a and then apply it somehow to the forms b and c.
The simpler model of a few limited number of special forms and otherwise strict evaluation is then gone.
See also: FEXPR
Special forms are not functions: functions take values as arguments, whereas special forms take forms. For example, look at your example of if:
(if 1 2 3)
Okay, that's easy, since 2 and 3 are already values. But what about this?
(define (modadd a b n)
(if (zero? n) #f (modulo (+ a b) n)))
In this case, the if is actually receiving the #f and (modulo (+ a b) n) as forms, not as values. And this is important! (modulo x n) will fail if n is 0: that is why it's left unevaluated until we know that n is not 0.
The trouble with being able to pass special forms as first-class objects is that higher-order functions cannot call those objects using predictable semantics: is it a function object, so that you're passing in values, or is it a special form, so that you're passing in forms? This gets to be a huge mess.
Yes, you can write a wrapper function, like my modadd, that encapsulates if. However, there is no way you can just reimplement if as a function, while still preserving the only-evaluate-one-of-the-branches behaviour.