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
I am trying to write a function that returns the cartesian product of 2 sets (lists) with the help of the 'map' function and I want each pair of elements in the returned list to be a vector.
(cartesian-product '(1 2 3) '(a b))
'(#(3 a) #(3 b) #(2 a) #(2 b) #(1 a) #(1 b))
My initial idea was to make a separate procedure that makes a vector out element c (constant) in set 2 and element n in set 1 where element n changes for each iteration and then proceed to map this separate function with set 2. So for example, if I use the above lists (in the code sample) I would get 3 different vectors from this separate function:
#'(a 1) #'(a 2) #'(a 3)
And when using map on this I would get the result:
'(#'(a 1) #'(a 2) #'(a 3) #'(b 1) #'(b 2) #'(b 3))
But I realized that I would instead get a result that looks something like this:
'((#'(a 1) #'(a 2) #'(a 3)) (#'(b 1) #'(b 2) #'(b 3)))
because the separate function has to be recursive and it would have to return a list when finished.
Now I am back to square one and I am out of ideas. Help please...
Should mention that this is a school assignment and I am not allowed to use any predefined functions except for simple ones like:
cdr,car,cons,map etc
Try to keep it as basic as possible. I have only been using Scheme for like a month so go easy on me :)
We can nest two maps and flatten the result at the end, making sure to create a vector in the right place:
(define (cartesian-product lst1 lst2)
(apply append
(map (lambda (x)
(map (lambda (y)
(vector x y))
lst2))
lst1)))
It works as expected:
(cartesian-product '(1 2 3) '(a b))
=> '(#(1 a) #(1 b) #(2 a) #(2 b) #(3 a) #(3 b))
I need to write a function in Scheme that acts as a zipper - meaning it takes two lists and creates a 'zipper' out of the two lists such that
(zip '(a b c) '(1 2 3)) => ((a 1) (b 2) (c 3))
Furthermore it takes each element in the nth position and pairs them together.
I'm fairly new to Scheme, so any help would be much appreciated!
Thanks!
From my Standard Prelude: (define (zip . xss) (apply map list xss))
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))))
So I have an error:
EVAL: undefined function P1
Below is my code so far.
(defun andexp (a b) (list 'and a b))
(defun orexp (a b) (list 'or a b))
(defun notexp (a) (list 'not a))
(defun evalexp (main-list bind-list)
;first change the bind-list to work with sublis
(setq new-bind-list (list (car bind-list).(cdr bind-list)))
;here will go the looping to check matching variable names
(sublis main-list new-bind-list)
);end of evalexp function
Here I am creating an expression:
(setq p1 (andexp 1 (orexp 'a 'b)))
Which evaluates to this:
(and 1 (or a b))
when I run the code below, I get the error I mentioned above.
(evalexp ( p1 '( (a 0) (b 1))))
p1 should contain a list, so I assumed it would work. This leads to my question of, how am I suppose to send lists as parameters into a function? Am I doing it wrong, or is it something else?
note the erroneous extra parens:
(evalexp ( p1 '( (a 0) (b 1))))
should be
(evalexp p1 '((a 0) (b 1)))