How can i overload a function at run time in Scheme? - 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)

Related

How to count the number of if-statements in a separate file of code

I am trying to write a scheme program that counts the number of if-statement a file containing code. I know how to read in the file but I don't know how to go about counting the number of if-statements.
This is very hard without actually implementing reducing the language to a more primitive form. As an example, imagine this:
(count-ifs '(let ((if +))
(if 1 2 3)))
; ==> 0
0 is the correct amount as if is a binding shadowing if and Scheme supports shadowing so the result of that expression is 6 and not 2. let can be rewritten such that you can check this instead:
(count-ifs '((lambda (if)
(if 1 2 3))
+))
; ==> 0
It might not look like an improvement, but here you can actually fix it:
(define (count-ifs expr)
(let helper ((expr expr) (count 0))
(if (or (not (list? expr))
(and (eq? (car expr) 'lambda)
(memq 'if (cadr expr))))
count
(foldl helper
(if (eq? (car expr) 'if)
(add1 count)
count)
expr))))
(count-ifs '((lambda (if)
(if 1 2 3))
(if #t + (if if if))))
; ==> 2
Challenge is to expand the macros. You actually need to make a macro expander to rewrite the code such that the only form making bindings would be lambda. This is the same amount of work as making 80% of a Scheme compiler since once you've dumbed it down the rest is easy.
A simple way to do it could be recursion structure like this:
(define (count-ifs exp)
(+ (if-expression? exp 1 0)))
(if (pair? exp)
(+ (count-ifs (car exp)) (count-ifs (cdr exp))))
0)))
But this might overcount.
A more correct way to do it would be to process the code by checking each type of expression you see - and when you enter a lambda you need to add the variables it binds to a shadowed symbols list.

Class methods can't be used for andmap?

While working on a Racket program for managing employee time sheets, I found that I cannot use a class's member method for andmap.
#lang racket
(define example%
(class object%
(super-new)
(define/public (is-even? n)
(even? n))
(define/public (test)
(println
;; Next line causes error.
(andmap is-even? '(2 3 4))))))
;; if the following line is used, everything works properly
;;(andmap even? '(2 3 4))))))
(let ([tmp (new example%)])
(send tmp test))
DrRacket gives the following error message on attempt to run this simple program:
class: misuse of method (not in application) in: is-even?
Of course I don't need to use andmap ... It is just a luxury since I can feed a lambda and the result of map into addmap and get the same functionality...
Unfortunately, this doesn't work either, giving the same error as the previous program...
#lang racket
(define example%
(class object%
(super-new)
(define/public (iseven? n)
(even? n))
(define/public (test)
(println
(let ([true? (lambda
(v)
(equal? v #t))])
(andmap true?
;; map also refuses to use my class's method...
;; so much for my hacky workaround idea.
(map iseven? '(2 3 4))))))))
(let ([tmp (new example%)])
(send tmp test))
I like to fix my own problems so I looked up the given error message. I didn't find anything related. This leads to the following question: Why can't andmap, map, etc. use a class's method for their procedure argument?
PS: The actual class is significantly more complicated, but this is a minimal, verifiable example. :)
In Racket, a method is actually implemented by a macro that rewrites
(method arg ...)
to
(method-impl this arg ...)
where method-impl is bound either to the method implementation itself (if the method is private or final) or to some code that fetches the right method implementation from the class's vtable.
You can eta-expand the method name, like this:
(andmap (lambda (x) (is-even? x)) xs)
or you can use for/and:
(for/and ([x (in-list xs)]) (is-even? x))
You just have to use is-even? (or any other method name) in operator position.
As to why Racket's class library works that way: I'm not sure. It would be possible to make method names used as expressions (ie, not in operator position) do the lambda wrapping automatically; the current implementation deliberately doesn't do that, but I'm not sure what the rationale is.

Function Definitions After Expressions in Scheme

I understand I can't define a function inside an expression, but I'm getting errors defining one after an expression within the same nested function. I'm using R5RS with DrScheme.
For example, this throws an error, 'define: not allowed in an expression context':
(define (cube x)
(if (= x 0) 0) ;just for example, no reason to do this
(define (square x) (* x x))
(* x (square x)))
In R5RS you can only use define in rather specific places: in particular you can use it at the beginning (only) of forms which have a <body>. This is described in 5.2.2. That means in particular that internal defines can never occur after any other expression, even in a <body>.
Native Racket (or whatever the right name is for what you get with#lang racket) is much more flexible in this regard: what you are trying to do would (apart from the single-armed if) be legal in Racket.
You can use define inside another definition. Some Schemes won't allow you to have an if without the else part, though. This works for me:
(define (cube x)
(if (= x 0) 0 1) ; just for example, no reason to do this
(define (square x) (* x x))
(* x (square x)))
Have you tried making the definition at the beginning? maybe that could be a problem with your interpreter.
define inside a procedure body (that includes all forms that are syntactic sugar for procedures, like let, let*, and letrec) are only legal before other expressions and never after the first expression and it can not be the last form.
Your example shows no real reason for why you would want to have an expression before definitions. There is no way you can get anything more than moving all define up to the beginning. eg.
(define (cube x)
;; define moved to top
(define (square x) (* x x))
;; dead code moved under define and added missing alternative
(if (= x 0) 0 'undefined)
(* x (square x)))
If the code isn't dead. eg. it's the tail expression you can use let to make a new body:
(define (cube x)
(if (= x 0)
0
(let ()
;; this is top level in the let
(define (square x) (* x x))
;; required expression
(* x (square x)))))
I think perhaps we would need an example where you think it would be warranted to have the define after the expression and we'll be happy to show how to scheme it up.

Can someone explain equality to me in scheme/racket?

So I stumbled across this today and it has me puzzled.
(define (x) '(1))
(eq? (x) (x)) ;=> #t
(eq? '(1) '(1)) ;=> #f
(define (y) (list 1))
(eq? (y) (y)) ;=> #f
(eq? (list 1) (list 1)) ;=> #f
Can anyone explain what's happening here ?
When compiled this program
(define (x) '(1))
(eq? (x) (x))
(eq? '(1) '(1))
is compiled into (something like):
(define datum1 '(1))
(define datum2 '(1))
(define datum3 '(1))
(define (x) datum1)
(eq? (x) (x))
(eq? datum2 datum3)
Therefore (x) will always return the object stored in datum1.
The expressions (eq? '(1) '(1)) on the other hand will
find out that datum2 and datum3 does not store the same object.
Note: There is a choice for the compiler writer. Many Scheme implementation will compile the above program to:
(define datum1 '(1))
(define (x) datum1)
(eq? (x) (x))
(eq? datum1 datum1)
and then the result will be true in both cases.
Note: The documentation of quote doesn't explicitly state whether multiple occurrences of '(1) in a program will produce the same value or not. Therefore this behavior might change in the future. [Although I believe the current behavior is a deliberate choice]
eq? checks if the objects are the same (think "if the pointer refers to the same address in memory").
In the first case you're working with literals created at compile time. Comparing (and modifying) literals is generally undefined behaviour. Here it looks like procedure x returns the same literal every time, but in the second expression it looks like the 2 literals are not the same. As I said, undefined behaviour.
In the second case you're not working with literals but list creates a new list at execution time. So each call to y or list creates a fresh list.
uselpa's answer is correct.† I wanted to expand on what a quoted datum is, a little further, though.
As you know, all Scheme programs are internally read in as a syntax tree. In Racket, in particular, you use the read-syntax procedure to do it:
> (define stx (with-input-from-string "(foo bar)" read-syntax))
> stx
#<syntax::1 (foo bar)>
You can convert a syntax tree to a datum using syntax->datum:
> (syntax->datum stx)
'(foo bar)
quote is a special form, and what it does is return the quoted portion of the syntax tree as a datum. This is why, for many Scheme implementations, your x procedure returns the same object each time: it's returning the same portion of the syntax tree as a datum. (This is an implementation detail, and Scheme implementations are not required to have this behaviour, but it helps explain why you see what you see.)
And as uselpa's answer says, list creates a fresh list each time, if the list is non-empty. That's why the result of two separate non-empty invocations of list will always be distinct when compared with eq?.
(In Scheme, the empty list is required to be represented as a singleton object. So (eq? '() '()) is guaranteed to be true, as is (eq? (list) '()), (eq? (cdr (list 'foo)) (list)), etc.)
† I would not use the phrasing "undefined behaviour" for comparing literals because that's easily confused with the C and C++ meaning of UB, which is nasal demons, and although the result of comparing literals may not be what you expect, it would not cause your program to crash, etc. Modifying literals is nasal demons, of course.

How can I unsplice a list of expression into code?

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.

Resources