I'm a beginner of the Scheme language.
Recently I found that the data type symbol can be displayed using quote, like this:
> 'E
E
> (quote E)
E
However, if the code below executed, every kind of quote may fail:
> (define 'E 123)
> 'E
E: undefined;
cannot reference an identifier before its definition
> 'abc
abc: undefined;
cannot reference an identifier before its definition
So what happend when code (define 'E 123) being executed?
First you asked Scheme to evaluate (define 'E 123). Let's put a quote in front of that, to see what it looks like without the ' shorthand. You can always do this: quote any expression to ask Scheme, "What do you think this value is?"
> '(define 'E 123)
=> (define (quote E) 123)
Well, in Scheme, (define (x ...) ...) is a shorthand for (define x (lambda (...) ...)): it's just a convenient shorthand for defining a function. So in this case (define (quote E) 123) is the same as (define quote (lambda (E) 123)). Thus, the symbol you are redefining is quote, and you define it to be a function of one parameter which always returns 123.
Next you asked to evaluate 'E. Again let's expand that to look through the shorthand:
> ''E
=> (quote E)
You now call the quote function you defined, and pass it the variable E as an argument. But E has not previously been defined, so this fails. If you wanted to, you could first define E to have any value, and then perhaps 'E would return 123. It rather depends on what Scheme evaluator you are using: the one I found does not much appreciate it when you try to redefine quote, but apparently yours does not mind, so I suspect you would get 123, and that you would get the same result if you defined abc and then evaluated 'abc.
in general (define name ...) is converted in (bind name) at the beginning of the scope and in the place where define appears, it is executed (set! name ...). You need to define a symbol, not a (quote name). Because define is a special form, the rules of evaluation are particular, not general application -- define is not a function call.
Related
In miniKanren, succeed can be defined as (define succeed (== #t #t)), and fail can be defined as (define fail (=== #t #f)). But what about #s and #u as short forms of succeed and fail, as they appear in The Reasoned Schemer?
(define #s succeed) produces an error in Racket:
Welcome to Racket v7.2.
> (require Racket-miniKanren/miniKanren/mk)
> (define #s succeed)
; readline-input:2:8: read-syntax: expected `(`, `[`, or `{` after `#s` [,bt
; for context]
#<procedure:...iniKanren/mk.rkt:337:4>
; readline-input:2:18: read-syntax: unexpected `)` [,bt for context]
I have the feeling that this has something to do with reader macros.
How can I define #s for succeed and #u for fail in Scheme and also in Racket?
I am using the canonical miniKanren implementation for Scheme and the canonical miniKanren implementation for Racket.
Identifiers in Racket can not begin with #. It is simple to bind the identifiers s and u. Redefining the meaning of #s and #u is not as simple, since it needs to happen in the reader. Normally #something signals to reader that something special is to be read.
The input (foo bar) will be read as a list, #(foo bar) will be read as a vector, and #s(foo bar) will be read as a structure. You can read about the standard syntax here:
https://docs.racket-lang.org/reference/reader.html?q=%23s#%28mod-path._reader%29
Now if you want to change the meaning of #s and #u you need to look at readtables.
Each time the reader sees an # it consults a readtable to see how to handle the following characters. Since reading happens before parsing/expansion and evaluation, you can't change the reader simply by calling a function in your program. You will need to either use
the #reader extension mechanism or create your own language.
For more on readtables: https://docs.racket-lang.org/reference/readtables.html?q=reader-macro
The Guide has an example of how to use reader extensions:
https://docs.racket-lang.org/guide/hash-reader.html
I solved all the book using
(define succeed
(lambda (s)
`(,s)))
(define SUCC succeed)
(define fail
(lambda (s)
'()))
On the other side, you should consult the source code provided by Friedman & Byrd. I solved it using mit-scheme -- no specific feature of racket is used, R6RS is enough.
For Racket, #s and #u can be defined as such (reference: Using Racket for The Reasoned Schemer):
;; #s for succeed.
(current-readtable
(make-readtable (current-readtable)
#\s
'dispatch-macro
(lambda (ch port src line col pos) succeed)))
;; #u for fail.
(current-readtable
(make-readtable (current-readtable)
#\u
'dispatch-macro
(lambda (ch port src line col pos) fail)))
Note that this only works in the REPL.
This defines #s and #u by modifying the readtable.
For Scheme, adding read syntax is defined in SRFI-10 sharp-comma external form, but the resulting #,() forms are probably awkward for most tastes. For Scheme, it is best to just define s and u because there is currently no portable way to define #s and #u.
I'm learning SICP and do the programming exercises. I have a question about exercise 4.5. The exercise 4.5 is:
Scheme allows an additional syntax for cond clauses, (<test> => <recipient>). If <test> evaluates to a true value, then <recipient> is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the <test>, and the result is returned as the value of the cond expression. For example:
(cond
((assoc 'b '((a 1) (b 2))) => cadr)
(else false))
As shown above,if <test> is true,the value of the cond clause should be (<recipient> <test>) (i.e.
then <recipient> is evaluated. Its value must be a procedure of one argument; this procedure is then invoked on the value of the <test>, and the result is returned...
But when I search the solution on the Internet, almost all I found are (list (extended-cond-recipient first) (extended-cond-test first)). It's a list consist of <recipient> and <test> , not a function call.
What should I do? It has troubled me a long time...
In The Core of the Evaluator, under “Special Forms”, is written:
• A case analysis (cond) is transformed into a nest of if expressions and then evaluated.
That is, first a transformation at the program level is done, and only after this transformation the resulting expression is evaluated. The transformation is done by the function cond->if, which does not evaluate the cond expression, only transform it in a nested list containing multiple if. This can be seen in the definition of the eval function, where there is the case:
((cond? exp) (eval (cond->if exp) env))
In the solutions that you have seen, the cond->if function is modified so that it transforms the => syntax in a list (as you have correctly observed), a list that contains the function as first element, and its argument as second element, and that list will be evaluated correctly in the subsequent steps of the interpreter.
I'm not sure if the question title is appropriate but here is what I wonder:
From the repl, I wanted to get the list of bindings defined in the current module. After some searching this seemed like a good solution:
(define (racket-symbols-set)
(list->set (namespace-mapped-symbols (module->namespace 'racket))))
(define (namespace-symbols-set)
(list->set (namespace-mapped-symbols)))
(define (module-bindings)
(set->list (set-subtract
(namespace-symbols-set)
(racket-symbols-set))))
so, calling (module-bindings) returns a list of symbols. But if I try to call a symbol from that result, such as doing ((first (module-bindings))), I get a "application: not a procedure" error although the first symbol is a procedure.
How do I call the corresponding procedure of that symbol?
You can look up the value of a namespace variable using namespace-variable-value. And since your namespace-symbols-set just uses the current namespace, which is also the default namespace for namespace-variable-value, using it is very simple.
For example, to invoke the procedure associated with the first item in the list returned by your module-bindings procedure:
((namespace-variable-value (car (module-bindings))))
Alternatively, specify your preferred namespace as the fourth argument of the namespace-variable-value call.
You need to evaluate that symbol in order for it to return the corresponding procedure.
> (define (foo) 'bar)
> (eval 'foo)
#<procedure:foo>
> ((eval 'foo))
'bar
Hence in your case
((eval (car (module-bindings))))
will call the first procedure of the list returned by module-bindings.
Let's call this function "dynamic-define".
Basically I want to write a macro or lambda that works like this:
$ (dynamic-define "variable" 123)
$ variable
$ => 123
I tried it:
(define-syntax dynamic-define
(syntax-rules ()
((_ string <body>)
(eval `(define ,(string->symbol string) <body>)))))
and it works as expected but doesn't seem to be a good solution.
I tried to use without eval like this:
(define-syntax dynamic-define
(syntax-rules ()
((_ string <body>)
(define (string->symbol string) <body>))))
But when I try to use I get this error:
Error: invalid syntax (define (string->symbol "variable") 123)
What should I do?
(PLEASE: edit this question to fit native English and erase this line please)
You're running against a fundamental problem: you cannot do a real dynamic define in a "clean" way, hence your attempt using eval. Note that the two solutions above are both not dynamic -- all they give you is the ability to write "foo" instead of foo. As I said elsewhere, using eval is usually bad, and in this case it's worse since it's eval that is used from a macro which makes it very weird. This is in addition to having an implicit quasi-quote in your macro that makes things even more confusing. You could just as well define the whole thing as a plain function:
(define (dynamic-define string <body>)
(eval `(define ,(string->symbol string) ,<body>)))
If you really need this to work, then it's best to take a step back and think about what it is that you need, exactly. On one hand, the above solutions are not dynamic since they require using the macro with a string syntax
(dynamic-define "foo" 123) ; instead of (define foo 123)
but how would it look to have a real dynamic definition that takes in a string? You'd probably expect this to define b:
(define a "b")
(dynamic-define a 123)
but this only becomes more confusing when you consider how it interacts with other bindings. For example:
(define y 123)
(define (foo s)
(define x 456)
(dynamic-define s 789)
(+ x y))
Now, assuming that dynamic-define does what you want it to do, think about what you'd get with (foo "x") and (foo "y"). Worse, consider (foo "s") and (foo "+"). And even worse, what about
(foo (random-element '("x" "y" "s" "+" "define")))
? Clearly, if this dynamic-define really does some dynamic definition, then there is no sense that you can make of this code without knowing ahead of time what name foo will be called with. Without being able to make such sense, compilation goes out the window -- but much more importantly, correctness (or generally, the meaning of your code) dies.
In my experience, this kind of pattern is much better handled with hash tables and similar devices.
using define-macro
#> (define-macro (dynamic-define varstr val)
`(define ,(string->symbol varstr) ,val))
#> (dynamic-define "variable" 123)
#> variable
123
using syntax-case
#> (define-syntax dynamic-define
(lambda (stx)
(syntax-case stx ()
((k varstr val)
(with-syntax ([var (datum->syntax-object
#'k
(string->symbol (syntax-object->datum #'varstr)))])
#'(define var val))))))
#> (dynamic-define "variable" 123)
#> variable
123
I've been looking at the if-let and when-let macros, Im having trouble determining what exactly it is that they "do". In particular, the documentation sais :
clojure.core/when-let
([bindings & body])
Macro
bindings => binding-form test
When test is true, evaluates body with binding-form bound to the value of test
I thus am somewhat confused about the way macros are documented.
1) What does the "=>" symbol mean ?
2) What does "test" refer to ?
Direct answer to your questions:
=> means "expands to", as in BNF notation. In this case it means that you need two forms: binding-form and the test.
"test" means anything that can be evaluated as bool.
By the way, I think that the docs are unclear or even maybe erroneous here. It is hard (or impossible) to deduce that the two forms constituting the bindings need to be enclosed in a vector. IMHO it should be either when-let ([[bindings] & body]) (the vector shown in the args) or bindings => [binding-form test] (the vector shown in the BNF-like expansion.)
It's often helpful when dealing with a macro to call macroexpand and see what the generated code is.
(macroexpand
'(if-let [x (myfunc)]
(foo x)
(bar))
; expands to
(let* [temp__3695__auto__ (myfunc)]
(if temp__3695__auto__ (clojure.core/let [x temp__3695__auto__]
(foo x))
(bar)))
; the generated symbols are necessary to avoid symbol
; capture but can confuse. The above is equivalent to:
(let* [ t (myfunc)]
(if t
(let [x t]
(foo x))
(bar))
So you can see that if-let is a shorthand for "bind local variable to the result of a function call and if that variable is truthy call the first form, else call the other form. The value returned by your function is only available in the 'truthy' branch."
wrt documentation convention
bindings => binding-form test
=> reads something like 'is equivalent to'
test is some form that returns a value
For most of these functions, clojuredocs is your friend, example usage often clarify things. If the clojuredocs example doesn't cut it for you, you can add your own
Consider the following code:
(if-let [x (a-function)]
(do-something-with x) ;; (a-function) returned a truthy result
(do-something-else) ;; (a-function) returned nil or false
This is like let, in that x will be bound to the return value of (a-function). This function could return nil or false. In that case, the implicit test fails and (do-something-else) will be evaluated. If x is not nil and not false, (do-something-with x) will be evaluated.
A scenario where this could be useful:
(if-let [user (find-logged-in-user)]
(do something with logged in user) ;; a user was found
(redirect to login page) ;; no user was found
I sometimes use something like the following, to conditionally add keys to a map of options:
(apply merge {:username "joe"
:email "joe#example.com"}
(when-let [name (find-full-name)] {:name name})
(when-let [dob (find-date-of-birth)] {:dob dob}))
This results in a map with :username and :email keys, and a :name key if the users' full name was found, plus a :dob key if a date of birth was found.
I hope that makes the use of if-let and when-let clearer.