suppose I have the following functions:
(define (g x) (f x))
(define (f x) (+ 1 x))
I would like to temporarily call g with a different f. For example, something like this:
(let ((f (lambda (x) (+ 2 x))))
(g 5))
I would like the code above to evaluate to 7, but it doesn't. Instead, it evaluates to 6, since g calls the f outside the scope of the let.
Is there a way to do this without redefining g inside the let, and without inlining the entire body of the definition of g in the let? (In practice, g may be a very large, complicated function).
What you are asking for is dynamic rather than lexical binding of 'f'. R6RS and R7RS support this with parameters. This will do what you want:
(define f (make-parameter (lambda (x) (+ 1 x))))
(define (g x) ((f) x))
(display (g 5))(newline)
(parameterize ((f (lambda (x) (+ 2 x))))
(display (g 5))(newline))
I'm not sure that you can, but I'm by no means a Scheme expert.
I realise that you're trying to achieve this without redefining g inside the let, but how about:
(define (h f x) (f x))
(define (g x) (h f x))
(define (f x) (+ 1 x))
(let ((f (lambda (x) (+ 2 x))))
(h f 5))
That way, you preserve the behaviour of g where it's currently being called. But where you want to temporarily have a different behaviour, you can call h instead.
A bit more code for clarification:
(let ((f (lambda (x) (+ 2 x))))
(display (g 5)) ; 6
(newline)
(h f 5)) ; 7
You could use an optional parameter in g to pass the f from the let expression.
(define (g x . args)
(if (null? args)
(f x)
((car args) x)))
and
(let ((f (lambda (x) (+ 2 x))))
(g 5 f))
I found a way to do exactly what I wanted, although I have a feeling many people will not consider this kosher:
(define (g x) (f x))
(define (f x) (+ 1 x))
(let ((old-f f))
(set! f (lambda (x) (+ 2 x)))
(let ((ans (g 5)))
(set! f old-f)
ans))
; -> 7
(g 5) ; -> 6
edit In response to the comment below, I wasn't even aware that fluid-let was a thing. It even already works on MIT-Scheme. That's actually exactly what I needed. If commenter below posts something like this as an answer, it will be made the accepted answer:
(define (g x) (f x))
(define (f x) (+ 1 x))
(fluid-let ((f (lambda (x) (+ x 2))))
(g 5)) ; -> 7
(g 5) ; -> 6
Related
It's a problem in SICP book ch4,here is the code
(let ((a 1))
(define (f x)
(define b (+ a x))
(define a 5)
(+ a b))
(f 10))
the error message is “a: undefined; cannot use before initialization”,if I use lambda expression
((lambda (a)
(define (f x)
(define a 5)
(define b (+ a x))
(+ a b))
(f 10)) 1)
still dont work,but if I write this as procedure define,like this
(define (f a)
(define (g x)
(define b (+ a x))
(+ a b))
(g 10))
(f 1)
it runs without error,but these two are basically the same right? why the let and lambda expression failed? thanks.
Because it refers to the inner a, not the one in the let:
(let ((a 1))
(define (f x)
(define b (+ a x)) ; `a` here refers to
(define a 5) ; **this one**
(+ a b))
(f 10))
Internal defines are all placed in one shared scope. It is done so we can define mutually recursive functions.
If you switch the order of the two defines it'll work (put a definition above the b definition) because then a will be initialized before being used in the b initialization, but only if you use #lang racket.
In #lang sicp the following works:
(let ((a 1))
(define (f x)
(define a 5)
(define b (lambda () (+ a x)))
(+ a (b)))
(f 10))
I am trying to use lambda, but when I test it in the console, it returns #<procedure:...esktop/Lab 4.rkt:105:2>.
My code is
(define (comp f g)
(lambda (x) (f (g x))))
And my test code is
(comp (lambda (x) (+ x 1)) 3)
For some reason, lambda is deferring the evaluation. Can someone please help?
comp takes two function arguments and returns a new function - their
composition:
(define (comp f g)
(lambda (x) (f (g x))))
;Value: comp
To test it, one has to call it on a number:
((comp (lambda (x) (+ x 1))
(lambda (x) (+ x 2)))
3)
;Value: 6
I am really new to scheme functional programming. I recently came across Y-combinator function in lambda calculus, something like this Y ≡ (λy.(λx.y(xx))(λx.y(xx))). I wanted to implement it in scheme, i searched alot but i didn't find any implementation which exactly matches the above given structure. Some of them i found are given below:
(define Y
(lambda (X)
((lambda (procedure)
(X (lambda (arg) ((procedure procedure) arg))))
(lambda (procedure)
(X (lambda (arg) ((procedure procedure) arg)))))))
and
(define Y
(lambda (r)
((lambda (f) (f f))
(lambda (y)
(r (lambda (x) ((y y) x)))))))
As you can see, they dont match with the structure of this Y ≡ (λy.(λx.y(xx))(λx.y(xx))) combinator function. How can I implement it in scheme in exactly same way?
In a lazy language like Lazy Racket you can use the normal order version, but not in any of the applicative order programming languages like Scheme. They will just go into an infinite loop.
The applicative version of Y is often called a Z combinator:
(define Z
(lambda (f)
((lambda (g) (g g))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
Now the first thing that happens when this is applied is (g g) and since you can always substitute a whole application with the expansion of it's body the body of the function can get rewritten to:
(define Z
(lambda (f)
((lambda (g)
(f (lambda args (apply (g g) args))))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
I haven't really changed anything. It's just a little more code that does exactly the same. Notice this version uses apply to support multiple argument functions. Imagine the Ackermann function:
(define ackermann
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1)))))))
(ackermann 3 6) ; ==> 509
This can be done with Z like this:
((Z (lambda (ackermann)
(lambda (m n)
(cond
((= m 0) (+ n 1))
((= n 0) (ackermann (- m 1) 1))
(else (ackermann (- m 1) (ackermann m (- n 1))))))))
3
6) ; ==> 509
Notice the implementations is exactly the same and the difference is how the reference to itself is handled.
EDIT
So you are asking how the evaluation gets delayed. Well the normal order version looks like this:
(define Y
(lambda (f)
((lambda (g) (g g))
(lambda (g) (f (g g))))))
If you look at how this would be applied with an argument you'll notice that Y never returns since before it can apply f in (f (g g)) it needs to evaluate (g g) which in turn evaluates (f (g g)) etc. To salvage that we don't apply (g g) right away. We know (g g) becomes a function so we just give f a function that when applied will generate the actual function and apply it. If you have a function add1 you can make a wrapper (lambda (x) (add1 x)) that you can use instead and it will work. In the same manner (lambda args (apply (g g) args)) is the same as (g g) and you can see that by just applying substitution rules. The clue here is that this effectively stops the computation at each step until it's actually put into use.
I'm trying to create a function that wraps itself n times using a function called repeat
(define (repeat f n)
(if (= n 1)
f
(repeat (lambda (x) (f x)) (- n 1))))
((repeat inc 5) 2)
I'm expecting the result to be equal to
(inc (inc (inc (inc (inc 2))))) ; 7
But my result is 3
What am I doing wrong?
To be clear, I want repeat to return a function that accepts a single argument. f should not be applied until the return value of repeat is called with an argument.
e.g.,
(define inc5 (repeat inc 5))
(inc5 2) ; => 7
p.s.,
This is related but not identical to exercise 1.43 in SICP. I've solved the problem as it is presented there, but I'm curious if it can be solved this way too.
The problem with your definition is that (lambda (x) (f x)) is the same as f, i.e., your repeat repeats only once.
I think what you need is
(define (repeat f n)
(if (= n 1)
f
(lambda (x) (f ((repeat f (- n 1)) x)))))
PS. Note that you are using Scheme syntax under the Common Lisp tag; you might want to update one or the other.
Lets take a look at a similar function.
(define (repeat-exp fn ct)
(if (= ct 1)
fn
(repeat `(lambda (x) (,fn x)) (- ct 1))))
Calling it will get you
> (repeat-exp inc 5)
'(lambda (x)
((lambda (x)
((lambda (x)
((lambda (x)
((lambda (x)
(#<procedure:inc> x))
x))
x))
x))
x))
>
As you can see, your initial function only gets called once; in the innermost evaluation. If you want it to get called at each level, you need to call it there too.
(define (repeat-exp2 fn ct)
(if (= ct 1)
fn
`(lambda (x)
(,fn (,(repeat-exp2 fn (- ct 1)) x)))))
> (repeat-exp2 inc 5)
'(lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
((lambda (x)
(#<procedure:inc>
(#<procedure:inc> x)))
x)))
x)))
x)))
>
Now you can write the numeric equivalent.
(define (repeat2 fn ct)
(if (= ct 1)
fn
(lambda (x)
(fn ((repeat2 fn (- ct 1)) x)))))
which should do what you wanted initially.
> (repeat2 inc 5)
#<procedure>
> ((repeat2 inc 5) 2)
7
I'm currently stuck on a problem creating func and am a beginner at Scheme. In order to achieve such a result, will I have to define double inside func?
(func double 3 '(3 5 1))
would return (24 40 8) because each element is doubled 3 times.
No, double needs to be outside func because it will be passed as a parameter (bound to f) to func:
(define (double n) (* 2 n))
(define (times f e t)
(if (= t 0)
e
(times f (f e) (- t 1))))
(define (func f t lst)
(map (lambda (e) (times f e t)) lst))
then
> (func double 3 '(3 5 1))
'(24 40 8)
OTOH, in this case times could be defined inside func, but it's a reusable procedure so I'd leave it outside.
If I understand your question correctly, here's one way you can implement func:
(define (func f n lst)
(do ((n n (sub1 n))
(lst lst (map f lst)))
((zero? n) lst)))
Example usage:
> (func (lambda (x) (* x 2)) 3 '(3 5 1))
=> (24 40 8)
#lang racket
(define (repeat f x n)
(cond [(= n 0) x]
[else (f (repeat f x (- n 1)))]))
(define (func f n xs)
(map (λ(x) (repeat f x n)) xs))
(define (double x)
(* 2 x))
(func double 3 '(3 5 1))
Possibly something like this:
(define (cmap fun arg1 lst)
(map (lambda (x) (fun arg1 x)) lst))
But really you want to do this (cmap list 1 (get-some-calc x) (get-list)) but it's very difficult to make it take any curried argument and perhaps you want more than one list. You do it like this:
(let ((cval (get-come-calc x)))
(map (lambda (x) (list 1 cval x)) (get-list)))