SICP recursive let definition - scope

For
(let ((fact
(lambda (n)
(if (= n 1)
1
(* n (fact (- n 1)))))))
(fact 10))
Scheme gives an error, i wanted to confirm if my reasoning is correct,
Since (let ((var1 arg1)) body) is equivalent to evaluating the body in an environment where var1 is bound to arg1.
Above, when we are trying to calculate arg1 before the bind call, we do not find the reference as that is exactly what we are trying to bind for it to be available
But then why does this not throw
(let ((fact (lambda (n)
(if (= n 1) 1 (* n (fact (- n 1)))))))
(display 10))
as we are trying to make the binding there as well.
Also why doesn't this throw then
(define factorial
(lambda (n)
(if (= n 0)
1
(* n (factorial (- n 1))))))
(factorial 10)

The reason is that the "variable fact is not bound" error occurs only when we actually try to look up the value of "fact". Consider
(let ((fact (lambda (n) (if (= n 0)
1
(* n (fact (- n 1)))))))
(fact 0))
This does not cause an error because we do not enter the else clause and therefore do not attempt to use the value of the unbound variable fact. However, trying the same thing with 1 does give us the error.
We do not run into an error when using define because define and let have different rules. In a let binding, you create a new lexical scope, and the binding of fact in the let binding does not "leak out" from the let to the outside world. Since the right side of a let assignment must only refer to bindings from the outside world, the right side cannot refer to the binding fact.
However, in a define statement, the whole point is to introduce a new binding in the current scope (not create a new scope). In a define binding, the right side of the assignment must refer only to variables from the outside world - but this potentially includes the variable being defined, as long as accessing it is hidden behind a lambda and hence done lazily.
In fact, consider the following:
(define is-even
(lambda (n) (or (= n 0)
(is-odd (- n 1)))))
(define is-odd
(lambda (n) (and (not (= n 0))
(is-even (- n 1)))))
(display (is-odd 55))
In this case, by the time we actually call is-even, is-odd is defined in the same scope as is-even and hence we can look up its value. Similarly, when we call is-odd, is-even is already defined and hence we have a binding for its value.
Note that the following does not work:
(define is-even
(lambda (n) (or (= n 0)
(is-odd (- n 1)))))
(display (let ((is-odd (lambda (n) (and (not (= n 0))
(is-even (- n 1))))))
(is-odd 55)))
This is because the is-odd binding here is not in the same scope as is-even. It is defined in a more local binding than is-even is. The is-odd being referred to in the is-even definition cannot be the same is-odd as created in the let statement, because this is-odd is a local binding and thus cannot be referred to in the wider scope that is-even is defined in.
If we were using the old-fashioned LISP notion of "dynamic scope", also known as "call-by-name semantics", the latter example would work perfectly fine. However, Scheme does not support dynamic scope (which is definitely for the best in my view).

Related

Will recursively-called variable be free or bound?

