Guile/Scheme - redefine another module's internal function - scheme

Let's say I have the following two files:
;; demo.scm
(define-module (demo)
#:export (f))
(define (g x) 1)
(define (f x) (g x))
... and in the same directory:
;; use-demo.scm
(add-to-load-path ".")
(use-modules (demo))
(define (g x) (+ x 1))
(display (f 5))
(newline)
Running use-demo.scm in Guile (2), I get the output 1. So it looks like the function f has 'closed over' the function g that's defined in module demo. Is there any way to get around this? I really want to use the version of g that I've redefined in use-demo.scm.

OK, just for the record, I did some research and am posting the solution to this specific problem in case it helps someone.
The trick is to not redefine g locally, but rather to 'inject' the new function into the demo module's mapping of names to values.
(add-to-load-path ".")
(use-modules (demo))
(module-define! (resolve-module '(demo)) 'g
(lambda (x) (+ x 1)))
(display (f 5))
(newline)

If you have specific functions that you'd like to be able to override, you could make them configurable using parameters. This has some advantages:
You don't need to call reload-module to put the module back in its original configuration.
The changes only apply for the scope of the code which needs the modified behaviour.
It works properly when using multiple threads.
Obviously, the main disadvantage is that you need to add some boilerplate for each function that you want to allow to be overridden (although that's what hygienic macros are for, hehe).
The following code may work. I haven't run it.
;; demo.scm
(define-module (demo)
#:export (f))
(define (default-g x) 1)
(define p (make-parameter default-g))
(define (f x) ((p) x))
;; use-demo.scm
(add-to-load-path ".")
(use-modules (demo))
(define (my-g x) (+ x 1))
(parameterize ((## (demo) p) my-g)
(display (f 5))
(newline))
Obviously, if you can provide some additional information about what the application for this capability is, I might be able to suggest alternative approaches (there are a few others).

Related

Difference between usage of set! and define

In the following code:
(define x 14)
(display x) ; x = 14
(set! x 13)
(display x) ; x = 13
(define x 14)
(display x) ; x = 14
(set! y 13) ; SchemeError: y not found!
(display y)
What we a use case where someone would want to use set! over just define, if define can be used for everything that set! can be used for + the actual definition itself?
define creates a new binding between a name and a value (a variable), set! mutates an existing binding. These are not the same operation, languages like Python which confuse the operations notwithstanding.
In particular something like
(define x 1)
...
(define x 2)
is illegal: you can only create the variable once. Implementations may not check this, but that doesn't make it legal. Once you've created the binding, if you want to modify it you need to do that with set!.
A particular case where implementations (including Racket) are intentionally sloppy about this is when they are being used interactively. Quite often if you're interacting with the system you may want to say, for instance:
> (define square (λ (x) (+ x x)))
... ooops, that's not right, is it?
... Better fix it using the command-line editing
> (define square (λ (x) (* x x)))
In cases like that it's clearly better for the implementation just to allow this repeated definition of things, because it's going to make the life of users enormously easier.
But in programs such repeated definitions in the same scope are (almost?) always bugs, and they really ought to be caught: if you want to mutate a binding, use set!. Racket in particular will certainly puke on these.
Finally note that define is simply not legal in all the places set! is: even in Racket (which allows define in many more places than Scheme does) this is not even slightly legal code:
(define (foo x)
(define v x)
(if (odd? x)
(define v (* v 2))
(define v (/ v 2)))
v)
While this is
(define (foo x)
(define v x)
(if (odd? x)
(set! v (* v 2))
(set! v (/ v 2)))
v)
(It's still terrible code, but it is legal.).

Is this a usable scheme function?

Is this function from my lecture notes written correctly?
(define foo (λ (f) (+ (f 1) (f 2))))
(foo 3) doesnt work and any more arguments says it expects 1 argument. I assume the lecturer meant:
(define foo (λ (f) (+ f f)) )
As far as I know (f 1) isnt a valid way of saying anything in scheme but if the first is actually a correct function can anyone give me an example of a valid input?
(define foo (λ (f) (+ (f 1) (f 2))))
is ok. It takes a function f as an input. You can call it like this:
(define g (lambda (x) (* x 10)))
(foo g)
Update: I found this example so the function is correct as is. I am actually not sure what is happening here though.
(define foo (λ (f) (+ (f 1) (f 2))))
(foo (λ (x) (* x 2)))
Output: 6
Edit: nevermind as I was typing I eventually understood the syntax. If the parameter f is a function, then (f 1) would mean f with an input of one and then the example makes sense. Should I delete the question probably wont be of use to anyone?

How do I print my procedure call in Scheme?

I am trying to convert a C program to Scheme for an assignment I'm working on. The program is supposed to compute the area of a circle given the formal parameter (diameter, in this case). I think I have it figured out but I don't know how to print the actual value to verify it. I've tried just putting in the number into the print call. The way it is now is the method my book used. When I run the program with Dr. Racket I get:
print: undefined;
cannot reference undefined identifier
(define pi 3.14159265)
(define test 5)
(define (areac d)
(lambda (d)
(* pi (/ d 2) (/ d 2)
)))
(print (areac test))
Edit: Language is set to R5RS
If you use "define", you don't have to use "lambda", because "define" is just convenient way to give the name to the lambda-procedure. Your code must look like this:
(define pi 3.14159265)
(define test 5)
(define (areac d)
(* pi (/ d 2) (/ d 2)
))
(display (areac test))
Command for printing data in scgeme is "display". So, just write
(display (areac test))

Scheme: overload built-in procedures, general overloading

More specifically, can you overload the built-in Scheme procedure display?
More generally, how can you overload any procedure in Scheme?
Scheme doesn't have overloading based on types a`la Java/C++, it's dynamically typed so it wouldn't make sense.
You can do a few things though:
You can overload based on the structure of the arguments:
(define overload1
(case-lambda
((x y) (+ x y))
((x y z) (+ (- x y) z))))
This doesn't really help you though since display is only going to take one argument no matter what.
(define (overload-kinda x)
(cond
((list? x) (do-list x))
((symbol? x) (do-sym x))
;etc
))
Which is hacky but sometimes necessary.
My usual approach is higher order functions and the case lambda
(define my-display
(case-lambda
((x) (display x))
((x f) (display (f x)))))
Now if we need special treatment for displaying anything we pass in a function to render it.
The accepted answer don't overload the function, only define different function with same behavior.
Scheme usually allow to overwrite bultin function, so to overload the function (e.g. display) you can use something called Monkey Patch:
(define display (let ((orig display))
(lambda (x . rest)
(let ((port (if (null? rest)
(current-output-port)
(car rest))))
(if (number? x)
(orig (string-append "#<" (number->string x 16) ">") port)
(orig x port))))))
and now the display work differently with numbers. you can also use custom types like display different type of records in specific way. This is general example how to overwrite bultin function in any language that allow to modify the original binding. You save original function in variable, redefine the function and if you what to call original function you use the variable where you saved original.
The code can be abstracted away into general macro that will redefine the function and run your code on specific types of arguments, so it would be proper overloading like in Java and not only based on number of arguments like in case-lambda.
Here is example such macro (using lisp type macro):
(define-macro (overload name-spec . body)
(let ((name (car name-spec))
(args (cdr name-spec)))
`(define ,name (let ((,name ,name))
(lambda ,args
,#body)))))
(overload (display x . rest)
(let ((port (if (null? rest)
(current-output-port)
(car rest))))
(if (number? x)
(display (string-append "#<" (number->string x 16) ">") port)
(display x port))))
(display 10)
;; ==> #<a>
(display "20")
;; ==> 20

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