How does this code work? It does not seem like any of these functions have a parameter but yet you are able to call it with a parameter
(define (make-add-one)
(define (inc x) (+ 1 x))
inc)
(define myfn (make-add-one))
(myfn 2)
This runs and returns 3.
Lets use substitution rules. make-add-one can be rewritten like this:
(define make-add-one (lambda ()
(define inc (lambda (x) (+ 1 x))
inc))
Since inc is just returned we can simplify it further to this:
(define make-add-one (lambda ()
(lambda (x) (+ 1 x)))
Now myfn we can replace the call to make-add-one with the code that the lambda has inside:
(define myfn (make-add-one)) ; ==
(define myfn (lambda (x) (+ 1 x)))
And at last, we can use substitution rules on the last call:
(myfn 2) ; ==
((lambda (x) (+ 1 x)) 2) ; ==
(+ 1 2) ; ==
3
Now make-add-one makes a new function that is identical to all other functions it makes. It doesn't really add anything. A good example of where this is useful is this example:
(define (make-add by-what)
(lambda (value) (+ value by-what)))
(define inc (make-add 1))
(define add5 (make-add 5))
(map add5 '(1 2 3)) ; ==> (6 7 8)
(map inc '(1 2 3)) ; ==> (2 3 4)
Just to see it's the same:
(add5 2) ; ==
((make-add 5) 2) ; ==
((lambda (value) (+ value 5)) 2) ; ==
(+ 2 5) ; ==
; ==> 7
And how does this work. In a lexically scoped language, all lambda forms captures the variables that are not bound in their own parameter list from the scope which it was created. This is known as a closure. A simple example of this is here:
(define x 10)
(define test
(let ((x 20)
(lambda (y) (+ x y))))
(test 2) ; ==> 22
So in Scheme test uses x from the let even after the scope is out since the lambda was created in that scope. In a dynamically scoped language (test 2) would return 12 and the two previous examples would also produce other results and errors.
Lexical scoping came first to Algol, which is the predecessor to all the C language family languages like C, java, perl. Scheme was proably the first lisp and it was the essential design of the language itself. Without closure first version of Scheme was the same as its host langugage, MacLisp.
Lift the definition of inc out of make-add-one:
(define (inc x) (+ 1 x))
(define (make-add-one)
inc)
Now it's clearer that the expression (make-add-one) is the same as inc, and inc is clearly a procedure with one parameter.
In other words, invoking make-add-one with no arguments produces a procedure that takes one argument.
You can use the substitution method to follow the evaluation:
(myfn 2)
==> ((make-add-one) 2)
==> (inc 2)
==> (+ 1 2)
==> 3
Related
I'm working through Simply Scheme. I'm using DrRacket with this as my definitions file
https://gist.github.com/alexgian/5b351f367169b40a4ad809f0bb718e1f
I'm on exercise 17.3, which says
https://people.eecs.berkeley.edu/~bh/ssch17/lists.html
Describe the value returned by this invocation of map
> (map (lambda (x) (lambda (y) (+ x y))) '(1 2 3 4))
In DrRacket, I get the following output for that invocation of map:
(#<procedure> #<procedure> #<procedure> #<procedure>)
I know that lambda lets you return procedures. I'm having a hard time figuring out what procedure is being returned for some reason though, what exactly is happening here.
Simply substitute in turn every value of the list to the variable x in the inner function. In other words, the result is equal to:
(list (lambda (y) (+ 1 y))
(lambda (y) (+ 2 y))
(lambda (y) (+ 3 y))
(lambda (y) (+ 4 y)))
a list of four functions, each of them increasing its parameter by a different value.
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.
I am trying to make a procedure which takes a list of lambdas, and uses the return value of these lambdas. In order to create and populate this list, I made the procedure:
(define generate-list-of-numbers-lambdas
(lambda (function)
(if (= (function) 3)
(list (lambda () 2))
(cons (lambda () (- (function) 1))
(generate-list-of-numbers (lambda () (- (function) 1)))))))
This procedure takes a procedure as an argument, and generates a list of numbers from the return value of the argument procedure until 2 (IE the original argument is a procedure which returns 20, the generate-list-of-numbers makes a list (19 18 17... 3 2)
This procedure takes a procedure as an argument (the argument procedure has no arguments, itself, and just returns an integer), however, this generate-list-of-numbers-lambdas procedures generates a list, but only the first element is a lambda.
Your procedure works just fine if you recur using generate-list-of-numbers-lambdas instead of generate-list-of-numbers; you simply forgot the -lambas part of the name.
A couple more things though. Your procedure calls (function) 3 times in the body. If the result needs to be used in more than one place, you should use a let binding.
(define generate-list-of-numbers
(lambda (function)
(let ((x (function))) ;; bind `x` to `(function)`
(if (= x 3) ;; use x
(list (lambda () 2))
(cons (lambda () (- x 1)) ;; use x
(generate-list-of-numbers (lambda () (- x 1)))))))) ;; use x
Next we see (lambda () ...) littered all about the code. A tiny dose of data abstraction goes a long way here -
(define num
(lambda (x)
(lambda () x)))
(define generate-list-of-numbers
(lambda (function)
(let ((x (function)))
(if (= x 3)
(list (num 2)) ;; use num
(cons (num (- x 1)) ;; use num
(generate-list-of-numbers (num (- x 1)))))))) ;; use num
;; calling our procedure is nicer too
(generate-list-of-numbers (num 20))
We see (num (- x 1)) twice again. It should be a let binding.
(define generate-list-of-numbers
(lambda (function)
(let ((x (function)))
(if (= x 3)
(list (num 2))
(let ((next (num (- x 1)))) ;; bind `next`
(cons next (generate-list-of-numbers next)))))) ;; use `next` twice
We used num to put numbers into our container. We will use val to take numbers out.
(define val
(lambda (n)
(n)))
(map val (generate-list-of-numbers (num 20)))
;; '(19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2)
Going back, we see we can use val in our procedure too. Lastly, we rename function to n. This allows us to think purely in terms of our numbers and forget that the values are wrapped a function (thunk), or some other data container.
(define generate-list-of-numbers
(lambda (n) ;; `function` renamed to `n`
(let ((x (val n))) ;; use `val` to read value of `n`
(if (= x 3)
(list (num 2))
(let ((next (num (- x 1))))
(cons next (generate-list-of-numbers next)))))))
(map val (generate-list-of-numbers (num 20)))
;; '(19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2)
All of that said, this is a weird procedure. I can only guess it is a homework assignment or something. It almost seems like you're trying to implement a lazy list of numbers, but it's not quite right. Starting the list at n - 1 and ending at 2 is another obscure choice and red flag. If you can provide a broader goal, I may be able to update the answer and provide additional help.
I'm currently preparing for an exam and thought that writing foldl with foldr would be a nice question to get tested on.
Anyways, I know that (foldl f base lst) returns (f xn (f x(n-1) . . . (f x1 base)
with the lst being (x1 . . . xn)
So what I currently have is this:
(define (foldl/w/foldr f base lst)
(foldr (lambda (x y) (f y (f x base))) base lst)))
This doesn't quite work, and I am unsure on how to proceed.
Using Haskell's documentation as a starting point (as mentioned by #soegaard in the comments), here's a working solution for this problem, using Racket syntax:
(define (foldl/w/foldr f base lst)
((foldr (λ (ele acc) (λ (x) (acc (f ele x))))
identity
lst)
base))
For example:
(foldl/w/foldr cons '() '(1 2 3 4 5))
=> '(5 4 3 2 1)
(foldl/w/foldr + 0 '(1 2 3 4 5))
=> 15
The key to understand this is that we're accumulating lambdas with delayed computations, not values, and at the end we invoke all the chain of lambdas passing the base value to start the computation. Also notice that the identity procedure is used as the first accumulator, and we accumulate more lambdas on top of it. For instance, this call:
(foldl/w/foldr + 0 '(1 2))
Will be evaluated as follows:
((lambda (x) ; this lambda is the value returned by foldr
((lambda (x)
(identity (+ 1 x))) ; add first element in the list (this gets executed last)
(+ 2 x))) ; add second element in the list (this gets executed first)
0) ; at the end, we invoke the chain of lambdas starting with the base value
=> 3
I am not a Lisp programmer, so this maybe not syntactically perfect, but it will be something like
foldl f a l = (foldr (lambda (h p) (lambda (x) (p (f x h))) )
l
(lambda (x) (x))
a))
The trick is to accumulate function instead of result value. I am applying four arguments to foldr, because in this case regular foldr returns function, that will take "a" as an argument.
What are the increment and decrement operators in scheme programming language.
I am using "Dr.Racket" and it is not accepting -1+ and 1+ as operators.
And, I have also tried incf and decf, but no use.
They are not defined as such since Scheme and Racket try to avoid mutation; but you can easily define them yourself:
(define-syntax incf
(syntax-rules ()
((_ x) (begin (set! x (+ x 1)) x))
((_ x n) (begin (set! x (+ x n)) x))))
(define-syntax decf
(syntax-rules ()
((_ x) (incf x -1))
((_ x n) (incf x (- n)))))
then
> (define v 0)
> (incf v)
1
> v
1
> (decf v 2)
-1
> v
-1
Note that these are syntactic extensions (a.k.a. macros) rather than plain procedures because Scheme does not pass parameters by reference.
Your reference to “DrRacket” somewhat suggests you’re in Racket. According to this, you may already be effectively using #lang racket. Either way, you’re probably looking for add1 and sub1.
-> (add1 3)
4
-> (sub1 3)
2
The operators 1+ and -1+ do /not/ mutate, as a simple experiment in MIT Scheme will show:
1 ]=> (define a 3)
;Value: a
1 ]=> (1+ a)
;Value: 4
1 ]=> (-1+ a)
;Value: 2
1 ]=> a
;Value: 3
So you can implement your own function or syntactic extensions of those functions by having them evaluate to (+ arg 1) and (- arg 1) respectively.
It's easy to just define simple functions like these yourself.
;; Use: (increment x)
;; Before: x is a number
;; Value: x+1
(define (increment x)
(+ 1 x)
)