I am trying to have a better understanding about free and bound variables. Here is an example code:
(define (what-kind-of-var? guess x)
(< (abs (- (square guess) x))
0.001))
I see that bound variables here would be guess and x, and free variables <, abs, -, and square. What if I called what-kind-of-var? recursively? Would it be a bound variable because it is binding itself?
Thanks!
It would, under dynamic binding, but Scheme has lexical scoping.
But actually it is neither. "Free" or "bound" comes from lambda calculus. what-kind-of-var? is a top-level variable, naming that lambda expression,
(define what-kind-of-var?
(lambda (guess x) ;; this
(< (abs (- (square guess) x))
0.001)))
but in lambda calculus expressions cannot be named. The only way to call it recursively in lambda calculus is to use Y combinator:
((Y (lambda (what-kind-of-var?) ;; outer
(lambda (guess x) ;; inner
(if (< (abs (- (square guess) x))
0.001)
guess
(what-kind-of-var? (+ 1 guess) x)))))
4 25)
and now of course what-kind-of-var? is bound inside that new lambda expression under Y. It's free in the nested, inner lambda, but bound in the outer one.
guess and x are parameters. They're eventually bound (to respective arguments) when the function is applied.
<, abs, -, are actually bound to procedures in the initial environment. So they're not free variables.
square would be the free variable, subject to the fact that what-kind-of-var? is not defined in its scope. (note that sqr is bound in the initial environment).
what-kind-of-var? is also not unbound, even if it calls itself recursively (assuming recursion is implemented properly in the language). (define (f param) body) can be seen as (define f (lambda (param) body)

Why (define (h n) (f 0)) evaluate to 100 when calling (h 10)?

(define n 100)
(define (f a) n)
(define (g n) n)
(define (h n) (f 0))
Why (define (h n) (f 0)) evaluate to 100 instead of 10 when calling (h 10)?
When calling (h 10), will n be redefined as 10 or still 100? How about (g 10)?
So when you make a procedure and introduce a binding it is only accessible withing the scope of that binding:
((lambda (w) (+ w 10)) 2) ; ==> 12
w ; ERROR: Undefined variable (it only exists inside the lambda)
You can rename any parameter as long as you rename all of it's use. Eg. this is the exact same:
((lambda (w2) (+ w2 10)) 2) ; w renamed to w2 and has not effect on the outcome.
Actually, many compilers rename all identifiers so that they are unique. I'll do that with your code now:
(define n_1 100)
(define (f_1 a_1) n_1)
(define (g_1 n_2) n_2)
(define (h_1 n_3) (f_1 0))
(h_1 10) ; ==> 100
This is the same code as in your question. All I've done is rename so that bindings are not shadowed by new closures that use the same names.
Do you see now why (h_1 10) evaluates to 100 now that there are no shadowed bindings?
Fun fact: In a lisp language without closures we have dynamic binding. There the variables created last in runtime dictates what n is. In a dynamic Scheme my rewrite would work the same as in a normal lexical Scheme, but your original code would evaluate (h 10) ; ==> 10 since the local dynamic binding n to 10 is the closest.

Racket struct error: given value instantiates a different structure type with the same name

I'm pretty familiar with Racket, and many in the Scheme and Lisp family, but I have no idea what is up with this error, or what is causing it:
network-biases: contract violation;
given value instantiates a different structure type with the same name
expected: network?
given: (network ...) <-- I omitted this because its useless.
Heres the function where the error is (I have a gist of the rest):
(define (update-mini-batch net mini-batch eta)
(define nabla-b (map (lambda (b)
(apply grid (shape b))) (network-biases net)))
(define nabla-w (map (lambda (w)
(apply grid (shape w))) (network-weights net)))
(define-values (nabla-b-new nabla-w-new)
(foldl (lambda (lst bw)
(define x (first lst))
(define y (second lst))
(define-values (nabla-b nabla-w) bw)
(define-values (delta-nabla-b delta-nabla-w) (backprop net x y))
(define nabla-b-new (+/ nabla-b delta-nabla-b))
(define nabla-w-new (+/ nabla-w delta-nabla-w))
(values nabla-b-new nabla-w-new)) (values nabla-b nabla-w) mini-batch))
(struct-copy network net
[biases (map (lambda (b nb)
(- b (* nb (/ eta (length mini-batch)))))
(network-biases net) nabla-b-new)]
[weights (map (lambda (w nw)
(- w (* nw (/ eta (length mini-batch)))))
(network-weights net) nabla-w-new)]))
I couldn't get an MCVE that actually threw an error, so I don't have one to give.
The distilled basics of what I'm trying to do in the above function is this:
Calculate new values for a structure's properties, and create a new structure with those new properties.
- Thanks!!
Structures in Racket are generative. This means that each time
(struct network (num-layers sizes biases weights) #:transparent)
is run, a new type of structure is created. These are all named network.
The error message you see is usually due to evaluating the structure definition twice (and it is a bit confusing since the two types have the same name).
I can't see anywhere in your code that could lead to (struct network ...) being run twice. Are you using DrRacket or an alternative environment that doesn't reset namespace?
If I open "nn.rkt" and run it, will I see the error?

Scheme list of strings

my function in scheme looks like this
(define (func1 input)
(let kloop ((x 6))
(let ((act (string-copy (func2 input2))))
(if (eq? act "") (display "null") (display act))
(if (> x 0) (kloop (- x 1)))))))
func2 return some string which is stored in act. Now I have to create a list of all strings returned by this function. Here above, I am just displaying those strings. I tried different approaches, but nothing is working out. I tried using append and cons.
Please suggest.
Your last if is missing the else case, which is where one would expect the return value of the function to be.
You don't mention how you've tried to use append and cons, but a common pattern is to pass an accumulating parameter around in the loop:
(define (five input)
(let loop ((x 5) (outputs '()))
(if (> x 0)
(loop (- x 1) (cons input outputs))
outputs)))
> (five "yes")
'("yes" "yes" "yes" "yes" "yes")
You are calling func2 on input six times. Does it return a different value each time? If not, this works:
(define (func1 input)
(make-list 6 (func2 input)))
The question is a bit confusing, you should provide a sample of the expected output for a given input. And why the empty string is treated differently in your code? apparently the recursion should advance on the value of x, not the value of the string returned by func2. Also, why are you copying the string? seems unnecessary.
Assuming that the named let is used just for keeping track of the number of iterations, this solution seems aligned with your intent, as this will return a 6-element list of all strings returned by func2
(define (func1 input)
(let kloop ((x 6))
(if (zero? x)
'()
(cons (func2 input)
(kloop (- x 1))))))
But we can be smarter and use the named let to give a tail-recursive solution, which is more efficient:
(define (func1 input)
(let kloop ((x 6)
(acc '()))
(if (zero? x)
acc
(kloop (- x 1)
(cons (func2 input)
acc)))))

Scheme - list functions with filter

I am currently working on a homework assignment with MIT scheme, and have come across a few problems that are supposedly very short, though I'm a bit confused as to how to implement some of them.
One problem asks me to write a function that returns a list with all the integers removed. I did manage to solve that,
(define (f2a lst) (map (lambda(x) (remove number? x)) lst))
though I'm confused as to how I can rewrite it to not use remove, but rather use a filter.
*note: (f2a '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns '(("a" "b") ("c") ("d"))
The other two problems are ones to which I haven't found any solutions.
They ask me to write a function that returns a list with all positive odd and negative even integers removed. For example,
(f2b '(("a" 1 "b") (2 "c") (-1 "d") (-2)))
returns
(("a" "b") (2 "c") (-1 "d"))
I have some code down that is incorrect, but I feel shows how I have tried to approach solving this one:
(define (f2b lst)
(lambda(x)
(cond ((and (positive? x) (odd? x)) (filter x lst))
((and (negative? x) (even? x)) (filter x lst))
(else "this should never print"))))
The last problem simply asks for a function that returns a string consisting of all strings appended together in a list. (f2c '(("a" 1 "b") (2 "c") (-1 "d") (-2))) returns "abcd".
I almost managed to figure this one out, but got stuck when it kept returning strange values. This is the code I have:
(define (f2c lst)
(lambda(x)
(map (lambda (x) (filter string? x)) lst)
(list x))
(string-append (car lst) (cdr lst)))
In terms of higher-order syntax, I'm limited to map, filter, accumulate and sum. I am not asking for a direct answer, but rather some help for me to figure out what I need to do. What am I doing wrong with my code? Any assistance given with this is very much appreciated. Thank you.
The structure of the input and the desired output is identical in the first two problems; the only thing that differs is the predicate on when/when-not to remove an element. For the second case it would be:
(define (f2b lst)
(map (lambda (sublst)
(remove (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x)))))
sublst))
lst))
Since only the predicate differs you can generalize this as:
(define (f2x predicate)
(lambda (lst)
(map (lambda (sublst) (remove predicate sublst)) lst)))
(define f2a (f2x number?))
(define f2b (f2x (lambda (x)
(and (number? x)
(or (and (positive? x) (odd? x))
(and (negative? x) (even? x))))))
For your last problem, you can use the result of the first problem as:
(define (f2c lst)
(apply string-append (apply append (f2a list))))
Also, note that your syntax for f2b and f2a is incorrect. You are using
(define (func arg)
(lambda (x) ...))
which means that (func arg) returns a function which isn't what you want.

Resources