racket match syntax quasiquote and question mark - lisp

I am trying to understand pattern match document of racket and have some questions like the following, I can't parse it.
(quasiquote qp) — introduces a quasipattern, in which identifiers match symbols. Like the quasiquote expression form, unquote and unquote-splicing escape back to normal patterns.
http://docs.racket-lang.org/reference/match.html
Example:
> (match '(1 2 3)
[`(,1 ,a ,(? odd? b)) (list a b)])
'(2 3)
It doesn't explain this example, and how "identifiers match symbols"? I guess it is match '(1 2 3) to pattern '(1, a, b) and b is odd, but why `(,1 ,a ,(? odd? b)) not `(1 a (? odd? b)), whey it needs commas in between list members? Especially `(,? Why that way? So string!
Thanks!

If you're not familiar with quasiquoting, then you might to get comfortable with list patterns in match, then learn about quasiquoting in general. Then putting the two together will be easier to understand.
Why? Because quasiquote is "only" a shorthand or alternative for what you can write with list. Although I don't know the actual development history, I imagine that the author(s) of match started off with patterns like list, cons, struct and so on. Then someone pointed out, "hey, sometimes I prefer to describe a list using quasiquoting" and they added quasiquoting, too.
#lang racket
(list 1 2 3)
; '(1 2 3)
'(1 2 3)
; '(1 2 3)
(define a 100)
;; With `list`, the value of `a` will be used:
(list 1 2 a)
; '(1 2 100)
;; With quasiquote, the value of `a` will be used:
`(1 2 ,a)
; '(1 2 100)
;; With plain quote, `a` will be treated as the symbol 'a:
'(1 2 a)
; '(1 2 a)
;; Using `list` pattern
(match '(1 2 3)
[(list a b c) (values a b c)])
; 1 2 3
;; Using a quasiquote pattern that's equivalent:
(match '(1 2 3)
[`(,a ,b ,c) (values a b c)])
; 1 2 3
;; Using a quote pattern doesn't work:
(match '(1 2 3)
['(a b c) (values a b c)])
; error: a b c are unbound identifiers
;; ...becuase that pattern matches a list of the symbols 'a 'b 'c
(match '(a b c)
['(a b c) #t])
; #t

Related

What's difference between case and match?

I was confusing about the difference between match and case. In the document, it mentions that match supports general pattern matching.
> (define (m x)
(match x
[(list a b c)
#:when (= 6 (+ a b c))
'sum-is-six]
[(list a b c) 'sum-is-not-six]))
> (m '(1 2 3))
'sum-is-six
> (m '(2 3 4))
'sum-is-not-six
For this example, I thought I could rewrite it using case expression. But seems it's quite complicated. I have to get the length of the input x, and maybe a lambda function to get the sum of the elements of x and compare it with 6.
So I guess we prefer match when doing pattern matching. Is it true? Any difference other than that?
You said it yourself, match does general pattern matching (a very powerful concept!) whereas case only checks if a value belongs in one of several lists of possible (implicitly quoted) values. All that case does is syntactic sugar for a cond with multiple conditions, for example:
(case (+ 7 5)
[(1 2 3) 'small]
[(10 11 12) 'big]
[else 'other])
... is roughly equivalent to:
(let ((val (+ 7 5)))
(cond ((or (equal? val 1) (equal? val 2) (equal? val 3))
'small)
((or (equal? val 10) (equal? val 11) (equal? val 12))
'big)
(else 'other)))
Whereas match does some complex matching; it checks if a value is one of several possible patterns, it's not only about comparing values for equality, it also checks the type and "shape" of the value against the pattern, and we can even add additional constraints using #:when. To see how complex this can be check under the grammar part of match's documentation.
There are two differences:
match is a lot more powerful than case. case doesn't have "patterns" in the way match does, and it implicitly quotes the datums in each "branch question". It only compares the quoted form of the datum against the value, like a switch statement. match has a different and much richer pattern language.
The x in each branch-question of these two examples
(case 5
[(x) 10]
[else 'fail])
;=> 'fail
(case 'x
[(x) 10]
[else 'fail])
;=> 10
Is implicitly quoted, as the symbol 'x. In match terms, this is equivalent to
(match 5
['x 10]
[_ 'fail])
;=> 'fail
(match 'x
['x 10]
[_ 'fail])
;=> 10
Where quoting is one of many options for creating patterns, not the default. If you leave out the quote in a match, x is no longer a symbol; it is a wildcard that matches anything and defines x as the result.
(match 5
[x (+ x 1)])
;=> 6
This could never happen with case because of case's implicit quoting.
case branch-questions have multiple datums per branch.
These datums must be wrapped in parentheses.
(case expr
[(datum ...) answer]
...)
Where match has only one pattern per branch (no parentheses)
(match expr
[pattern answer]
...)

Apparent 'eval' of quote symbol in CLISP

Some output from the CLISP REPL:
[1]> (list 'list 1 2 3)
(LIST 1 2 3)
[2]> (list 'list '(1 2 3))
(LIST (1 2 3))
[3]> (list 'quote 1 2 3)
(QUOTE 1 2 3)
[4]> (list 'quote '(1 2 3))
'(1 2 3)
The first three, I understand exactly what's going on: The list function is passed a symbol ('list or 'quote) and so the result is a list that begins with the list or quote symbol. It's the fourth that confuses me. Why doesn't it return (QUOTE (1 2 3))?
I realise that if you enter (QUOTE '(1 2 3)) into the REPL, you get '(1 2 3) back, so the expression are equivalent in that sense. But (LIST 1 2 3) is equivalent to (1 2 3), and yet the first expression doesn't return that.
It seems inconsitent that (list 'quote 1 2 3) returns a list with the first item being a quote symbol, but (list 'quote (1 2 3)) returns a quoted list. Especially since expressions like (list 'list ...) seem to always return a list beginning with the symbol - so far, at least, quote is the only 'special case' like this.
It's not the easiest question to articulate, so I'm hoping I've managed to get my confusion across. Can anyone explain why quote gets treated in this seemingly-unique way?
'something is the same as (quote something) for the lisp reader. Even when nested it will be the case. The next expressions I will double quote so that after evaluation one of the quotes are still in there.
When printing the implementations can choose what to output where there are several possible representations, so some implementations would print the evaluation of ''something as
(quote something) while others may use the abbreviation 'something.
'(quote 1 2 3) cannot be abbreviated since a quoted form only has one argument. Thus here both lisp systems would print (quote 1 2 3).
Here is a way to look at your last expression:
(let ((data (list 'quote '(1 2 3))))
(format nil
"whole thing: ~a first element: ~a second-element: ~a"
data
(car data)
(cadr data)))
This will either evaluate to "whole thing: '(1 2 3) first element: QUOTE second-element: (1 2 3)" or "whole thing: (QUOTE (1 2 3)) first element: QUOTE second-element: (1 2 3)".
Since the printer never sees if the input is abbreviated and the data has the same structure in memory the output is never affected by how you input the data. Thus (quote (quote (1 2 3))) will print the same as ''(1 2 3).
You have the same behaviour with cons cells but the standard dictates how the rules are. (cons 1 (cons 2 (cons 3 '()))) would be (1 . (2 . (3 . ()))) but is actually just printed (1 2 3) However if you (cons 1 2) you get (1 . 2) showing that print treats the output differently based on the cdr. However the reader can read any of these and they will all print the same eg. '(1 . (2 . (3 . ()))) ==> (1 2 3) and (+ . (2 . ( 3 . ()))) ; ==> 5
Numbers can have as many visual forms as there are bases below the number in question.
(let ((*print-base* 16))
(print 255)) ; prints FF (255 in hexadecimal)
list does not have any abbreviation or specialness in Lisp. It's not even a primitive function but it's very helpful as it removes the inconvenience of having to cons by hand everytime. It can be defined like this:
(defun my-list (&rest lst)
lst)
(my-list 1 2 3 4) ; ==> (1 2 3 4)
Note that a REPL (the READ-EVAL-PRINT-LOOP) does three things:
reading using the function READ
evaluating using the function EVAL
and printing the result using something like the function PRINT
To understand what is going on you have to look at all three functions.
Let's look at the third form:
(list 'quote 1 2 3)
This is read as a list of five elements:
LIST
(QUOTE QUOTE)
1
2
3
EVAL then evaluates the arguments, and calls the function list with the four results and returns a new result, a list of four elements:
QUOTE
1
2
3
PRINT then takes this list and writes it as: (QUOTE 1 2 3). There is no abbreviated way to print it.
Let's look at the fourth form:
(list 'quote '(1 2 3))
This is read as a list of three elements:
LIST
(QUOTE QUOTE)
(QUOTE (1 2 3))
eval calls list with two arguments:
QUOTE
(1 2 3)
eval then returns a list of length two:
QUOTE
(1 2 3)
print now can print this list in two different ways:
(QUOTE (1 2 3)) or the abbreviated form '(1 2 3). Here a quote character is in front of a single expression.
Your implementation used the first version.

Creating repetitions of list with mapcan freezes?

I have two lists: (1 2 3) and (a b) and I need to create something like this (1 2 3 1 2 3). The result is a concatenation of the first list as many times as there are elements in the second. I should use some of the functions (maplist/mapcar/mapcon, etc.). This is exactly what I need, although I need to pass first list as argument:
(mapcan #'(lambda (x) (list 1 2 3)) (list 'a 'b))
;=> (1 2 3 1 2 3)
When I try to abstract it into a function, though, Allegro freezes:
(defun foo (a b)
(mapcan #'(lambda (x) a) b))
(foo (list 1 2 3) (list 'a 'b))
; <freeze>
Why doesn't this definition work?
There's already an accepted answer, but I think some more explanation about what's going wrong in the original code is in order. mapcan applies a function to each element of a list to generate a bunch of lists which are destructively concatenated together. If you destructively concatenate a list with itself, you get a circular list. E.g.,
(let ((x (list 1 2 3)))
(nconc x x))
;=> (1 2 3 1 2 3 1 2 3 ...)
Now, if you have more concatenations than one, you can't finish, because to concatenate something to the end of a list requires walking to the end of the list. So
(let ((x (list 1 2 3)))
(nconc (nconc x x) x))
; ----------- (a)
; --------------------- (b)
(a) terminates, and returns the list (1 2 3 1 2 3 1 2 3 ...), but (b) can't terminate since we can't get to the end of (1 2 3 1 2 3 ...) in order to add things to the end.
Now that leaves the question of why
(defun foo (a b)
(mapcan #'(lambda (x) a) b))
(foo (list 1 2 3) '(a b))
leads to a freeze. Since there are only two elements in (a b), this amounts to:
(let ((x (list 1 2 3)))
(nconc x x))
That should terminate and return an infinite list (1 2 3 1 2 3 1 2 3 ...). In fact, it does. The problem is that printing that list in the REPL will hang. For instance, in SBCL:
CL-USER> (let ((x (list 1 2 3)))
(nconc x x))
; <I manually stopped this, because it hung.
CL-USER> (let ((x (list 1 2 3)))
(nconc x x) ; terminates
nil) ; return nil, which is easy to print
NIL
If you set *print-circle* to true, you can see the result from the first form, though:
CL-USER> (setf *print-circle* t)
T
CL-USER> (let ((x (list 1 2 3)))
(nconc x x))
#1=(1 2 3 . #1#) ; special notation for reading and
; writing circular structures
The simplest way (i.e., fewest number of changes) to adjust your code to remove the problematic behavior is to use copy-list in the lambda function:
(defun foo (a b)
(mapcan #'(lambda (x)
(copy-list a))
b))
This also has an advantage over a (reduce 'append (mapcar ...) :from-end t) solution in that it doesn't necessarily allocate an intermediate list of results.
You could
(defun f (lst1 lst2)
(reduce #'append (mapcar (lambda (e) lst1) lst2)))
then
? (f '(1 2 3) '(a b))
(1 2 3 1 2 3)
Rule of thumb is to make sure the function supplied to mapcan (and destructive friends) creates the list or else you'll make a loop. The same applies to arguments supplied to other destructive functions. Usually it's best if the function has made them which makes it only a linear update.
This will work:
(defun foo (a b)
(mapcan #'(lambda (x) (copy-list a)) b))
Here is some alternatives:
(defun foo (a b)
;; NB! apply sets restrictions on the length of b. Stack might blow
(apply #'append (mapcar #'(lambda (x) a) b))
(defun foo (a b)
;; uses loop macro
(loop for i in b
append a))
I really don't understand why b cannot be a number? You're really using it as church numbers so I think I would have done this instead:
(defun x (list multiplier)
;; uses loop
(loop for i from 1 to multiplier
append list))
(x '(a b c) 0) ; ==> nil
(x '(a b c) 1) ; ==> (a b c)
(x '(a b c) 2) ; ==> (a b c a b c)
;; you can still do the same:
(x '(1 2 3) (length '(a b))) ; ==> (1 2 3 1 2 3)

List Item Evaluation

I'm learning lisp and have a question about a simple list:
(setq stuff '(one two three (+ 2 2)))
stuff ; prints "one two three (+ 2 2)"
(setq stuff (list `one `two `three (+ 2 2)))
stuff ; prints "one two three 4"
The first setq creates a list "one two three (+ 2 2)". The second list creates "one two three 4". Why does the first list not evaluate the (+ 2 2), but the second one does? I read in the Emacs Lisp intro documentation that when the list is built that it evaluates from the inside out. Why doesn't the first list evaluate the addition before adding it to the list?
This is elisp in emacs 24.
' is not equivalent to list, it's shorthand for quote. You're really doing this:
(setq stuff (quote (one two three (+ 2 2))))
The argument to quote is the expression (one two three (+ 2 2)).
From http://www.gnu.org/software/emacs/manual/html_node/elisp/Quoting.html: "The special form quote returns its single argument, as written, without evaluating it".
Looks like you're coming to grips with the evaluation semantics of Lisp, so keep playing around!
You can think of quote as suppressing evaluation of its argument. This allows you to write expressions that you can manipulate or pass around. It is also used to write data structures that should not be evaluated as function calls.
Data structures:
'(1 2 3) ; => '(1 2 3)
(1 2 3) ; => Lisp error: (invalid-function 1)
;; The Lisp reader sees the number 1 in the function position and tries to call it, signalling an error.
Syntax transformations:
(setq x '(string-to-int "123"))
(setf (car x) 'string-to-list)
x ; => '(string-to-list "123")
Delayed evaluation:
(setq x '(message "Hello World")) ; => '(message "Hello World")
(eval x) ; => "Hello World"
There is a closely related special operator called syntax quote, written using the backtick. It allows you to evaluate individual forms in a quoted expression using the comma ( , ) operator. It is like quote with an escape hatch.
`(1 2 (+ 3 4)) ; => '(1 2 (+ 3 4))
`(1 2 ,(+ 3 4)) ; => '(1 2 7) ;; Note the comma!
Syntax quote also permits list splicing using the ,# syntax:
`(1 2 ,#(+ 3 4)) ; => '(1 2 + 3 4)
As you can see, it splices the subsequent expression into the containing one. You probably won't see it all that often until you start writing macros.
list on the other hand is a simple function. It evaluates its arguments, then returns a new data structure containing these items.
(list 1 2 (+ 3 4)) ; => '(1 2 7)

What's the equivalent of foldr, foldl in Emacs Lisp?

What's the equivalent of foldr, foldl in Emacs Lisp?
If you
(require 'cl)
then you can use the Common Lisp function reduce. Pass the keyword argument :from-end t for foldr.
ELISP> (reduce #'list '(1 2 3 4))
(((1 2) 3) 4)
ELISP> (reduce #'list '(1 2 3 4) :from-end t)
(1 (2 (3 4)))
Since Emacs-24.3 we recommend the use of cl-lib over cl (which is planned for removal in some distant future), so it would be:
(require 'cl-lib)
(cl-reduce #'+ '(1 2 3 4))
and since Emacs-25, you can also use the seq package for that:
(require 'seq)
(seq-reduce #'+ '(1 2 3 4) 0)
Common Lisp library provides plenty of sequence functions like mapping, filtering, folding, searching and even sorting. CL library is shipped with Emacs by default, so you should stick to it. I however really like dash.el library, because it provides enormous amounts of functions for list and tree manipulations. It also supports anaphoric macros and encourages functional programming, which makes code concise and elegant.
Haskell's folds correspond with dash.el folds:
foldl with -reduce-from
foldr with -reduce-r-from
foldl1 with -reduce
foldr1 with -reduce-r
Sum of a range 1 to 10 using folds might look like in this in Haskell and dash.el:
foldl (+) 0 [1..10] -- Haskell
(-reduce-from '+ 0 (number-sequence 1 10)) ; Elisp
You probably know, that folds are very general, and it is possible to implement maps and filters via folds. For example, to increment every element by 2, Haskell's currying and sections would allow for terse code, but in Elisp you would usually write verbose throwaway lambdas like that:
foldr ((:) . (+2)) [] [1..10] -- Haskell
(-reduce-r-from (lambda (x acc) (cons (+ x 2) acc)) '() (number-sequence 1 10)) ; Elisp
Guess what, it isn't necessary in dash.el with anaphoric macros, which allow special syntax by exposing variables of a lambda as shortcuts, like it and acc in folds. Anaphoric functions start with 2 dashes instead of 1:
(--reduce-r-from (cons (+ it 2) acc) '() (number-sequence 1 10))
There are plenty fold-like functions in dash.el:
;; Count elements matching a predicate
(-count 'evenp '(1 2 3 4 5)) ; 2
;; Add/multiply elements of a list together
(-sum '(1 2 3 4 5)) ; 15
(-product '(1 2 3 4 5)) ; 120
;; Find the smallest and largest element
(-min '(3 1 -1 2 4)) ; -1
(-max '(-10 0 10 5)) ; 10
;; Find smallest/largest with a custom rule (anaphoric versions)
(--min-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (6)
(--max-by (> (length it) (length other)) '((1 2 3) (4 5) (6))) ; (1 2 3)