This is part of an interpreter I am making. I keep getting this error:
define not allowed in an expression context in: (define ret1 (list->string wl))
I am using DrScheme version 371, language Standard (R5RS).
(define (read-command)
(set! com '( '() ))
(set! wl (read-as-list))
(define ret1 (list->string wl))
(commRead)
ret1
)
similar issue here:
(define repl(
lambda()
(display "\nUofL>")
(define inp (read-command))
(define lengtha (length com)
In you interpreter, it seems that definitions can only appear at the beginning of the function. You should use a let* instead:
(define (read-command)
(let* ((com '('())) ; are you sure you didn't mean '(()) ?
(wl (read-as-list))
(ret1 (list->string wl)))
(commRead ret1)))
For the second problem, try this:
(define repl
(lambda ()
(display "\nUofL>")
(let ((inp (read-command))
(lengtha (length com)))
; return a value here
)))
As a side note, your code appears to be written in a procedural style - with all those set! and function calls executed for the effect. How on earth is ret1 going to be modified if you don't pass it as a parameter to commRead? I'd suggest you read a good book on Scheme programming and start writing code on a more functional style, currently your code isn't idiomatic and you'll get into trouble sooner or later.
Related
It strikes me beautiful, how i can create a REPL in Common Lisp using:
(loop (print (eval (read))))
However, since I'm a complete noob in Lisp (and dialects), I miserably failed to achieve the same in Scheme, due to the lacking loop function.
I tried to implement it as
(define (loop x) x (loop x))
But that doesn't seem to do anything (even when called as (loop (print 'foo))
So the question is: how to implement an infinite loop in Scheme?
(define (loop x)
x
(loop x))
This is an infinite loop when you call it. But it does not erad, evaluate or print. It takes an argument x, evaluates it then throws it away before callng itself with the same argument and it repeats.
For a REPL you want something like this:
(define (repl)
(display (eval (read))) ; for side effect of printing only
(repl))
Usually a REPL has a way to exit:
(define (repl)
(let ((in (read)))
(when (not (eq? in 'exit))
(print (eval in))
(repl))))
I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its
arguments. Because of this property, however, neither (and ... ) nor
(or ... ) can be defined as functions in terms of (cond ... ), though
both (and ... ) and (or ... ) can be expressed as abbreviations of
(cond ... )-expressions:
(and a b) = (cond (a b) (else #f)
and
(or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Imagine you wrote if as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom? the parts (not (pair? x)), #t and #f were evaluated before the body of my-if gets executed.
For the last example means (add (- a 1) (+ b 1)) gets evaluated regardless of what a is, even when a is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if both 10 and 20 would have been printed. This is how and and or is implemented as well.
You cannot define cond or and or or or if as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).
I'm reading The Little Schemer. And thanks to my broken English, I was confused by this paragraph:
(cond ... ) also has the property of not considering all of its
arguments. Because of this property, however, neither (and ... ) nor
(or ... ) can be defined as functions in terms of (cond ... ), though
both (and ... ) and (or ... ) can be expressed as abbreviations of
(cond ... )-expressions:
(and a b) = (cond (a b) (else #f)
and
(or a b) = (cond (a #t) (else (b))
If I understand it correctly, it says (and ...) and (or ...) can be replaced by a (cond ...) expression, but cannot be defined as a function that contains (cond ...). Why is it so? Does it have anything to do with the variant arguments? Thanks.
p.s. I did some searching but only found that (cond ...) ignores the expressions when one of its conditions evaluate to #f.
Imagine you wrote if as a function/procedure rather than a user defined macro/syntax:
;; makes if in terms of cond
(define (my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))
;; example that works
(define (atom? x)
(my-if (not (pair? x))
#t
#f))
;; example that won't work
;; peano arithemtic
(define (add a b)
(my-if (zero? a)
b
(add (- a 1) (+ b 1))))
The problem with my-if is that as a procedure every argument gets evaluated before the procedure body gets executed. thus in atom? the parts (not (pair? x)), #t and #f were evaluated before the body of my-if gets executed.
For the last example means (add (- a 1) (+ b 1)) gets evaluated regardless of what a is, even when a is zero, so the procedure will never end.
You can make your own if with syntax:
(define-syntax my-if
(syntax-rules ()
((my-if predicate consequent alternative)
(cond (predicate consequent)
(else alternative)))))
Now, how you read this is the first part is a template where the predicate consequent and alternative represent unevaluated expressions. It's replaced with the other just reusing the expressions so that:
(my-if (check-something) (display 10) (display 20))
would be replaced with this:
(cond ((check-something) (display 10))
(else (display 20)))
With the procedure version of my-if both 10 and 20 would have been printed. This is how and and or is implemented as well.
You cannot define cond or and or or or if as functions because functions evaluate all their arguments. (You could define some of them as macros).
Read also the famous SICP and Lisp In Small Pieces (original in French).
I have an experiment for my project, basically, I need to embedded some s-expression into the code and make it run, like this,
(define (test lst)
(define num 1)
(define l (list))
`#lst) ; oh, this is not the right way to go.
(define lst
`( (define num2 (add1 num))
(displayln num2)))
I want the test function be like after test(lst) in racket code:
(define (test lst)
(define num 1)
(define l (list))
(define num2 (add1 num)
(displayln num2))
How can I do this in racket?
Update
The reason I would like to use eval or the previous questions is that I am using Z3 racket binding, I need to generate formulas (which uses racket binding APIs), and then I will fire the query at some point, that's when I need to evaluate those code.
I have not figured out other ways to go in my case...
One super simple example is, imagine
(let ([arr (array-alloc 10)])
(array-set! arr 3 4))
I have some model to analyze the constructs (so I am not using racketZ3 directly), during each analyzing point, I will map the data types in the program into the Z3 types, and made some assertions,
I will generate something like:
At allocation site, I will need to make the following formula:
(smt:declare-fun arr_z3 () IntList)
(define len (make-length 10))
Then at the array set site, I will have the following assertions and to check whether the 3 is less then the length
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat)
Then finally, I will gather the formulas generated as above, and wrap them in the form which is able to fire Z3 binding to run the following gathered information as code:
(smt:with-context
(smt:new-context)
(define len (make-length 10))
(smt:assert (</s 3 (len arr_z3)))
(smt:check-sat))
This is the super simple example I can think of... making sense?
side note. Z3 Racket binding will crash for some reason on version 5.3.1, but it mostly can work on version 5.2.1
Honestly, I don’t understand what exactly you would like to achieve. To quote N. Holm, Sketchy Scheme, 4.5th edition, p. 108: »The major purpose of quasiquotation is the construction of fixed list structures that contain only a few variable parts«. I don’t think that quasiquotation would be used in a context like you are aiming at.
For a typical context of quasiquotation consider the following example:
(define (square x)
(* x x))
(define sentence
'(The square of))
(define (quasiquotes-unquotes-splicing x)
`(,#sentence ,x is ,(square x)))
(quasiquotes-unquotes-splicing 2)
===> (The square of 2 is 4)
Warning: if you're not familiar with how functions work in Scheme, ignore the answer! Macros are an advanced technique, and you need to understand functions first.
It sounds like you're asking about macros. Here's some code that defines test to be a function that prints 2:
(define-syntax-rule (show-one-more-than num)
(begin
(define num2 (add1 num))
(displayln num2)))
(define (test)
(define num1 1)
(show-one-more-than num1))
Now, I could (and should!) have written show-one-more-than as a function instead of a macro (the code will still work if you change define-syntax-rule to define), but macros do in fact operate by producing code at their call sites. So the above code expands to:
(define (test)
(define num1 1)
(begin
(define num2 (add1 num1))
(displayln num2)))
Without knowing the problem better, it's hard to say what the correct approach to this problem is. A brute force approach, such as the following:
#lang racket
(define (make-test-body lst)
(define source `(define (test)
(define num 1)
(define l (list))
,#lst))
source)
(define lst
`((define num2 (add1 num))
(displayln num2)))
(define test-source
(make-test-body lst))
(define test
(parameterize ([current-namespace (make-base-namespace)])
(eval `(let ()
,test-source
test))))
(test)
may be what you want, but probably not.
I'm working my way through SICP, using both the Ableson/Sussman
lectures and the Berkeley 61A lectures, which are far more my
speed. I'd like to do some of the Berkeley homework, but need the
definitions for sentence, butfirst, butlast and so forth. It looks like at one time there was a simply scheme language built in to Dr. Scheme, but version 4.1.5, the most recent, doesn't have it. From Planet PLT
I thought I could simply add (require (planet "simply-scheme.ss" ("dyoo"
"simply-scheme" 1 0))) in my definitions window. I get
require: PLaneT
could not find the requested package: Server had no matching package:
No package matched the specified criteria
I tried grabbing the simply.scm file from here
and pasted it into my Dr Scheme definitions window, but it doesn't work:
In Advanced Student mode, I get
read: illegal use of "."
For the line (lambda (string . args) in the following code.
(define whoops
(let ((string? string?)
(string-append string-append)
(error error)
(cons cons)
(map map)
(apply apply))
(define (error-printform x)
(if (string? x)
(string-append "\"" x "\"")
x))
(lambda (string . args)
(apply error (cons string (map error-printform args))))))
In R5RS I get
set!: cannot mutate module-required identifier in: number->string
(line 7 of the following code)
(if (char=? #\+ (string-ref (number->string 1.0) 0))
(let ((old-ns number->string)
(char=? char=?)
(string-ref string-ref)
(substring substring)
(string-length string-length))
(set! number->string
(lambda args
(let ((result (apply old-ns args)))
(if (char=? #\+ (string-ref result 0))
(substring result 1 (string-length result))
result)))))
'no-problem)
Advanced Student will never really work for you unless you're following examples that were designed for it. Most books and examples will assume R5RS or something like it. I would recommend using the Pretty Big language, as that includes both R5RS, as well as the PLT require syntax, and a few other things.
In order to use the Simply Scheme package from PLaneT, you will need to use the new require syntax (you can find this on the package listing page; it looks like the docs for the package haven't been updated):
(require (planet dyoo/simply-scheme:1:2/simply-scheme))
Following up; the Simply Scheme support library for Racket can be found at:
http://planet.plt-scheme.org/display.ss?package=simply-scheme.plt&owner=dyoo
I did some light documentation updates in http://planet.plt-scheme.org/package-source/dyoo/simply-scheme.plt/2/1/planet-docs/manual/index.html.