in racket, eval works in the repl but not in a program - racket

This does what I hoped:
$ racket
Welcome to Racket v8.3 [cs].
> (eval (list + 1 (list + 5 5)))
11
but this doesn't:
$ cat demo.rkt
#lang racket
(display (eval (list + 1 (list + 5 5))))
$ racket demo.rkt
?: function application is not allowed;
no #%app syntax transformer is bound
at: (#<procedure:+> 1 (#<procedure:+> 5 5))
context...:
What am I doing wrong?
I searched for the error, and it seems like this has never happened to anybody before

Well, I'll leave the question here with the answer in case anybody else searches for that error:
https://docs.racket-lang.org/guide/eval.html#%28part._namespaces%29
$ cat > demo.rkt
#lang racket
(define ns (make-base-namespace))
(display (eval (list + 1 (list + 5 5)) ns))
$ racket demo.rkt
11
It's all explained that it works in the repl but not a program.

Related

How to disable Racket's any s-expression value output

Example, I write a Racket script:
; filename: hello.rkt
#lang racket/base
(displayln "hello")
(+ 1 1)
and execute it:
$ racket hello.rkt
output is:
hello
2
I don't want it to print the number '2', how to disable result of the any S-expression value output?
You could use void to discard values, and begin to group several expressions together. E.g.
(void (begin (+ 1 1) (+ 2 2) (+ 3 3)))
This prints nothing.

debugging macro - unbound variable when calling

Essentially I am trying to code up a macro which will print out exactly some statement I am trying to evaluate, and the value it evaluates to.
What I have so far is the following:
(defmacro dbg (statement)
(format t "~a: ~a" statement (eval statement)))
and by typing the following into the slime repl: (dbg (* 2 2)) I get the desired result which is:
"(* 2 2): 4"
However when I try to use it in the following function **:
(defun get-start-position (curr-prime)
(dbg (/ (- (* curr-prime curr-prime) 3) 2))
(/ (- (* curr-prime curr-prime) 3) 2))
slime reports that curr-prime is unbound (and just sticking everything in a let doesn't help). To be more specific the act of trying to compile the function get-start-position results in:
2 compiler notes:
primes.lisp:27:3:
error:
during macroexpansion of (DBG (- # 3)). Use *BREAK-ON-SIGNALS* to intercept:
The variable CURR-PRIME is unbound.
primes.lisp: 29:9:
note:
deleting unreachable code
==>
CURR-PRIME
Compilation failed.
Presumably (and the second warning baffles me), the error comes about because the macro is expanded before the function which calls it gets a chance to bind curr-prime to some value (am I correct here?). That said I have no clue how to get round this issue
What am I doing wrong?
** for what its worth I am coding up a prime sieve where the indicator array has the following elements:
(3,5,7,9, ...)
This particular function will get me the index of the square of a given prime
Not a pro on Lisp macros, but this will do:
(defmacro dbg (statement)
(let ((result (gensym)))
`(let ((,result ,statement))
(format t "~a: ~a" ',statement ,result)
,result)))
then
(dbg (* 2 2))
=> (* 2 2): 4
4
and
(defun get-start-position (curr-prime)
(dbg (/ (- (* curr-prime curr-prime) 3) 2)))
(get-start-position 1)
=> (/ (- (* CURR-PRIME CURR-PRIME) 3) 2): -1
-1

I don't know how lisp macro construct its expansion? what's the exact step?

I tried to write a macro and execute it as follow. but it failed to execute.
(defmacro times_two (var) (* 2 var))
(times_two '(+ 1 2))
In my imagination, I think the expansion would be (* 2 (+ 1 2)). and after execution, the result would be 6. But failed.
I don't know why. I read the Emacs lisp manual, but I still can't understand them. I want to know what on earth the exact steps is while constructing expansion. What did the interpreter do?
When I evaluate these forms in Emacs, I get this error message when evaluating the second one:
Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p (quote (+ 1 2)))
*(2 (quote (+ 1 2)))
(lambda (var) (* 2 var))((quote (+ 1 2)))
(times_two (quote (+ 1 2)))
eval((times_two (quote (+ 1 2))))
eval-last-sexp-1(nil)
eval-last-sexp(nil)
call-interactively(eval-last-sexp nil nil)
This is showing you how it expanded the macro, which should tell you what went wrong. (The final expansion is at the top.)
The quoted expression '(+ 1 2) gets passed to the times_two macro, but a quoted list is not a valid argument to the * function.
What you actually want here is:
(defmacro times_two (var) `(* 2 ,var))
(times_two (+ 1 2))
Keep in mind that, generally, the result of a macro will be new Lisp code, not a final value. Your goal in writing a macro is to construct the form that will give you the result you want. Thus, most of the time your macro will end up using the quasiquote (`) syntax.
I suspect that you're confusing compile-time and run-time. Macros run at compile time, producing code to be executed at run-time. Generally speaking it's hard to keep these straight and it makes writing macros difficult.
In any event, when I put this into ielm, I get:
ELISP> (defmacro times_two (var)
(* 2 var))
times_two
ELISP> (times_two '(+ 1 2))
*** Eval error *** Wrong type argument: number-or-marker-p, (quote (+ 1 2))
ELISP>
At least part of the problem then is the '(+ 1 2), but then when I remove the quote the following is no better:
ELISP> (times_two (+ 1 2))
*** Eval error *** Wrong type argument: number-or-marker-p, (+ 1 2)
ELISP>
It seems that elisp is looking for a number or a marker in the place where we are putting '(+ 1 2) and (+ 1 2). Let's try using a number:
ELISP> (times_two 3)
6
That works.
Interestingly, the macro expansion of this gives:
ELISP> (macroexpand '(times_two 3))
6
Which is probably not really what we want.
When we write macros we want to return expressions to be evaluated at run time. So rather than returning a number we can try this:
ELISP> (defmacro times_two (var)
`(* 2 ,var))
The backtick (quasiquote) is a way of creating a list, but also allowing interpolation with the use of a comma. Defining times_two in this way gives:
ELISP> (times_two (+ 1 2))
6
And the expansion of:
ELISP> (macroexpand '(times_two (+ 1 2)))
(* 2
(+ 1 2))
Which is exactly how you imagined it.

mcons in dr racket

I'm having trouble reading output from dr racket. By default it displays lists using mcons. For example, sicp exercise 2.32 produces:
> (subsets (list 1 2 3))
(mcons
(mcons
'()
(mcons
(mcons 3 '())
(mcons
(mcons 2 '())
(mcons
(mcons 2 (mcons 3 '()))
(mcons
(mcons 1 '())
(mcons
(mcons 1 (mcons 3 '()))
(mcons
(mcons 1 (mcons 2 '()))
(mcons (mcons 1 (mcons 2 (mcons 3 '()))) '()))))))))
'())
I'm having trouble reading this. Is there a way to make the output look like:
(() (3) (2) (2 3) (1) (1 3) (1 2) (1 2 3))
Thanks!
Do you know what language are you using in your #lang line? The rest of the instructions below are assuming that you're using a #lang line.
If you are in #lang r5rs and you display or write the values, you should see the output you expect.
> (define p (list 1 2))
> (display p)
(1 2)
> (set-car! p 'one)
> (display p)
(one 2)
If you just type the values bare in Interactions, DrRacket will print them, and that uses the representation you're seeing. In DrRacket, you can customize the way that values print. Here's the process, step-by-step:
Go to the Language menu, and select Choose Language. You should see the language dialog pop up.
If the button on the lower left says Show Details, click it, and the dialog window should expand to include customizations.
Look for the Output Style option. There should be four choices: Constructor, Quasiquote, write, and print. Select write style, and then press Ok to confirm the customization.
Once you do this, then:
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
{1 2}
It will still print slightly differently than you expect, using curly braces, because it's trying to notate that the list structure is mutable.
If this bothers you, we can fix that. Add the following line near the top of your program (but after the #lang line).
(#%require r5rs/init)
This line pulls in a Racket-specific module called r5rs/init that tries to improve r5rs compliance; in particular, the braces should finally print as round ones for mutable pairs.
> (display (list 1 2))
(1 2)
> (write (list 1 2))
(1 2)
> (list 1 2)
(1 2)

How do I apply a symbol as a function in Scheme?

Is there a way I can apply '+ to '( 1 2 3)?
edit: what i am trying to say is that the function i get will be a symbol. Is there a way to apply that?
Thanks.
(apply (eval '+) '(1 2 3))
Should do it.
In R5RS you need
(apply (eval '+ (scheme-report-environment 5)) '(1 2 3))
The "Pretty Big" language in Dr. Scheme allows for:
(apply (eval '+) '(1 2 3))
How about 'apply'? Use the variable + instead of the symbol + .
(apply + '(1 2 3))
R5RS
;; This works the same as funcall in Common Lisp:
(define (funcall fun . args)
(apply fun args))
(funcall + 1 2 3 4) => 10
(funcall (lambda (a b) (+ a b) 2 3) => 5
(funcall newline) => *prints newline*
(apply newline) => *ERROR*
(apply newline '()) => *prints newline*
Btw, what's the deal with this "syntax highlighting" ??
In Racket's scheme it would be
#lang scheme
(define ns (make-base-namespace))
(apply (eval '+ ns) '(1 2 3))
How about the scheme "apply"
(apply + `(1 2 3)) => 6
I hope that was what you were asking :)