lambda functions and memory in scheme - scheme

I don't understand why if I write
(define (iter-list lst)
(let ((cur lst))
(lambda ()
(if (null? cur)
'<<end>>
(let ((v (car cur)))
(set! cur (cdr cur))
v)))))
(define il2 (iter-list '(1 2)))
and call (il2) 2 times I have printed: 1 then 2
(that's the result I want to have)
But if I don't put (lambda () and apply (il2) 2times I obtain then 1
In other words why associating the if part to a function lambda() makes it keep the memory of what we did when we applied the function before?

This is what's happening. First, it's important that you understand that when you write this:
(define (iter-list lst)
(let ((cur lst))
(lambda ()
...)))
It gets transformed to this equivalent form:
(define iter-list
(lambda (lst)
(let ((cur lst))
(lambda ()
...))))
So you see, another lambda was there in the first place. Now, the outermost lambda will define a local variable, cur which will "remember" the value of the list and then will return the innermost lambda as a result, and the innermost lambda "captures", "encloses" the cur variable defined above inside a closure. In other words: iter-list is a function that returns a function as a result, but before doing so it will "remember" the cur value. That's why you call it like this:
(define il2 (iter-list '(1 2))) ; iter-list returns a function
(il2) ; here we're calling the returned function
Compare it with what happens here:
(define (iter-list lst)
(let ((cur lst))
...))
The above is equivalent to this:
(define iter-list
(lambda (lst)
(let ((cur lst))
...)))
In the above, iter-list is just a function, that will return a value when called (not another function, like before!), this function doesn't "remember" anything and returns at once after being called. To summarize: the first example creates a closure and remembers values because it's returning a function, whereas the second example just returns a number, and gets called like this:
(define il2 (iter-list '(1 2))) ; iter-list returns a number
(il2) ; this won't work: il2 is just a number!
il2 ; this works, and returns 1

When you wrap the if in a lambda (and return it like that), the cur let (which is in scope for the if) is attached to the lambda. This is called a closure.
Now, if you read a little bit about closures, you'll see that they can be used to hold onto state (just like you do here). This can be very useful for creating ever incrementing counters, or object systems (a closure can be used as a kind of inside out object).

Note that in your original code, you renamed lst as cur. You didn't actually need to do that. The inner lambda (the closure to be) could have directly captured the lst argument. Thus, this would produce the same result:
(define (iter-list lst)
(lambda ()
...)) ; your code, replace 'cur' with 'lst'
Here are some example of other closure-producing functions that capture a variable:
(define (always n)
(lambda () n))
(define (n-adder n)
(lambda (m) (+ n m)))
(define (count-from n)
(lambda ()
(let ((result n))
(set! n (+ n 1))
result)))

Related

(Scheme) Is it possible to return one of two values depending on input, using only define or math statements?

The user inputs a number. When the number is above a specified amount, something happens. Something else happens if the number is below the specified amount, instead. Is it possible to achieve this without using any booleans/conditionals/ifs? As in purely through mathematical operations or function definitions?
You can do that with sgn and a hash table, for example (in Racket):
(define trigger-value 42) ; this is the reference value
(define action ; defines the actions that should happen
(hash
-1 (lambda () (displayln "below"))
0 (lambda () (displayln "BINGO"))
+1 (lambda () (displayln "above"))))
(define (test n) ; calls the right action procedure depending on n
((hash-ref action (sgn (- n trigger-value)))))
The expression (- n trigger-value) is negative when n < trigger-value, positive when n > trigger- value, and 0 if they are the same. Applying sgn to that value yields in -1, 0 or 1, respectively. That value is then used to look in the hash table which procedure should be called.
Here, the procedures just display a line, but they could also return a value, for example, which could then be used for further calculations.
testing
> (test 11)
below
> (test 90)
above
> (test 42)
BINGO
EDIT
This is the solution mentioned by #Chris in the comments:
(define action
(list
(lambda () (displayln "below"))
(lambda () (displayln "BINGO"))
(lambda () (displayln "above"))))
(define (test n) ; calls the right action procedure depending on n
((list-ref action (add1 (sgn (- n trigger-value))))))
and this is based on alists:
(define action
(list
(list -1 (lambda () (displayln "below")))
(list 0 (lambda () (displayln "BINGO")))
(list +1 (lambda () (displayln "above")))))
(define (test n) ; calls the right action procedure depending on n
((second (assv (sgn (- n trigger-value)) action))))

Scheme - How do I return a function?

This function is displaying the correct thing, but how do I make the output of this function another function?
;;generate an Caesar Cipher single word encoders
;;INPUT:a number "n"
;;OUTPUT:a function, whose input=a word, output=encoded word
(define encode-n
(lambda (n);;"n" is the distance, eg. n=3: a->d,b->e,...z->c
(lambda (w);;"w" is the word to be encoded
(if (not (equal? (car w) '()))
(display (vtc (modulo (+ (ctv (car w)) n) 26)) ))
(if (not (equal? (cdr w) '()))
((encode-n n)(cdr w)) )
)))
You're already returning a function as output:
(define encode-n
(lambda (n)
(lambda (w) ; <- here, you're returning a function!
(if (not (equal? (car w) '()))
(display (vtc (modulo (+ (ctv (car w)) n) 26))))
(if (not (equal? (cdr w) '()))
((encode-n n)(cdr w))))))
Perhaps a simpler example will make things clearer. Let's define a procedure called adder that returns a function that adds a number n to whatever argument x is passed:
(define adder
(lambda (n)
(lambda (x)
(+ n x))))
The function adder receives a single parameter called n and returns a new lambda (an anonymous function), for example:
(define add-10 (adder 10))
In the above code we created a function called add-10 that, using adder, returns a new function which I named add-10, which in turn will add 10 to its parameter:
(add-10 32)
=> 42
We can obtain the same result without explicitly naming the returned function:
((adder 10) 32)
=> 42
There are other equivalent ways to write adder, maybe this syntax will be easier to understand:
(define (adder n)
(lambda (x)
(+ n x)))
Some interpreters allow an even shorter syntax that does exactly the same thing:
(define ((adder n) x)
(+ n x))
I just demonstrated examples of currying and partial application - two related but different concepts, make sure you understand them and don't let the syntax confound you.

Using a list of functions and map (Scheme)

I have to create a function in Scheme that takes in a value X, a list of functions, and returns a list of X's applied to those functions. For example:
(f1 f2 ... fn) and x ==> ((f1 x) (f2 x) ... (fn x))
I'm able to use map to do this. I know how to apply a list of functions to another list:
(define (myMap f_list lst)
(if (null? f_list) lst
(map (car f_list)
(myMap (cdr f_list) lst))))
Is there anyway to alter this to allow me what I need?
you mean like this?
(define (applyAllTo fns x)
(map (lambda (fn) (fn x)) fns))
then
(applyAllTo (list (lambda (x) (* 2 x)) (lambda (x) (* 3 x))) 5)
==> (10 15)
you write:
create a function in Scheme that takes in a value X, a list of functions, and returns a list of X's applied to those functions.
First of all the function that you show isn't quite right:
(define (myMap f_list lst)
(if (null? f_list)
lst
really? return the 2nd argument if the 1st is an empty list? And if the 1st argument is a list of functions - judging from its name - why the 2nd is also called lst? Shouldn't it be x? And if it is, do we really want it returned when the list of functions is empty? No, when the list of functions is empty, there's nothing to apply our value to, so the overall list of results of applying x to each function in the list is ... an empty list, right? So,
(define (myMap f_list x)
the order of arguments is not important. You can change it later.
(if (null? f_list)
'()
(cons ; construct new list node
here you had map. Why? We're defining our own map-like function here. map-like functions construct an output list node by node, from results produced in a certain way from the values in the input list, node by node. I.e. we access the input list node by node, and construct the list of results node by node. Using the cons function .
( .... (car f_list) .... ) ; something to do with car
cons that on top of
(myMap (cdr f_list) x) )))
this part is right. So what do we do with the car of f_list? What is it? A function to be called. So we just call it - apply x to it. The function application syntax in Scheme is just (function argument_value). That's it.
Now you can do even more than what was asked in the assignment. For example, you can write a function that will apply each function in the input list twice to the given argument. It's easy to do, following the same general code skeleton:
(define (maplike_func a_list param) ; args order non-important
(if (null? a_list)
'()
(cons (do_something (car a_list) param)
(maplike_func (cdr a_list) param))))
In fact this skeleton is an instance of another, even more general pattern of folding:
(define (right_fold do_what on_null a_list)
(if (null? a_list)
on_null
(do_what (car a_list)
(lambda () (right_fold do_what on_null (cdr a_list))))))
With it, our function can be expressed as
(define (myMap f_list x)
(right_fold
(lambda (a r) (cons (a x) (r)))
'()
f_list))

Currying using Scheme

I have three functions for a practice exam that I am struggling on.
A function that takes a predicate "pred" and a set "x" and returns whether or not the predicate is true for all elements in the set.
What I was trying:
(define (all? pred x)
(lambda (t)
(equal? (pred t) x)))
Since pred t returns the subset of x where the predicate is true, I was trying to compare it to the original set... Which obviously isn't the way to do it.
A function that takes an operation "op" and a set "x" and returns a new set where basically the op function has been mapped to the entire set. Basically the equivalent of map, so you'd think I shouldn't be asking for help on this...
What I am trying:
(define (map op x)
(lambda (t)
(map (op t))))
I must be missing some basic aspect of currying because I feel like these operations should be simple..
So you're trying to do something like andmap
You could define a function that evaluates a list to see wether all their elements are #t values.
(define full-true?
(λ (lst)
(if (empty? lst) #t
(if (car lst) (full-true? (cdr lst))
(car lst)))
))
Then, your main function would be:
(define for-all?
(lambda
(pred lst-of-items)
(full-true? (map (lambda (x) (pred x)) lst-of-items))
))

How Do For Loops Work In Scheme?

I'm having some difficulty understanding how for loops work in scheme. In particular this code runs but I don't know why
(define (bubblesort alist)
;; this is straightforward
(define (swap-pass alist)
(if (eq? (length alist) 1)
alist
(let ((fst (car alist)) (scnd (cadr alist)) (rest (cddr alist)))
(if (> fst scnd)
(cons scnd (swap-pass (cons fst rest)))
(cons fst (swap-pass (cons scnd rest)))))))
; this is mysterious--what does the 'for' in the next line do?
(let for ((times (length alist))
(val alist))
(if (> times 1)
(for (- times 1) (swap-pass val))
(swap-pass val))))
I can't figure out what the (let for (( is supposed to do here, and the for expression in the second to last line is also a bit off putting--I've had the interpreter complain that for only takes a single argument, but here it appears to take two.
Any thoughts on what's going on here?
That's not a for loop, that's a named let. What it does is create a function called for, then call that; the "looping" behavior is caused by recursion in the function. Calling the function loop is more idiomatic, btw. E.g.
(let loop ((times 10))
(if (= times 0)
(display "stopped")
(begin (display "still looping...")
(loop (- times 1)))))
gets expanded to something like
(letrec ((loop (lambda (times)
(if (= times 0)
(display "stopped")
(begin (display "still looping...")
(loop (- times 1)))))))
(loop 10))
This isn't actually using a for language feature but just using a variation of let that allows you to easily write recursive functions. See this documentation on let (it's the second form on there).
What's going on is that this let form binds the name it's passed (in this case for) to a procedure with the given argument list (times and val) and calls it with the initial values. Uses of the bound name in the body are recursive calls.
Bottom line: the for isn't significant here. It's just a name. You could rename it to foo and it would still work. Racket does have actual for loops that you can read about here.

Resources