;; compute the max of a list of integers
(define Y
(lambda (w)
((lambda (f)
(f f))
(lambda (f)
(w (lambda (x)
((f f) x)))))))
((Y
(lambda (max)
(lambda (l)
(cond ((null? l) -1)
((> (car l) (max (cdr l))) (car l))
(else (max (cdr l)))))))
'(1 2 3 4 5))
I wish to understand this construction. Can somebody give a clear and simple explanation for this code?
For example, supposing that I forget the formula of Y. How can I remember it , and reproduce it long after I work with it ?
Here's some related answers (by me):
Y combinator discussion in "The Little Schemer"
Unable to get implementation of Y combinator working
In Scheme, how do you use lambda to create a recursive function?
Basically, with Y defined as λr.(λh.h h) (λg.r (λx.(g g) x)), an application Y r reduces as
Y r
(λw.(λh.h h) (λg.w (λx.(g g) x))) r
(λh.h h) (λg.r (λx.(g g) x))
h h
;where
h = (λg.r (λx.(g g) x)) <----\
|
(λg.r (λx.(g g) x)) h |
r (λx.(g g) x) <-------------- | ----------\
;where | |
g = h -----/ |
;so that |
(g g) = (h h) = r (λx.(g g) x) ------/
So r must expect two arguments - first representing the recursive function to be called, and second - an actual argument:
r = λf (λx. ....x.....(f y)...... )
so that (Y r) x reduces as
(r (λx.(g g) x)) x
(r f) x
;where
f = (λx.(g g) x)
f y = (λx.(g g) x) y = (g g) y = (r f) y ; f is "fixed point" of r
The definiton f = (λx.(g g) x) means, when f y is called, (g g) y will be called, at which point g will be self-applied, r "pulled" from inside g and the result of (r f) called with y argument. I.e. any call (f y) in the body of lambda expression resulting from (r f) application, is translated back to (r f) y i.e. invocation of same body with a new argument y.
The important implementational detail is whether it is the same function body, or its copy, but the semantics are the same - we are able to enter the same function body with a new argument value.
The essence of Y combinator is replication through reference and self-application: we refer to the same thing through same name, twice; and thus we arrange for it to receive itself as an argument.
When there's no referencing, as in pure lambda calculus, and parameters receive textual copies of arguments - i.e. reduction is done by textual rewriting - this still works, because same copies get replicated and passed around, being fed as argument to self so it is available on the next iteration, if need be.
But it is much more efficient when shared referencing is available (all uses of same name refer to same thing). Under environment model of evaluation creation of self-referential function is simple as
(let ((fact #f))
(set! fact
(lambda (n) (if (< 2 n) 1
(* n (fact (- n 1))))))
fact)
In fact the definition in your answer is that of applicative-order Y combinator. With normal-order, eta-reduction can be applied without causing infinite looping, to get Ynorm = (λw.(λh.h h) (λg.w (g g))) which is canonically written as
Ynorm = (λf.(λx.f (x x)) (λx.f (x x)))
indeed
Ynorm g
= (λx.g (x x)) (λx.g (x x))
= g ((λx.g (x x)) (λx.g (x x)))
Related
I have tried following examples, but no matter y occurred or not,
The function f returns the same value as (λ(y)(f y)) after application.
I would like to do is to define a function that is not the same (-> Y X) as (λ (y)(f y)) when y occurred in y as a counter example, but I don't know how.
Do I misunderstand the meaning of The Initial Second Commandment of λ?
;;y does not occurs
(claim f (-> Nat Nat))
(define f
(λ(y)
0))
;; both return (the Nat 0)
(f 5)
((the (-> Nat Nat)
(λ(y)
(f y)))
5)
;; y occurs
(claim g (-> Nat Nat))
(define g
(λ(y)
y))
;;both return (the Nat 5)
(g 5)
((the (-> Nat Nat)
(λ(y)
(g y)))
5)
In order to create an example illustrating the importance of the caveat "...as long as y does not occur in f", we need to create a function f in which a name y occurs free. The provision that y is free in f is critical. This is also why it is difficult to create such an example: (top-level) functions cannot contain free variables. However, functions that are interior to other functions can. This is the key.
Here is function g that contains another function inside of it:
(claim g (-> Nat
(-> Nat
Nat)))
(define g
(lambda (y)
(lambda (x) ;; Call this inner
y))) ;; function "f"
(I've chosen to write the claim in this way to emphasize that we are thinking about a function inside of a function.)
To get our bearings, this simple function g expects two Nat arguments, and returns the first.
Let's call the inner function f. Note that f contains a free variable y (for this reason, f is meaningless outside of g). Let's substitute (lambda (y) (f y)) for f:
(claim g1 (-> Nat
(-> Nat
Nat)))
(define g1
(lambda (y)
(lambda (y) ;; Here we've replaced "f"
((lambda (x) ;; with an eta-expanded
y) ;; version, introducing
y)))) ;; the name "y"
We can eliminate the application to produce the following expression:
g1
---------------- SAME AS
(lambda (y)
(lambda (y)
((lambda (x)
y)
y)))
---------------- SAME AS
(lambda (y)
(lambda (y)
y))
---------------- SAME AS
(lambda (y)
(lambda (y1)
y1))
In the last step, I've renamed the second y to y1 to illustrate that the variable in the body of the inner function refers to the closer binding site, and not the farther one.
To recap, we started with a function g that "takes two (curried) arguments and returns the first". We then introduced a faulty eta-expansion around the inner function. As a result, we ended up with a function g1 that "takes two (curried) arguments and returns the second". Clearly not equivalent to the original function g.
So this commandment is about variable capture, which is the price we pay for working with names. I hope that helps!
IMPORTANT NOTE:
Due to the way that Pie checks types, you will need to introduce an annotation in the body of g if you want to try this example out:
(claim g1 (-> Nat
(-> Nat
Nat)))
(define g1
(lambda (y)
(lambda (y)
((the (-> Nat Nat)
(lambda (x)
y))
y))))
In the following code how can i have the x and y variables to reflect the expressions given at macro call time?
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
#'(lambda (w h) (list x y)))))
When expanding a call like:
(defrule (70 (* 1/2 w) (+ h 3)))
it returns:
(DESTRUCTURING-BIND (P X Y) '(70 (* 1/2 W) (+ H 3))
#'(LAMBDA (W H) (LIST X Y)))
where the original expressions with W and H references are lost. I tried back-quoting the lambda function creation:
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
`#'(lambda (w h) (list ,x ,y)))))
But a same call:
(defrule (70 (* 1/2 w) (+ h 3)))
expands to:
(DESTRUCTURING-BIND
(P X Y)
'(70 (* 1/2 W) (+ H 3))
`#'(LAMBDA (W H) (LIST ,X ,Y)))
which returns a CONS:
#'(LAMBDA (W H) (LIST (* 1/2 W) (+ H 3)))
which can not be used by funcall and passed around like a function object easily. How can i return a function object with expressions i pass in as arguments for the x y part of the init-form with possible W H references being visible by the closure function?
You're getting a cons because you have the backquotes nested.
You don't need backquote around destructuring-bind, because you're destructuring at macro expansion time, and you can do the destructuring directly in the macro lambda list.
(defmacro defrule ((p x y) &rest replication-patterns)
(let (rule-table)
`#'(lambda (w h) (list ,x ,y))))
Looking at your code:
(defmacro defrule (init-form &rest replication-patterns)
(let (rule-table)
`(destructuring-bind (p x y) ',init-form
#'(lambda (w h) (list x y)))))
You want a macro, which expands into code, which then at runtime takes code and returns a closure?
That's probably not a good idea.
Keep in mind: it's the macro, which should manipulate code at macro-expansion time. At runtime, the code should be fixed. See Barmar's explanation how to improve your code.
I want to create a function : OP from i=n to p = f(i)
OP is a binary operator
Here is my function
(defun sigmaOP (f o n p)
(loop for i from n to p do
(let (val (o (val (funcall f i))))
)
val
)
f is a function
o is the operator
n is the begining and p the end
And to call I use
(sigmaOP (lambda (x) (* 2 x)) '+ 1 3)
But it doesn't work
The o argument isn't consider as operator.
This function work if I remove o and instead there is + or *,...
Thanks
An operator is a function to call, too, so you need to precede o with funcall, or use it as a parameter in a call e.g. to reduce. Are you thinking of something like this?
(defun sigmaOP (f o n p)
(reduce o
(loop for i from n to p
collect (funcall f i))))
Call:
(sigmaOP (lambda (x) (* 2 x)) #'+ 1 3)
Im new to Scheme and trying to make function that is (in f u x), u is integer, x is a list and f binary function. The scheme expression (in + 3 '(1 2 3)) should return 3+1+2+3=9.
I have this but if i do (in + 3 '(1 2)) it return 3 not 6. What am i doing wrong?
(define (in f u x)
(define (h x u)
(if (null? x)
u
(h (cdr x) (f u (car x)))))
(h x 0))
From what I understand of what your in function is supposed to do, you can define it this way:
(define in fold) ; after loading SRFI 1
:-P
(More seriously, you can look at my implementation of fold for some ideas, but you should submit your own version for homework.)
(define (repeated f n)
if (= n 0)
f
((compose repeated f) (lambda (x) (- n 1))))
I wrote this function, but how would I express this more clearly, using simple recursion with repeated?
I'm sorry, I forgot to define my compose function.
(define (compose f g) (lambda (x) (f (g x))))
And the function takes as inputs a procedure that computes f and a positive integer n and returns the procedure that computes the nth repeated application of f.
I'm assuming that (repeated f 3) should return a function g(x)=f(f(f(x))). If that's not what you want, please clarify. Anyways, that definition of repeated can be written as follows:
(define (repeated f n)
(lambda (x)
(if (= n 0)
x
((repeated f (- n 1)) (f x)))))
(define (square x)
(* x x))
(define y (repeated square 3))
(y 2) ; returns 256, which is (square (square (square 2)))
(define (repeated f n)
(lambda (x)
(let recur ((x x) (n n))
(if (= n 0)
args
(recur (f x) (sub1 n))))))
Write the function the way you normally would, except that the arguments are passed in two stages. It might be even clearer to define repeated this way:
(define repeated (lambda (f n) (lambda (x)
(define (recur x n)
(if (= n 0)
x
(recur (f x) (sub1 n))))
(recur x n))))
You don't have to use a 'let-loop' this way, and the lambdas make it obvious that you expect your arguments in two stages.
(Note:recur is not built in to Scheme as it is in Clojure, I just like the name)
> (define foonly (repeat sub1 10))
> (foonly 11)
1
> (foonly 9)
-1
The cool functional feature you want here is currying, not composition. Here's the Haskell with implicit currying:
repeated _ 0 x = x
repeated f n x = repeated f (pred n) (f x)
I hope this isn't a homework problem.
What is your function trying to do, just out of curiosity? Is it to run f, n times? If so, you can do this.
(define (repeated f n)
(for-each (lambda (i) (f)) (iota n)))