I am still in the process of understanding macros and though I think I understand the basics of "backquote" "unquote" and "unquote splicing", I had thought they were only used/useful in macros.
however I came across this Common Lisp code from Rosetta code (the calender task),
(defun month-strings (year month)
"Collect all of the strings that make up a calendar for a given
MONTH and YEAR."
`(,(date-calc:center (month-to-word month) (length *day-row*))
,*day-row*
;; We can assume that a month calendar will always fit into a 7 by 6 block
;; of values. This makes it easy to format the resulting strings.
,# (let ((days (make-array (* 7 6) :initial-element nil)))
(loop :for i :from (date-calc:day-of-week year month 1)
:for day :from 1 :to (date-calc:days-in-month year month)
:do (setf (aref days i) day))
(loop :for i :from 0 :to 5
:collect
(format nil "~{~:[ ~;~2,d~]~^ ~}"
(loop :for day :across (subseq days (* i 7) (+ 7 (* i 7)))
:append (if day (list day day) (list day))))))))
here back-quote, unquote, and unquote splicing are used in a normal function, and it works to create a list of strings.
and while I do not use Scheme, the Racket solution had something similar,
(define days
(let ([? (if (= mn 12) (λ(x y) y) (λ(x y) x))])
(round (/ (- (find-seconds 0 0 12 1 (? (+ 1 mn) 1) (? yr (+ 1 yr))) s)
60 60 24))))
(list* (~a mname #:width 20 #:align 'center) "Su Mo Tu We Th Fr Sa"
(map string-join
(nsplit 7 `(,#(make-list pfx " ")
,#(for/list ([d days])
(~a (+ d 1) #:width 2 #:align 'right))
,#(make-list (- 42 pfx days) " ")))))))
which I did not test.
my questions are,
Why would this be necessary in a function, what is the use case?
and how is it different from a macro ?
quasiquote, unquote and unquote-splicing are just syntax sugar for a combination of quoted datum, list, and cons. Imagine this:
`(,a b c) ; == (cons a '(b c))
`(a b ,c) ; == (list 'a 'b c)
`(a b ,#c d) ; == (cons 'a (cons 'b (append c '(d))))
These are small trivial examples, so you can imagine the right hand side might become crazy complex, but it is nice to know that the quasiquote magic makes new cons when needed and keep literals as is in the tails. Thus using nconc of quasiquoted expression would not work in the first case, but in the second and third because the last cons is needed to be fresh in those cases.
If you have a function that creates a list structure, quasiquote will make the code more clear and consice since the form will look more like the result. It is no different than a macro since both create list structure. A macro differs in what happens with the result. In a function the value is returned and in a macro code gets replaced.
You can check what happens after using the macro with macroexpand:
(macroexpand '`(,a ,b ,#c))
; ==> (cons a (cons b c))
; ==> t
Backquote
See the CLHS on Backquote.
The example
The example is similar to this code:
CL-USER 14 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`(,a ; a gets evaluated and put in
,b ; b gets evaluated and put in
,#c)) ; c gets evaluated and spliced in
(1 2 3 4 5)
The effect of above code is similar to using the function list*.
CL-USER 15 > (let ((a 1)
(b 2)
(c '(3 4 5)))
(list* a b c))
(1 2 3 4 5)
Which version you use is mostly a matter of taste.
list* creates a list of the first values and puts them in front of the last value, which usefully should be a list.
List creation
There are many ways and styles to create a list. The two here:
use nested functions like cons, list, list*, append, ... This is especially useful when there are many elements to be computed.
use templates of lists with the backquote operator and ,, ,#, ,. for evaluating. This is especially useful when there are nested lists with fixed objects and a few objects to compute.
Thus the backquoted way is useful when you think of list templates to fill out. Whenever you want to create (nested) lists, which are based on templates with a lost of constant structure (meaning objects and nesting), then this is a way to do it. This is not limited to macros - it is a general mechanism to build lists.
You can also think of templates being an inversion:
functions evaluate by default and constant elements need to be quoted
backquote templates don't evaluate by default and variable elements need to be unquoted.
Warning
Backquoted expressions themselves don't need to be pure lists. The internal representation of backquoted expressions is undefined and implementations actually differ.
Vectors, too
Note that this works for vectors, too:
CL-USER 20 > (let ((a 1)
(b 2)
(c '(3 4 5)))
`#(,a
,b
,#c))
#(1 2 3 4 5)
Quasi-Quote (QQ) is a list constructor in Scheme.
It’s more flexible than quote ('), list or cons because it allows for mixing symbols with expression evaluations.
The QQ has two helper mechanisms:
unquote - denoted (,)
unquote-splicing - denoted (,#)
When QQ is used, a quote context is initiated. Unquote allows us to momentarily escape the quote context and evaluate the expression right after the unquote. Unquote-splicing both escapes an entire list from the quote context as well as “unwraps” the list.
Consider:
(define b 5)
(define s (list 1 2))
Note the differences in the values of the following expressions: Quote, Quasi-Quote.
Input:
'(a b c)
`(a b c)
Output
> (a b c)
> (a b c)
Input
'(a ,b c)
`(a ,b c)
Output
> (a ,b c)
> (a 5 c)
Input
'(a ,s c)
`(a ,s c)
Output
> (a ,s c)
> (a (1 2) c)
Input
'(a ,#s c)
`(a ,#s c)
Output
> (a ,#s c)
> (a 1 2 c)
Source: Compilation course I took , The Common Lisp Cookbook - Macros and Backquote
Related
I am learning how to use higher-order functions in scheme. I get the idea of using higher-order functions, however I am having trouble using them. For this learning exercise, I would prefer to only use some combination of filter, fold, and/or map.
For example, I want to construct the set difference between two lists call them A and B. I am defining set difference as x such that x is an element of A but x is not an element of B. I only want to use the functions map, filter and fold. For example:
Let A = (1 8 6 2)
Let B = (5 7 9 1 6)
The set difference of A and B would be (8 2)
The idea is to construct a new list by iterating over the elements of A and seeing if an element of A equals an element of B, if so don't add a to the new list; otherwise add a to the new list.
My algorithm idea goes something like this:
Let neq be "not equal to"
For each a in A and b in B evaluate the expression: (neq? a b)
For a = 1 we have:
(and (neq? 1 5) (neq? 1 7) (neq? 1 9) (neq? 1 1) (neq ? 1 6))
If this expression is true then a goes in the new list; otherwise don't add a to the new list. In our example (neq? 1 1) evaluates to false and so we do not add 1 to the new list.
Pretty much my entire procedure relies on 1, and this is where I have a trouble.
How do I do step 1?
I see that in step 1 I need some combination of the map and fold functions, but how do I get the and a neq b distributed?
EDIT This is the closest sample I have:
(fold-right (trace-lambda buggy (a b c) (and (neq? a b))) #t A B)
|(buggy 3 5 #t)
|#t
|(buggy 2 4 #t)
|#t
|(buggy 1 1 #t)
|#f
#f
The above shows a trace of my anonymous function attempting to perform the (and (neq? a b)) chain. However, it only performs this on elements in A and B at the same position/index.
All help is greatly appreciated!
A simplified version of member is easy to implement using fold, of course:
(define (member x lst)
(fold (lambda (e r)
(or r (equal? e x)))
#f lst))
Now, with that, the rest is trivial:
(define (difference a b)
(filter (lambda (x)
(not (member x b)))
a))
If you want to amalgamate all that into one function (using your neq?), you can do:
(define (difference a b)
(filter (lambda (x)
(fold (lambda (e r)
(and r (neq? e x)))
#t b))
a))
In Haskell, fold is capable of short-circuiting evaluation because of lazy evaluation.
But in Scheme it is impossible. That's why in Racket e.g., there's a special function supplied for that, ormap, which is capable of short-circuiting evaluation. IOW it is a special kind of fold which must be defined explicitly and separately in Scheme, because Scheme is not lazy. So according to your conditions I contend it is OK to use it as a special kind of fold.
Using it, we get
(define (diff xs ys)
(filter
(lambda (y)
(not (ormap (lambda (x) (equal? x y)) ; Racket's "ormap"
xs)))
ys))
If your elements can be ordered, it is better to maintain the sets as ordered (ascending) lists; then diff can be implemented more efficiently, comparing head elements from both lists and advancing accordingly, working in linear time.
Using Racket:
(define A '(1 8 6 2))
(define B '(5 7 9 1 6))
(filter-not (lambda (x) (member x B)) A)
==> '(8 2)
Of course, it is possible in Scheme to implement member on top of fold that short-circuits on the first match:
(define (member x lst)
(call-with-current-continuation
(lambda (return)
(fold (lambda (e r)
(if (equal? e x)
(return #t)
r))
#f lst))))
I'm no Scheme expert so not sure if I'm using the correct terminology here. Let the code speak for itself:
CSI> (define tree '(1 2 3 'Symb 4 5 6))
#<unspecified>
CSI> tree
(1 2 3 (quote Symb) 4 5 6)
CSI> (symbol? 'Symb)
#t
CSI> (map symbol? tree)
(#f #f #f #f #f #f #f)
Coming from Clojure background, I thought symbols were used like this in Scheme, like keywords in Clojure. I'm supposed to go through a nested list structure and replace symbols with a function call. This is my onedimensional solution and it does work:
(define (print-track track attrs)
(apply fmt #t
(map (lambda (attr)
(cond
((symbol? attr) (get-attr attr track))
(else attr)))
attrs)))
The empty space above the (symbol?) line was for a (list?) conditional, but it's likely the wrong aproach.
I'm using Chicken Scheme.
You've run into the Lisp quote "gotcha". In Scheme, symbols are used for variable reference, which you obviously understand. This evaluates to true:
> (symbol? 'Symb)
because you quoted the symbol, and prevented it from being used as a variable reference.
> (symbol? Symb)
Would first look up the value of the Symb variable, and then check if that value was a symbol.
> (let ((Symb 'foo)) (symbol? Symb))
Would evaluate to #t, since the value of Symb is a symbol: foo.
> (let ((Symb 7)) (symbol? Symb))
Would, of course, evaluate to #f.
You seem to have tripped on a nuance of quote.
'Symb
is actually shorthand; it's equivalent to
(quote Symbol)
which, again, returns its unevaluated argument.
But your code doesn't need the inner quote. When you
> (define tree '(1 2 3 'Symb 4 5 6))
the entire list is quoted; nothing inside of the list is going to be evaluated. That's why
> tree ; => (1 2 3 (quote Symb) 4 5 6)
Inside of the quoted list, 'Symb is equivalent to (quote Symb), which is actually a list. Since the whole list is quoted, using Symb unquoted would not be treated as a variable reference. It would just be the symbol.
> (define tree '(1 2 3 Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)
Now, if you were passing all those arguments to the list function, what you originally did would be correct:
> (define tree (list 1 2 3 'Symb 4 5 6))
> tree ; => (1 2 3 Symb 4 5 6)
In that case, you're passing those arguments to a function; arguments to a function are evaluated, so you need quote to prevent symbols from being treated as variable references.
> (define tree (list 1 2 3 (quote Symb) 4 5 6))
Would do the same thing.
In Python, I can do something like this:
t = (1, 2)
a, b = t
...and a will be 1 and b will be 2. Suppose I have a list '(1 2) in Scheme. Is there any way to do something similar with let? If it makes a difference, I'm using Racket.
In racket you can use match,
(define t (list 1 2))
(match [(list a b) (+ a b)])
and related things like match-define:
(match-define (list a b) (list 1 2))
and match-let
(match-let ([(list a b) t]) (+ a b))
That works for lists, vectors, structs, etc etc. For multiple values, you'd use define-values:
(define (t) (values 1 2))
(define-values (a b) (t))
or let-values. But note that I can't define t as a "tuple" since multiple values are not first class values in (most) scheme implementations.
A bare-bones idiom is to use apply with lambda where you'd use let, like:
(define t '(1 2))
(apply (lambda (a b)
;; code that would go inside let
)
t)
The advantage is that it works on any implementation. Of course this can only be used on simple cases, but sometimes that's all you need.
The general term for what you're looking for (at least in Lisp-world) is destructuring and a macro that implements it is known as destructuring-bind. In Common Lisp, it works like this:
(destructuring-bind (a b c) '(1 2 3)
(list a b c)) ;; (1 2 3)
it also works for multiple "levels" of nesting:
(destructuring-bind (a (b c) d) '(1 (2 3) 4)
(list a b c d)) ;; (1 2 3 4)
It looks like there's a nice implementation of destructuring-bind as a scheme macro.
I think this is what you are looking for:
http://www.phyast.pitt.edu/~micheles/scheme/scheme16.html
Look at let-values or let+.
This works in Racket if you don't want to bring in the match dependency:
From a list:
(let-values ([(a b c) (apply values '(1 2 3))])
(+ a b c))
Or directly from a values expression:
(let-values ([(a b c) (values 1 2 3)])
(+ a b c))
Here is a simple destructuring-bind macro for schemes with case-lambda (such as Racket or Chez Scheme):
(define-syntax bind
(syntax-rules ()
((_ arg pat def body)
(apply
(case-lambda
[pat body]
[x def] )
arg ))))
Here is the example that motivated me to write this macro. Putting the default before the body makes for readable code:
(define (permutations l)
;
(define (psub j k y)
;
(define (join a b)
(bind a (ah . at) b
(join at (cons ah b)) ))
;
(define (prec a b z)
(bind b (bh . bt) z
(prec (cons bh a) bt
(psub (cons bh j) (join a bt) z) )))
;
(if (null? k)
(cons (reverse j) y)
(prec (list) k y) ))
;
(psub (list) (reverse l) (list)) )
Here are benchmarks for computing permutations of length 9, on various schemes:
0m0.211s Chez Scheme
0m0.273s Bigloo
0m0.403s Chicken
0m0.598s Racket
The translation to GHC Haskell is 5x faster than Chez Scheme. Guile is much slower than any of these schemes.
Aside from the ease of leveraging the existing case-lambda code, I like how this macro accepts exactly the same syntax as function definition argument lists. I love the simplicity of scheme. I'm old enough to remember programming Fortran on punched cards, where the allowed syntax varied wildly with context. Scheme is supposed to be better than that. The impulse is overwhelming to guild the lily on macros like this. If you can't justify changing the syntax for function definitions too, then don't change that syntax here either. Having an orthogonal grammar is important.
I'm looking for a function in Scheme to replace a element in an equation by a value.
Exemple : '(+ a b c a) with (1 2 3) should give me '(+ 1 2 3 1). (I don't want to resolve the equation, it was just an exemple)
Basically, I want to say that a=1, b=2, c=3
To proceed, I extract the variables of my first list in another list.
Then, I received the expected values in another list.
Now, I want to assign values to variables.
Any hints on how I proceed?
Thanks a lot.
You can use an "association list" of mappings that looks like ((a 1) (b 2) (c 3)).
assq can retrieve the matching pair. So, for everything in your original list, you can look it up using assq and then replace it.
So:
(lambda (ls a-list)
(map (lambda (x)
(let ((lookup (assq x a-list)))
(if lookup
(cadr lookup)
x)))
ls)))
Would take a list and an association list and replace everything in the original list with its replacement (if there is one).
Ain't this what let do?
> (let ((a 1) (b 2) (c 3))
(+ a b c b))
=> 8
If you don't want to evaluate the expression:
> (let ((a 1) (b 2) (c 3))
`(+ ,a ,b ,c ,a))
=> (+ 1 2 3 1)
I'm trying to write a function in scheme that takes a list and squares every item on the list, then returns the list in the form (list x y z). However, I'm not sure how to write a code that will do that. So far, I have
(define (square=list list)
(cond
[(empty? list) false]
[else (list (sqr (first a-list))(square-list (rest a-list)))]))
but it returns the list in the form
(cons x (cons y (cons z empty)))
What can I do to make it return the list just in the form (list x y z)? Thanks!
You're almost there -- make sure you understand the difference between cons and list (the textbook How to Design Programs explains this in Section 13. You can find the online copy here).
cons will take an item as its first element and (usually) a (possibly empty) list for the 'rest' part. As an example, (cons 1 empty) has the number 1 as its first element and the empty list as the 'rest'. (cons 1 (cons 2 empty)) has the number 1 as the first element, and (cons 2 empty) as the 'rest'.
list is just an easy shorthand for making lists, taking an arbitrary number of items. Thus:
(list 1 2 3 4 5)
is the same as...
'(1 2 3 4 5)
which is the same as
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty))))).
But be careful. (list 1 (list 2 (list 3))) is not the same as (cons 1 (cons 2 (cons 3 empty))). In fact, it is (cons 1 (cons 2 (cons 3 empty) empty) empty).
If you're still confused, feel free to post a comment.
The problem is that you're using list in the else statement. You are saying build me a list with this value as the first entry, and a list as the second entry.
You want to cons the first entry onto the list created by recursive call.
(list 'a '(b c d))
; gives you
'(a (b c d))
(cons 'a '(b c d))
; gives you
'(a b c d)
This is probably not what your TA is looking for, but I'll throw it in anyway because it may help you grok a tiny bit more of Scheme. The idiomatic (in Scheme) way to write what you are trying to do is to use map:
> (map (lambda (x) (* x x)) '(1 2 3 66 102 10403))
(1 4 9 4356 10404 108222409)
map applies a function (here, (lambda (x) (* x x)) - a nameless function that returns the square of its input) to each element of a list and returns a new list containing all of the results. Scheme's map basically does the same iteration you are doing in your code, the advantage being that by using map you never have to explicitly write such iterations (and, nominally at least, a Scheme implementation might optimize map in some special way, though that's not really that important in most cases). The important thing about map is that it reduces your code to the important parts - this code squares each element of the list, this other code takes the square root of each element, this code adds one to it, etc, without having to repeat the same basic loop iteration code again and again.