How can I unsplice a list of expression into code? - scheme

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.

Related

Using break from loop in Racket

I can use "while" loop in Racket with code from While Loop Macro in DrRacket
(define-syntax-rule (while-loop condition body ...)
(let loop ()
(when condition
body ...
(loop))))
However, I want to use break inside an infinite loop as follows:
(define (testfn)
(define x 5)
(while-loop #t ; infinite while loop;
(println x)
(set! x (sub1 x))
(when (< x 0)
(break)))) ; HOW TO BREAK HERE;
How can I insert break in above indefinite while loop? Thanks for your comments/answers.
You don't. Racket is in the Scheme family so all loops are actually done with recursion.
You break out of a loop by not recursing. Any other value would become the result of the form.
(define (helper x)
(displayln x)
(if (< x 0)
'return-value
(helper (sub1 x)))
(helper 5)
There are macros that makes the syntax simpler. Using named let is one:
(let helper ((x 5))
(displayln x)
(if (< x 0)
'return-value
(helper (sub1 x)))
Looking at your while-loop is just a macro that uses named let macro that turns into a recursive procedure.
If you instead of #t write an expression that eventually becomes false it stops. Like:
(while-loop (<= 0 x)
...)
Note that using set! to update variables in a loop is not considered good practise. If you are learning Racket try not to use set! or your new looping construct. Try using named let or letrec.
As mentioned in the accepted answer to the linked question, it's not recommended - at all! to do looping in this fashion. When using standard Scheme avoid imperative loops and prefer recursion (using helper procedures or a named let), or use iterations and comprehensions in Racket.
Also, break is not a standard Scheme construct. Consider rewriting the logic using a more idiomatic Racket that doesn't require explicit breaking and avoids the imperative style:
(define (testfn n)
(for [(x (in-range n -1 -1))]
(println x)))
(testfn 5)
=> 5
4
3
2
1
0

How to use typed scheme/racket

I am trying to learn typed scheme/racket(?). Down below I have an example from my code:
#lang typed/racket
(: add (Real Real -> Real))
(define (add x y)
(+ x y))
I would like to implement a procedure "check" which checks if two datatypes are allowed with an operator. For example,
(check '(+ int int))
Should result in
int
But
(check '(* int (+ real int)))
Should result in something like this:
The operator '+' must have two operands of the same (numerical) type.
That is, check should take a list.
Questions:
How do I implement "check"? Firstly I though "ok, I have a list, so let's use car and cdr" to get the operator and the operands but it didn't work and I don't even know why it doesn't work. I also though about making if statements like (if (and (= x y) (or (= x int) (= y int)) and so on to make the checks but... don't think this is the right way to go.
Should I make a procedure "add" or not? Is there any other way to do this? Int the examples it looks like they are only using "+", "-" and so on. Lastly; How do I check that the input "int" is an int and then gives int as output.
I am pretty lost right now and I am sorry for my pretty vaugue questions but I would be really happy if someone could help me out to understand this.
Note: the procedure add takes real numbers and output a real number so it doesn't follow along with the example too well. But I hope you grasp the idea. Thanks :)
You're asking a fascinating question, and it doesn't have a simple answer.
The program that you're trying to write is essentially a type-checker. That is, it takes an expression, and checks to see whether the given function's domain includes the arguments it's being called with. We can write one of those, but I suspect you're going to be unsatisfied. Here, let me go write one now....
#lang typed/racket
(require typed/rackunit)
;; a type is either
;; - 'number, or
;; - (list 'fn list-of-types type)
;; examples of types
'number
'(fn (number number) number)
(define-type FnTy (List 'fn (Listof Ty) Ty))
(define-type Ty (U 'number FnTy))
;; given an expression, returns a type
;; or signals an error
(: check (Any -> Ty))
(define (check input)
(cond [(and (list? input)
(pair? input)
(symbol? (car input)))
(define fn-ty (lookup-fn-type (car input)))
(define arg-types (map check (rest input)))
(cond [(equal? (cadr fn-ty) arg-types)
(caddr fn-ty)]
[else (error 'check
"expression didn't type-check: ~v\n"
input)])]
[(number? input)
'number]
[else (raise-argument-error
'check
"well-formed expression"
0 input)]))
(: lookup-fn-type (Symbol -> FnTy))
(define (lookup-fn-type fn-name)
(match fn-name
['+ '(fn (number number) number)]
[other (raise-argument-error 'lookup-fn-type
"known function name"
0 fn-name)]))
(define TEST-INPUT '(+ 3 43))
(check-equal? (check TEST-INPUT)
'number)
(check-equal? (check '(+ (+ 3 4) 129837))
'number)
Does this answer any part of your question?

Scheme definition error(short)

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.

Environment not part of a continuation?

Is the environment not part of a continuation in scheme?
I have tested this with Chicken, Gauche, Racket and Gambit, and they all behave similarly:
(define kont #f)
(let ((a 1)
(b 2))
(call-with-current-continuation
(lambda (k)
(set! kont k)
(display 'mutating)
(newline)
(set! a -1)
(set! b -2)))
(display (+ a b))
(newline))
I would expect -3 when the LET is evaluated, but +3 in the calls to kont (since I thought the program would remember the bindings of a and b before mutation):
(let ... ) ; <-- evaluating the LET above
; prints "mutating"
=> -3
(kont 100)
=> -3
(kont 100)
=> -3
So the continuation only affects control, and not the environment? In this case, why is it said that one of the ways to implement continuations is to "copy the stack" (are bindings are not on the stack?)
The continuation captures the bindings. However, as you surmise, these bindings are mutable.
You've been somewhat misled, here, by the "copies the stack" slogan. While this is a reasonable way to think about call/cc, it's not the whole story. For one thing, you really really wouldn't want a language feature that exposed whether or not local bindings were stack-allocated or not.
Instead, call/cc is defined using the notion of "program contexts". For a nice treatment of this, you might want to take a look at Shriram Krishnamurthi's (free, online) textbook PLAI, or at the (not-free, much more in-depth) book "Semantics Engineering with PLT Redex".
As an aside; your program doesn't really check what you wanted it to check, because you never invoked the captured continuation. I think you wanted to write something like this:
#lang racket
(define kont #f)
(let ([a 3])
(let/cc k
(set! kont k)
(set! a 4))
(printf "~s\n" a))
(kont)
... which shows pretty much the same behavior that you mention above.
You change the values of a and b in the environment with set!. So a and b is -1 and -2 in the continuation environment. You can not unroll side effects. There are no differences between a, b and kont in your continuation.

How can i overload a function at run time in Scheme?

rt.
I want to redefine a function at run time so that i can change the behavior of the system at run time.
thanks.
(define (foo x) ...stuff...)
(set! foo (lambda (x) ...different stuff...))
It might be advisable to use let to do this locally, this can also apply to keywords in this sense:
(let ((define +))
(define 2 3)) ; ===> 5
Or even redefine them to constants, remember, Scheme is a lisp-1:
(let ((define 2) (+ 4))
(- define +)) ; ===> -2
Or even:
(let ((quote /))
'3) ===> 1/3
Doing it only locally preserves the functional style.
Assuming you want to overload a function you defined earlier, simply define it again. This also works for redefining functions such as car and cdr, e.g. to make car into cdr:
(define (car x) (cdr x))
However, I think you won't be able to affect other already defined functions with such a redefinition, so a system function which uses car will still use the original system car and not yours:
(define (test x) (car x))
(define (car x) (cdr x))
(test '(1 2 3))
1
I guess the reason for this is that internally the symbols disappear once a function gets read or evaluated and the symbols are replaced by what they're bound to; in this case, the actual code of the function. So rebinding a symbol to a different function won't affect the rest of your already defined code. This is usually a good thing because it helps uphold referential transparency.
If you want to redefine scheme keywords such as lambda or cond, use let-syntax (see http://community.schemewiki.org/?scheme-faq-language)

Resources