Unable to use eval on user input in Racket
Asked Answered
H

2

6

I'm currently learning Scheme (using Racket), but one of the challenges I'm coming upon is trying to execute the following bit of code, which is meant to execute Racket code from user input using eval:

(display (eval (read)))

 

Here's some of the weird behavior I've observed so far:

  1. (display (eval (read))) in the definition window prompts for keyboard input, as expected, when the definitions are run. However, providing the input
    ((lambda (x) (+ x 1)) 1)
     
    gives the error
    ?: function application is not allowed; no #%app syntax transformer is bound in: ((lambda (x) (+ x 1)) 1)

  2. On the other hand, using (display ((eval (read)) 1)) and providing input
    (lambda (x) (+ x 1))
     
    returns the error
    lambda: unbound identifier; also, no #%app syntax transformer is bound in: lambda

  3. However, running (display (eval (read))) and providing ((lambda (x) (+ x 1)) 1) in the console pane, as opposed to the definitions pane, prints out 2, as expected.

What is the reason for this behavior?

Houseclean answered 16/5, 2016 at 2:50 Comment(3)
I'm wondering, are you using eval because you're curious, or are you trying to do something that you don't know how to do otherwise?Yonder
@Alex I'm using eval because I'm curious, not because I'm trying to do any workarounds.Houseclean
Hey Edwin just a heads up, Racket is a different language from Scheme, not just a scheme dialect. (Just like C++ is a different language than C, even though they look vary similar.) As Alex's answer indicates, the solution to your problem is going to be very different from the solution to this problem in Scheme, as they both have different syntax and evaluation models. As such, I'm going to update this question to remove the scheme references because they're unrelated. If you'd rather leave them in feel free to undo that edit. :)Felicitation
Y
9

It looks like you don't have the namespace set up. If you're running (eval (read)) within a file, it doesn't work because the current-namespace is set to an empty namespace by default. You can set up a namespace with racket/base in it by doing (current-namespace (make-base-namespace)) first:

#lang racket
(current-namespace (make-base-namespace))
(println (eval (read)))

Running this program and giving it the input ((lambda (x) (+ x 1)) 1) results in it printing 2.

The reason it worked in the interactions window (item 3 of your weird-behavior list), is that in the interactions window, the current-namespace parameter is set to the namespace of the file.

This is not true for the definitions window, the main program, so you have to set the current-namespace yourself, or pass a namespace in as a second argument to eval:

#lang racket
(define ns (make-base-namespace))
(println (eval (read) ns))
Yonder answered 16/5, 2016 at 3:1 Comment(1)
Interesting. That fixed it.Houseclean
C
2

Racket, the software package, has support for both R5RS and R6RS and will probably get support for R7RS. The software also has several non standard languages in its own Racket language family that has much in common with Scheme but is not Scheme. Alex has made an excellent answer for that language so I though I'd add information about Scheme since you write you're learning Scheme which is not the same as learning Racket when it comes some corner cases including eval.

eval is a procedure which has had breaking changes between the different Scheme reports since it became mandatory in R5RS. Here are some examples from different versions of the standard:

#!r6rs

(import (rnrs)
        (rnrs eval))

(display (eval '((lambda (x) (+ x 1)) 1) 
               (environment '(rnrs)))) 
; ==> undefined, prints 2

The slightly older but still in common used R5RS:

#!r5rs

(display (eval '((lambda (x) (+ x 1)) 1) 
               (scheme-report-environment 5))) 
; ==> undefined, prints 2

The to come R7RS which only has it's small version ratified so far:

#!r7rs

(import (scheme)
        (scheme eval))

(display (eval '((lambda (x) (+ x 1)) 1) 
               (environment '(scheme)))) 
; ==> undefined, prints 2
Cru answered 20/5, 2016 at 8:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.