miniKanren: How to define #s and #u? - scheme

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.

Related

Common Lisp No Dispatch Character Defined

I am currently reading the chapter on read-time macros from Paul Graham's "On Lisp" book.
The problem I am encountering is the following. When I run one of his examples:
(set-dispatch-macro-character #\# #\?
#’(lambda (stream char1 char2)
‘#’(lambda (&rest ,(gensym))
,(read stream t nil t))))
I get the following error:
No dispatch function defined for #\’
Why is it happening? Could it be because I am running it at the REPL? What can one do to fix it?
The PDF from which you are copying the code uses punctuation marks outside the range of basic ASCII characters you are supposed to use here:
CL-USER> (char-name #\’)
"RIGHT_SINGLE_QUOTATION_MARK"
The usual quote symbol should instead use the apostrophe character:
CL-USER> (char-name #\')
"APOSTROPHE"
The same goes for backquote:
CL-USER> (char-name #\‘)
"LEFT_SINGLE_QUOTATION_MARK"
You should be writing instead:
(set-dispatch-macro-character #\# #\?
#'(lambda (stream char1 char2)
`#'(lambda (&rest ,(gensym))
,(read stream t nil t))))
The #' is not necessary before lambda, since Common Lisp also defines a macro named lambda which expands into (function (lambda ...)).
You can test your new read macro as follows:
CL-USER> #?10
#<FUNCTION (LAMBDA (&REST #:G617)) {1001C541FB}>
CL-USER> (funcall *)
10
When using SBCL, I obtain warnings about unused variables. This happens because the code declares variables in anonymous functions but never uses them. This is not a serious problem, but generally speaking, it is better to declare which variables are ignored:
(set-dispatch-macro-character
#\# #\?
(lambda (stream &rest chars)
(declare (ignore chars))
(let ((rest (gensym)))
`(lambda (&rest ,rest)
(declare (ignore ,rest))
,(read stream t nil t)))))

Macro for renaming sequence- functions

Can I create a macro so that I can call sequence- functions with a s-? Hence, I should be able to write s-length, s-filter and s-map instead of sequence-length, sequence-filter and sequence-map. Thanks.
You can use filtered-in from racket/require to perform this sort of transformation. Here’s a simple example:
#lang racket
(require racket/require
(filtered-in (λ (name) (regexp-replace #rx"^sequence-" name "s-"))
racket/sequence))
(s-ref '(1 2 3) 1)
If you find yourself using this sort of thing often, it wouldn’t be too hard to write a require transformer that would expand to filtered-in:
#lang racket
(require (for-syntax racket/require-transform
syntax/parse)
racket/require)
(define-syntax reprefix-in
(make-require-transformer
(syntax-parser
[(_ original-prefix:id new-prefix:id require-spec:expr ...)
#:with replacer (string-append "^" (regexp-quote (symbol->string (syntax-e #'original-prefix))))
#:with replacement (symbol->string (syntax-e #'new-prefix))
(expand-import #'(filtered-in (λ (name) (regexp-replace (regexp 'replacer) name 'replacement))
(combine-in require-spec ...)))])))
Then you can use it like this:
(require (reprefix-in sequence- s- racket/sequence))
(s-ref '(1 2 3) 1)
Yes there is. To versing levels of cludgyness.
The way I highly recommend you do, however, is to use rename-in To rename each of these functions on import. So for example, your code would look like:
#lang racket
(require (rename-in racket/sequence
[sequence-length s-length]
[sequence-map s-map]
[sequence-filter s-filter]
...))
There are other more advanced ways to do this that do not require you to explicitly list out each identifier, using module->exports, regexp-match, format-id, and make-require-transformer. But this seems to brittle to me and you're better off being explicit about which names you want to rename.

Temporary Variable Assistance (Scheme)

I'm making a random sentence generator using Scheme (Pretty Big), and I'm having trouble defining temporary variables. I want to make something like this:
<NOUN1> <VERB1> <NOUN2> <but> <NOUN2> <VERB1> <NOUN2> <also>
Example: Sharks eat fish, but fish eat fish also.
I have word lists, and functions to choose a word from said list. Then, I use append to create a function. I am able to do:
(define (sentence)
(append (getNoun) '(and) (getNoun) (getVerb)))
However, I am unable to figure out a way to temporarily define a variable.
I have this so far:
(define (sentence1)
(append (getNoun)
(lambda (verb getVerb)
(noun getNoun))
(verb) (noun) '(but) (noun) (verb) (noun)))
Hints/Help please?
You are looking for let.
http://docs.racket-lang.org/reference/let.html
Here is an example usage:
(define (my-proc age)
(let ([age-plus-10 (+ age 10)])
(printf "age is ~a" age)
(printf "age-plus-10 is ~a" age-plus-10)))
Notice how we can temporarily define age-plus-10 and then use it later.

How to make a "define" that accepts string in the first parameter in SISC Scheme?

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

SICP Exercise 4.54

I have a question about Exercise 4.54 from Section 4.3.3 of Structure and Interpretation of Computer Programs (http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3.3). This exercise concerns the Amb evaluator.
The exercise is the following:
If we had not realized that require could be implemented as an ordinary procedure that uses amb, to be defined by the user as part of a nondeterministic program, we would have had to implement it as a special form. This would require syntax procedures
(define (require? exp) (tagged-list? exp 'require))
(define (require-predicate exp) (cadr exp))
and a new clause in the dispatch in analyze
((require? exp) (analyze-require exp))
as well the procedure analyze-require that handles require expressions. Complete the following definition of analyze-require.
(define (analyze-require exp)
(let ((pproc (analyze (require-predicate exp))))
(lambda (env succeed fail)
(pproc env
(lambda (pred-value fail2)
(if <??>
<??>
(succeed 'ok fail2)))
fail))))
I completed it as follows:
(define (analyze-require exp)
(let ((pproc (analyze (require-predicate exp))))
(lambda (env succeed fail)
(pproc env
(lambda (pred-value fail2)
(if (false? pred-value)
(fail2) ;; or (fail)
(succeed 'ok fail2)))
fail))))
My doubt is the following:
I know that, during execution, when the predicate value pred-value is false, require should fail; that is, it should call a failure continuation procedure. But I'm a bit confused as to whether it should call (fail) or (fail2). Which one is correct?
(fail2) is the correct one. The procedure conforms to a continuation-passing style, and the correct continuation procedure in this case is fail2.
I think (fail) is correct.
Here we have got pred-value, which means pproc evaluates well for now. But if it is false value, we treat it as bad as pproc evaluates wrong. so the continuation here is fail not fail2.
A test can be found here:
https://wizardbook.wordpress.com/2011/01/22/exercise-4-54/
(fail2)is correct, well,most of the time it doesn't matter whichever you choose,but for the following conditons:
1.the predicate part contains (amb) such as
(require (amb false true false true true))
2.the predicate part contains (set! <...> <...>)
you can check it out,this is because most of the process's fail-continuation is the same as its caller's except for the above two kinds of processes. Though it sounds some kind of ridiculous.

Resources