Hi I am trying to understand the output of the following code
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
when I use
(map (p q) (list 1 2 3))
the result is
(1 16 81)
shouldn't the answer be
(1 4 9) ?
You're mapping (p q) over the list, so start with figuring out what that is.
Using the subsitution method, you get
(p q)
==> ((lambda (x) (lambda (y) (x (x y)))) q)
==> (lambda (y) (q (q y)))
==> (lambda (y) (q ((lambda (x) (* x x)) y)))
==> (lambda (y) (q (* y y)))
==> (lambda (y) ((lambda (x) (* x x)) (* y y)))
==> (lambda (y) (* (* y y) (* y y)))
so (p q) is a function that takes a number and squares its square.
Two functions are provided:
(define p (lambda (x) (lambda (y) (x (x y)))))
(define q (lambda (x) (* x x)))
q is a function which takes a number and squares it.
p is a function which takes a function x, and returns another function where x is applied twice to y. Please note that in p, that x is in the function location of the forms, and has been highlighted in the listing to show this.
The use of x in both expressions is unfortunately confusing. You can replace any variable in a lambda expression with any other variable, for example function - this is called alpha-conversion - https://en.wikipedia.org/wiki/Lambda_calculus - and you can change the name of any named function to something more sensible. So, I've renamed q to square, the squaring function, and I've renamed p to do-twice.
(define do-twice (lambda (function) (lambda (y) (function (function y)))))
(define square (lambda (x) (* x x)))
It then becomes obvious what is happening when you evaluate do-twice square.
Francis King's answer is very clear,
this is just an extended footnote inspired by it.
Replacing identifiers with mnemonic ones (rewriting q as square) can make it easier to understand code [1]
Procedures as [first-class] values in Scheme [2] are often introduced with examples using lambda:
> (define twelve 12)
> (define square (lambda (x) (* x x)))
> (square twelve)
144
>
just as the characters 12 in the code above are the representation of a Number,
the characters (lambda (x) (* x x)) are the representation of a Procedure:
(number? 12) => #t, (procedure? (lambda (x) (* x x))) => #t
Two further code rewritings may be helpful:
using the "short-form" define for procedures, and annotating the definition
with a type signature (argument and result types):
> (define (square x) (* x x)) ;; Number -> Number
> (square 3)
9
> (define (do-twice f x) ;; (X -> X) X -> X
(f (f x)))
> (do-twice square 3)
81
> (map (lambda (x) (do-twice square x))
'(1 2 3))
(1 16 81)
>
Note that this do-twice does not yet correspond to the p of the question: making
this do-twice the first argument of map would require:
(map do-twice (make-list 3 square) '(1 2 3))
Mapping one list needs a function of one argument, so something has to produce the do-twice of
(define (do-twice x) (f (f x))) as its value:
> (define (do-twice-with f) ;; (X -> X) -> (X -> X)
(define (do-twice x) ;; X -> X
(f (f x)))
do-twice)
> ((do-twice-with square) 3)
81
> (map (do-twice-with square)
'(1 2 3))
(1 16 81)
>
So do-twice-with is the function p in the question.
do-twice-with requires a function argument (X -> X), but X can be any type, so:
> (define (repeat s) ;; String -> String
(string-append s " " s))
> ((do-twice-with repeat) "buffalo")
"buffalo buffalo buffalo buffalo"
and do-twice-with itself has type (X' -> X') (with X' standing for (X -> X)), so can be
applied to itself:
> (((do-twice-with do-twice-with) square) 3)
43046721
> (((do-twice-with do-twice-with) repeat) "buffalo") [3]
"buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo buffalo"
((((do-twice-with do-twice-with) do-twice-with) square) 3) is left as an
exercise for the reader...
[1] "Naming is perhaps the most powerful abstracting notion we have" [Guy L Steele]
[2] https://walker.cs.grinnell.edu/courses/151.sp04/readings/procedures-as-values.xhtml
[3] https://en.wikipedia.org/wiki/Buffalo_buffalo_Buffalo_buffalo_buffalo_buffalo_Buffalo_buffalo
Related
i try to realize what this expiration, and don't get it.
( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))
i think,
a is a number, and b is #t or #f,
on the if statement we ask if b is true, if yes return first expression(sum 3 numbers), else the second(Subtract 3 numbers)
what i need to write on Racket to run this?
i try
(define question( lambda (a b) (lambda (x y) (if b (+ x y a) (-x y a)))))
and than
(question 5 #f)
and nothing not going well in this language.
This is not a complete answer as I don't want to do your homework for you.
First of all formatting and indenting your code is going to help you in any programming language. You almost certainly have access to an editor which will do this. Below I've done this.
So, OK, what does a form like (λ (...) ...) denote? Well, its a function which takes some arguments (the first ellipsis) and returns the value of the last form in its body (the second ellipsis), or the only form in its body in a purely functional language.
So, what does:
(λ (a b)
(λ (x y)
...))
Denote? It's a function of two arguments, and it returns something: what is the thing it returns? Well, it's a form which looks like (λ (...) ...): you know what those forms mean already.
And finally we can fill out the last ellipsis (after correcting an error: (-x ...) is not the same as (- x ...)):
(λ (a b)
(λ (x y)
(if b
(+ x y a)
(- x y a))))
So now, how would you call this, and how would you make it do something interesting (like actually adding or subtracting some things)?
(lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a))))
is a function that takes two arguments (that's what (lambda (a b) ...) says).
You can use the substitution method to discover what it produces.
Apply it to 5 and #f:
((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f)
[Replace a with 5 and b with #f in the body]:
(lambda (x y) (if #f (+ x y 5) (- x y 5)))
And this is a function that takes two numbers and produces a new number.
(Note that the #f and the 5 became fixed by the application of the outer lambda.)
It's easier to use the function if we name it (interactions from DrRacket):
> (define question (lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))))
> (question 5 #f)
#<procedure>
which is as expected, based on the reasoning above.
Let's name this function as well:
> (define answer (question 5 #f))
and use it:
> (answer 3 4)
-6
or we could use it unnamed:
> ((question 5 #f) 3 4)
-6
or you could do it all inline, but that's a horrible unreadable mess:
> (((lambda (a b) (lambda (x y) (if b (+ x y a) (- x y a)))) 5 #f) 3 4)
-6
I am learning Scheme by 'Structure and Interpretation of Computer Programs'
In Chapter 1.3.2 Constructing Procedures Using lambda.
I understood lambda like this.
The value to match the lambda is written outside the parenthesis of the lambda.
((lambda (x) (+ x 4) 4) ; (x) is matched to 4, result is 8
But in SICP, another example code is different.
The code is :
(define (sum x y) (+ x y))
(define (pi-sum a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 3))))
a
(lambda (x) (+ x 4))
b
))
(pi-sum 3 6)
I think if (lambda (x) (/ 1.0 (* x (+ x 3)))) want match to a, lambda and a must bound by parenthesis.
But in example code, don't use parenthesis.
When I run this code, error is occurs.
error is this :
***'sum: expects only 2 arguments, but found 4'***
When I use more parenthesis like this :
(define (sum x y) (+ x y))
(define (pi-sum a b)
(sum ((lambda (x) (/ 1.0 (* x (+ x 3))))
a)
((lambda (x) (+ x 4))
b)
))
(pi-sum 2 6) ; result is 10.1
Code is run.
I'm confused because of SICP's example code.
Am I right on the principle of lambda?
If I am right, why SICP write like that?
It says to use the sum from 1.3.1. On page 77 (actually starting on 77 and ending on 78) it looks like this:
(define (sum term a next b)
(if (> a b)
0
(+ (term a)
(sum term (next a) next b))))
As you can see it looks a lot different from your sum that just adds two number together. You also had a typo in pi-sum:
(define (pi-sum a b)
(sum (lambda (x) (/ 1.0 (* x (+ x 2)))) ; multiplied by 2, not 3!
a
(lambda (x) (+ x 4))
b))
(* 8 (pi-sum 1 1000))
; ==> 3.139592655589783
So the point here is that you can pass lambdas instead of named procedures. Since (define (name . args) body ...) is just syntax sugar for (define name (lambda args body ...)) passing (lambda args body ...) instead of defining it and pass a name is just an equal refactoring.
Parentheses around a variable (+) or a lambda ((lambda args body ...)) calls whatever procedure the operator expression evaluates. It is not what you want since you pass procedures to be used by sum as an abstraction. sum can do multiplications or any number of things based on what you pass. in sum term is the procedure (lambda (x) (/ 1.0 (* x (+ x 2)))) and you see it calls it as apart of its code.
For the function foo6, give a Curried application of the procedure which evaluates to 3.
(define foo6
(lambda (x)
(x (lambda (y) (y y)))))
I've defined a foo7 to see how the last line works
(define foo7 (lambda (y) (y y)))
Is there some "y" that can both be the operator and the operand?
Edit: The question should read:
Is there some "y" that can both be the operator and the operand that will not cause an error or infinite loop?
Question taken from the Structure and Interpretation of Computer Program (SICP) Sample Programming assignments:
https://mitpress.mit.edu/sicp/psets/index.html
From the "Introductory assignment," Exercise 11:
PDF Version: https://github.com/yangchenyun/learning-sicp/raw/master/practices/assignments/01.introductory-assignment/ps1_1.pdf
PS (Original Version):
https://mitpress.mit.edu/sicp/psets/ps1/ps1_1.ps
Yes. Scheme and Racket are both Lisp1s which means they only have one namespace and thus. the variable v can be any value including procedures.
The second you see something like (lambda (y) (y y)) it obvious what type y is a procedure by the way it is being applied. For any other values than a procedure it would end with a application error:
((lambda (y) (y y)) 5)
; ERROR: application: 5 is not a procedure
The procedure itself will probably expect itself as an argument so we can assume some sort of omega or z combinator.
We have higher order procedures you pass functions as values in operand position and to use them just put then in operator position:
(define (times n p)
(lambda (arg)
(let loop ((n n) (acc arg))
(if (<= n 0)
acc
(loop (sub1 n) (p acc))))))
(define double (lambda (v) (+ v v)))
(define test (times 3 double))
(test 5) ; ==> 40
Scheme is not alone on having this feature. The same code as above can be expressed just as easily in JavaScript as it also only have one namespace and parseInt(x) evaluates the variable parseInt to a value that gets applied with the argument you get from evaluating the variable x. They are just two variables, nothing special.
EDIT
Here is an example where (lambda (y) (y y)) is used in something usefull.
;; the Z combinator
(define Z
(lambda (f)
((lambda (y)
(y y))
(lambda (g)
(f (lambda args (apply (g g) args)))))))
(define (fib n)
((Z (lambda (helper)
(lambda (n a b)
(if (zero? n)
a
(helper (- n 1) b (+ a b))))))
n 0 1))
(fib 10) ; ==> 55
The Z combinator is the Y combinator for eager languages. It makes it possibly for self reference without mutating the environment.
Yes,
(define (foobar n)
((foo6
(lambda (u) (u (lambda (y)
(lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))))))
n))
Y? I mean, why? Because
(foo6 x)
=
(x (lambda (y) (y y))
=
(x u) where u = (lambda (y) (y y))
i.e. (u y) = (y y)
So the argument to foo6 should be a function x expecting u such that u y = y y. So we give it the function such that
(foobar n)
=
((foo6 x) n)
=
((x u) n)
=
((u y) n) so, x = (lambda (u) (u (lambda (y) (lambda (n) ...))))
=
((y y) n) so, y = (lambda (y) (lambda (n) ...))
=
((lambda (n)
(if (zero? n)
1
(* n ((y y) (- n 1)))))
n)
and later, when / if ((y y) (- n 1)) needs to be evaluated, the same (lambda (n) ...) function is arrived at again as the result of (y y) application, and is used again when / if ((y y) (- (- n 1) 1)) needs to be evaluated.
Try it! What's (foobar 5) evaluating to? (ʎʇuǝʍʇpuɐpǝɹpunɥǝuo)
So, everything fits. Do u see y?
(lambda (y) (y y)) actually has a name: it is "U combinator".
I am trying to write a representation of pairs that does not use cons, car or cdr but still follows the property of pairs, i.e., (car (cons x y)) should be x and (cdr (cons x y)) should be y.
So here is one solution that I got from the SICP book:
(define (special-cons x y)
(lambda (m) (m x y)))
I was able to write another solution but it can only allow numbers:
(define (special-cons a b)
(* (expt 2 a)
(expt 3 b)))
(define (num-divs n d)
(define (iter x result)
(if (= 0 (remainder x d))
(iter (/ x d) (+ 1 result))
result))
(iter n 0))
(define (special-car x)
(num-divs x 2))
(define (special-cdr x)
(num-divs x 3))
Is there any other solution that allows for pairs for any object x and object y?
What about structs (Racket) or record-types (R6RS)?
In Racket:
#lang racket
(struct cell (x y))
(define (ccons x y) (cell x y))
(define (ccar cl) (cell-x cl))
(define (ccdr cl) (cell-y cl))
(define (cpair? cl) (cell? cl))
(define x (ccons 1 2))
(cpair? x)
=> #t
(ccar (ccons 1 2))
=> 1
(ccdr (ccons 3 4))
=> 4
This is a good way of doing it.
#lang racket
(define (my-cons x y)
(lambda (p)
(if (= p 1) x y)))
(define (my-car pair)
(pair 1))
(define (my-cdr pair)
(pair 2))
Here is the test
> (my-car (my-cons 1 '(2 3 4)))
1
> (my-cdr (my-cons 1 '(2 3 4)))
'(2 3 4)
The classic Ableson and Sussman procedural implementation from Structure and Interpretation of Computer Programs (section 2.1.3):
(define (cons x y)
(define (dispatch m)
(cond ((= m 0) x)
((= m 1) y)
(else (error "Argument not 0 or 1 -- CONS" m))))
dispatch)
(define (car z)
(z 0))
(define (cdr z)
(z 1))
Rptx's solution is roughly equivalent, and this is presented for reference.
I'm trying to write a procedure that makes use of the distributive property of an algebraic expression to simplify it:
(dist '(+ x y (exp x) (* x 5) y (* y 6)))
=> (+ (* x (+ 1 5))
(* y (+ 1 1 6))
(exp x))
(dist '(+ (* x y) x y))
=> (+ (* x (+ y 1))
y)
; or
=> (+ (* y (+ x 1))
x)
As the second example shows, there can be more than one possible outcome, I don't need to enumerate them all, just a valid one. I'm wondering if someone could provide me with at least a qualitative description of how they would start attacking this problem? Thanks :)
Oleg Kiselyov's pmatch macro makes distributing a factor across terms pretty easy:
(define dist
(λ (expr)
(pmatch expr
[(* ,factor (+ . ,addends))
`(+ ,#(map (λ (addend)
(list factor addend))
addends))]
[else
expr])))
(dist '(* 5 (+ x y))) => (+ (5 x) (5 y))
The main trick is to match a pattern and extract elements from the expression from the corresponding slots in the pattern. This requires a cond and let with tricky expressions to cdr to the right place in the list and car out the right element. pmatch writes that cond and let for you.
Factoring out common terms is harder because you have to look at all the subexpressions to find the common factors and then pull them out:
(define factor-out-common-factors
(λ (expr)
(pmatch expr
[(+ . ,terms) (guard (for-all (λ (t) (eq? '* (car t)))
terms))
(let ([commons (common-factors terms)])
`(* ,#commons (+ ,#(remove-all commons (map cdr terms)))))]
[else
expr])))
(define common-factors
(λ (exprs)
(let ([exprs (map cdr exprs)]) ; remove * at start of each expr
(fold-right (λ (factor acc)
(if (for-all (λ (e) (member factor e))
exprs)
(cons factor acc)
acc))
'()
(uniq (apply append exprs))))))
(define uniq
(λ (ls)
(fold-right (λ (x acc)
(if (member x acc)
acc
(cons x acc)))
'()
ls)))
(factor-out-common-factors '(+ (* 2 x) (* 2 y)))
=> (* 2 (+ (x) (y)))
The output could be cleaned up some more, this doesn't cover factoring out a 1, and remove-all is missing, but I'll leave all that to you.
A very general approach:
(dist expr var-list)
=> expr factored using terms in var-list
dist would have to know about "distributable" functions like +,-,*,/,etc and how each of them behave. If, say, it only knew about the first four, then :
(dist expr var-list
(if (empty? var-list) expr
(let* ([new-expr (factor expr (first var-list))])
(return "(* var " (dist new-expr (rest var-list)))))
That "return "(* var " " is not correct syntax, but you probably already knew that. I'm not a racket or lisp expert by any means, but basically this comes down to string processing? In any case, factor needs to be fleshed out so that it removes a single var from * functions and all of the var from + functions (replacing them with 1). It also needs to be smart enough to only do it when there are at least two replacements (otherwise we haven't actually done anything).