What does the . in (define-syntax-rule (id . pattern) template) mean? Is it just part of the define-syntax-rule syntax or does it mean something special in racket?
It's standard variable arguments syntax for definitions (it's the same for procedures): all the identifiers after the name and before the dot are treated as required parameters, and after the dot comes a variable length list (with zero or more elements) with the optional parameters. For example:
(define (test x . args)
(displayln x)
(displayln args))
(test)
=> arity mismatch, the expected number of arguments
does not match the given number
(test 1)
=> 1
()
(test 1 2)
=> 1
(2)
(test 1 2 3)
=> 1
(2 3)
It's possible to have zero required parameters, making all of the parameters optional:
(define (test . args)
(displayln args))
(test)
=> ()
(test 1)
=> (1)
(test 1 2)
=> (1 2)
In the case of define-syntax-rule, this means that after the id zero or more patterns are expected:
(define-syntax-rule (id . pattern) template)
Related
trying to do a dr racket problem to tell if a number is apart of list. getting errors
#lang racket
(mymember (x, l))
if l=?null
then "false"
if x==car(l)
then "true"
mymember(x,l)
mymember 2' (1,3,4,5,6)
Racket uses prefix notation. This makes commas unnecessary. First, some syntax:
How to define a function?
( define ( name variable1 variable2 ) body )
Where name is the name of the function, and the variables are the parameters. Which are followed by the body expression.
Example:
; Number -> Number
; converts from fahrenheit to celsius.
(define (f2c f)
(* 5/9 (- f 32)))
How to call a function?
( name expression1 expression2 )
name is the name of the function and expression1 and expression2 are its arguments.
Example:
(sqr 3)
;; == 9
Similarly, to check if two values are equal: (equal? x y)
How to use the if expressions?
( if question-expression then-answer-expression else-answer-expression )
If the value of the question-expression is not false, the if evaluates the then-answer-expression, otherwise it evaluates the else-answer-expression.
Example:
;; Number -> Number
;; reciprocate all non-zero x, otherwise return 0.
(define (inverse-of-x x)
(if (= x 0) 0 (/ 1 x)))
... and so on. Read the Racket Guide for the essentials on syntax, semantics and datatypes in the language.
Fixing all the syntax still leads to one error: an infinite loop. That is because the recursive call doesn't call cdr on the list. So the recursive call is made on the same list (not a shorter list) forever. Wrapping a cdr and fixing the syntax leads to a correct function.
#lang racket
; [X] [List-of X] -> "true" U "false"
; is x an element of l?
(define (mymember x l)
(if (equal? l null)
"false"
(if (equal? x (car l))
"true"
(mymember x (cdr l)))))
(mymember 2 '()) ; = false
(mymember 2 '(1 3 4 5 6)) ; = false
(mymember 2 '(1 3 2 5 6)) ; = true
From https://www.gnu.org/software/guile/manual/html_node/Syntax-Rules.html#Syntax-Rules I got the following macro example:
(define-syntax simple-let
(syntax-rules ()
((_ (head ... ((x . y) val) . tail)
body1 body2 ...)
(syntax-error
"expected an identifier but got"
(x . y)))
((_ ((name val) ...) body1 body2 ...)
((lambda (name ...) body1 body2 ...)
val ...))))
I am trying to understand how this macro works. So I annotated it a little:
;; EXAMPLE 7
;; Reporting errors at macro-expansion time (read time, compile time).
(define-syntax simple-let
(syntax-rules ()
[(simple-let (head ... ((x . y) val) . tail)
; (1) head ... can also be zero times?
; (2) what is `. tail` matching?
; (3) can I not use two ellipsis on the
; same level instead of `. tail`?
body1
body2 ...)
(syntax-error "expected an identifier but got"
(x . y))]
;; if there ((a . b) val) is not matched
[(simple-let ((name val) ...)
body1
body2 ...)
((lambda (name ...)
body1
body2 ...)
val ...)]))
The only part I do not really understand in terms of how it works is the first match expression:
(simple-let (head ... ((x . y) val) . tail)
So I tried a few examples:
;; simply working
(simple-let ([a 3])
(+ a 4))
;; caught
(simple-let ([(a . b) 3]) ; Q: What is `. tail` matching in this one?
(+ a 4))
(simple-let ([a 3] [(b . c) 3]) ; Q: What is `. tail` matching in this one?
(+ a b))
;; not caught
(simple-let ([a 3] [(b . c) 3] [d 4]) ; Q: Why is `. tail` not matching `[d 4]`?
(+ a b))
I have difficulties understanding what part is . tail matching and why. I tried using ... instead of . and put it behind tail, in order to catch the example where the syntax error is not caught, because it does not go into the first match case, but it does not work and tells me that it is a bad usage of ellipsis. My guess is, that one cannot have two ellipsis in the same nesting level, because it would be hard to know which ellipsis matches what. Kind of like regular expressions become computationally expensive in some cases.
So what does . tail match in the examples and why is that one example not caught?
usually tail matches the rest of the list e.g.
for '(1 2 3 4) matching with the pattern (1 . x), x matches '(2 3 4).
The result is confusing so one need to go to the sources to see the implementaion (see ice-9/psyntax.scm)
There one can see that the ellipsis is translated to (each+ x y z) with z in this case is tail and is matching the last cdr which in all your cases is '().
In the example ... is gready and . tail is not. If you are dissatisfied with how this behavior is documented or want to change the implementation you may ask on the guile-devel mailing list: guile-devel#gnu.org
Guile has also syntax-parse as a downloadable lib (search for guile-syntax-parse) which is a port of racket's syntax-parse as of a couple of years ago (see racket's documentation if you are curious) I coded your example with syntax-parse and that seamed to execute as you expected.
I can't figure out on how to write a vector function that returns the first odd number in the list.
Ex: (check-expect (first-oddnumb 2 3 4 5 6) 3)) ;;it returns 3 because 3 is the first odd number in the list.
I can't figure out on how to write a vector function that returns the first odd number in the list.
My confusion is the same as #Sylwester's: "vector function"? The rest of the question seems to make sense tho.
I can help you write a function that returns the first odd number in the list.
We want the function to work like this
(first-odd-number 2 3 4 5 6) ;; => 3
So the first thing we have to do is learn how to write a function that accepts a variable number of arguments
(define (variadic . xs) xs)
(variadic 1 2) ;; => '(1 2)
(variadic 1 2 3) ;; => '(1 2 3)
(variadic 1 2 3 4) ;; => '(1 2 3 4)
(variadic) ;; => '()
Note the . before the xs parameter. This gives us a way to collect all of the passed arguments into the bound identifier, xs. Notice how the arguments are collected into a list. Also pay attention to how xs will still be a list (empty list '()) even if no arguments are given in the function call.
Now we can begin writing your function
(define (first-odd-number . xs)
;; so we know xs will be a list here ...
)
Let's talk about the possible states of xs
xs could be empty, in which case what should we return? maybe a 0 or something? (more on this later)
Otherwise, xs has at least one number ...
is the first number an odd number? if so, return that number
is the first number an even number? if so, return first-odd-number of the remaining numbers in xs
OK, we can pretty much define this in Racket verbatim
(define (first-odd-number . xs)
;; begin case analysis of xs
(cond
;; is the list of numbers empty? return 0
[(empty? xs) 0]
;; the list is not empty, continue ...
;; is the first number odd?
[(odd? (car xs)) (car xs)]
;; otherwise...
;; the number even, check remaining numbers
[else (apply first-odd-number (cdr xs))]))
(first-odd-number 2 3 4 5 6) ;; => 3
(first-odd-number 3 4 5 6) ;; => 3
(first-odd-number 4 5 6) ;; => 5
(first-odd-number) ;; => 0
And that's pretty much it !
Improvements...
If you're like me tho, that 0 is making you feel uneasy. What if you were given a list of only even numbers? What should the return value be?
(first-odd-number 2 4 6) ;; => 0
This is kind of weird. We could use the 0 to mean that no odd number was found, but Maybe there's a better way ...
(struct Just (value) #:transparent)
(struct None () #:transparent)
(define (first-odd-number . xs)
(cond
;; no odd number was found; return None
[(empty? xs) (None)]
;; an odd number was found, return (Just n)
[(odd? (car xs)) (Just (car xs))]
;; otherwise check the remaining numbers
[else (apply first-odd-number (cdr xs))]))
(first-odd-number 2 3 4 5 6) ;; => (Just 3)
(first-odd-number 3 4 5 6) ;; => (Just 3)
(first-odd-number 4 5 6) ;; => (Just 5)
(first-odd-number) ;; => (None)
Now when the caller of our first-odd-number is working with the function, we don't have to don't have to remember that 0 is a special case we need to consider
(define (print-the-first-odd-number . xs)
(match (apply first-odd-number xs)
[(Just x) (printf "the number is ~a\n" x)]
[(None) (printf "no odd number was found\n")]))
(print-the-first-odd-number 2 3 4 5 6) ;; the number is 3
(print-the-first-odd-number 2 4 6) ;; no odd number was found
Another way is to use a comprehension to iterate over the vector (or whatever), specifically, for/first, which returns the value returned by the first body that gets evaluated, combined with a #:when clause to limit said evaluation to the first odd element of a vector:
#lang racket/base
(define (first-odd-number container)
(for/first ([num container]
#:when (odd? num))
num))
(displayln (first-odd-number #(2 3 4 5 6))) ; 3, passing a vector
(displayln (first-odd-number '(2 3 4 5 6))) ; 3, passing a list
If no odd number is present, it returns #f.
While you get better performance by using type specific sequence builders like in-vector with a for loop, using a container directly like this gives more flexibility (It would also work with sets of numbers and a few other standard types)
If instead wanting a function that takes a variable number of arguments, use a hardcoded in-list and the appropriate formals:
(define (first-odd-number . numbers)
(for/first ([num (in-list numbers)]
#:when (odd? num))
num))
#lang racket
(define-syntax for
(syntax-rules ()
((_ list 'as element body ...)
(map (lambda (element)
body ...)
list))))
>
(for '(0 1 2 3 4) 'in i
(print i)
(newline))
=>
0
1
2
3
4
'(# # # # #)
My question is why the symbol 'in can pattern the symbol 'as ?
The symbol 'in isn't a only pattern with 'in?
Macro patterns are not evaluated. In particular, 'as is not a symbol. It is simply the list (quote as). ('as evaluates to a symbol, but it isn't by itself a symbol.) Thus, your macro is really the same as:
(define-syntax for
(syntax-rules ()
((_ list (quote as) element body ...)
(map (lambda (element)
body ...)
list))))
where quote and as are pattern variables that can match anything whatsoever.
As mentioned in uselpa's answer, the correct way to require the use of as exactly as written is to use the literal list:
(define-syntax for
(syntax-rules (as)
((_ list as element body ...)
(map (lambda (element)
body ...)
list))))
Or, if you're really sadistic and want to make the user quote the as, do this:
(define-syntax for
(syntax-rules (quote as)
((_ list 'as element body ...)
(map (lambda (element)
body ...)
list))))
(Yes, you can even change the literal list to be 'as instead of (quote as) as I have it, but that just makes your macro unreadable. Don't do that. :-P)
In the Racket doc, at some point it says
The template is used in place of a form that matches the pattern, except that each instance of a pattern variable in the template is replaced with the part of the macro use the pattern variable matched.
which makes me think that the 'as symbol is simply ignored. And indeed, this
(define-syntax for
(syntax-rules ()
((_ list element body ...)
(map (lambda (element)
body ...)
list))))
(for '(0 1 2 3 4) i (print i) (newline))
works just as well.
To get the behaviour you want, use
(define-syntax for
(syntax-rules (as)
((_ list as element body ...)
(map (lambda (element)
body ...)
list))))
then
> (for '(0 1 2 3 4) as i (print i) (newline))
0
1
2
3
4
'(#<void> #<void> #<void> #<void> #<void>)
but
> (for '(0 1 2 3 4) in i (print i) (newline))
for: bad syntax in: (for (quote (0 1 2 3 4)) in i (print i) (newline))
For example, here is a macro:
(defmacro my-macro (x y)
(if (> x 0)
`(lambda (z) (+ z ,y))
`(lambda (z) (+ ,x z))))
and (my-macro 2 3) returns (lambda (z) (+ z 3))
However, ((my-macro 2 3) 1) returns an error saying,
Debugger entered--Lisp error:
(invalid-function (my-macro 2 3))
((my-macro 2 3) 1)
eval(((my-macro 2 3) 1))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
What am I missing?
Emacs Lisp requires the first element of a list form to be a built-in function (or subr), a lambda-expression (i.e. (lambda LIST . LIST)) or a macro lambda-expression (i.e. (macro lambda LIST . LIST)). The first element can also be a symbol whose function slot contains a valid first element.
(my-macro 2 3) doesn't have the required form, so it's an invalid function.
If you're used to Scheme, where the function part of a function call is evaluated normally, note that this can't work identically in Lisp where functions have a different namespace ((f 3) looks up f's function slot, whereas the value of f is normally its value slot).
If you want to evaluate a function like a normal value, you can use funcall or apply.
(funcall (my-macro 2 3) 1)
As the error message makes clear, in evaluating the form ((my-macro 2 3) 1), Emacs doesn't expand (my-macro 2 3) before evaluating the list it's the first element of. You want to say
(funcall (my-macro 2 3) 1)
or
(eval (list (my-macro 2 3) 1)
or something like that, so that the macro gets evaluated.