Reputation: 123
I'm am staying within #lang racket. I am trying to figure out how to delay a function argument from being evaluated - I cannot change the argument being passed in. For example, say I wanted to pass in do something like this:
(define (a e) 6)
Then I want to call a with this argument
(a (/ 1 0))
How can I delay the evaluation of this argument?
I tried doing something like (in the function a):
(define (a e)
(define E (lambda () e))
6)
But this still evaluates the argument first. Any advice?
Upvotes: 2
Views: 1585
Reputation: 48745
#lang racket
is an eager language, but as it's earlier generation was a R5RS Scheme it still has R5RS compatible delay
and force
:
(define (test delayed-e) 6)
(test (delay (/ 1 0)))
; ==> 6
Without the special forms you could do:
(test (thunk (/ 1 0)))
; ==> 6
;; the same as
(test (lambda () (/ 1 0)))
; ==> 6
Notice in both you need to do it when you call the functions since you need to wrap the values before the language evaluates them. In a lazy language like #lang lazy
you can write the code naively and it will do the correct thing.
#lang lazy
(define (test e) 6)
(test (/ 1 0))
; ==> 6
Now an implementation of #lang lazy
would be to have macro that decorates with delay
and force
so the core might be the same with just slightly different surface language. If there was as easy to use lazy evaluation in an eager language we wouldn't have the use for lazy languages.
EDIT
Macros are a way to do computation on the actual code. Thus if you made your function a macro instead you could have it turn into whatever you'd like:
(define-syntax test
(syntax-rules ()
((_ ignored-edpression) 6)))
(test (/ 1 0))
; ==> 6
Not it's important to know that this replaces the code with 6
. You could instead make it wrap:
(define-syntax define-lazy
(syntax-rules ()
((_ (name args ...) body ...)
(begin
(define (impl args ...)
body ...)
(define-syntax name
(syntax-rules ()
((_ margs (... ...)) (impl (delay margs) (... ...)))))))))
(define-lazy (test e) 6)
(test (/ 1 0))
; ==> 6
If you look at what this expands (test (/1 0))
to it will look like the first example. Unlike the lazy languages you would need to force
the arguments in the body explicitly though.
(define-lazy (my-if p c a)
(if (force p)
(force c)
(force a)))
(my-if (< 3 4) 10 (/ 1 0))
; ==> 10
Upvotes: 2