why does only the last expr in a lambda block get evaluated? - scheme

I wrote this following simple piece of scheme just to see whether Scheme is doing dynamic or static binding.
Now I was expecting line 17 (myFunc 5 6) to evaluate to 56 (because I know Scheme has static-scoping).
But when I execute the code, all I get is 6 (without the 5) which makes no sense!
Could anyone please tell me what makes it print only 6?
2(define myFunc
3 (lambda (a b)
4 (define aref
5 (lambda ()
6 a))
7 (define bref
8 (lambda ()
9 b))
10 (define innerFunc
11 (lambda (a b)
12 (aref)
13 (bref)))
14
15 (innerFunc 1 2)))
16
17(myFunc 5 6)

The body of a lambda is implicitly inside a begin form. And a begin returns the value of the last expression. So this:
((lambda () 1 2 3))
Will evaluate to the same value as this:
(begin 1 2 3)
... Which is the number 3. Now if you need to simultaneously return two or more values try this (works in Racket):
(values 1 2 3)
=> 1
2
3

Related

Lazy stream of random(s): When does evaluation happen?

The following code, I thought, should define a stream of random numbers between 1 and 10:
(define random-stream (stream-cons (random 1 11) random-stream))
However, what it actually does is define a stream of a specific random number. For example:
> (stream->list (stream-take random-stream 10))
'(5 5 5 5 5 5 5 5 5 5)
I presume this is the random number that (random 1 11) produces when the definition is first parsed. I got around this by making random-stream an argument-less function:
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
This works:
> (stream->list (stream-take (random-stream) 10))
'(6 1 10 9 4 2 2 3 3 10)
So it looks to me that constants are, understandably, evaluated at read time, whereas functions are evaluated at call time. Usually this wouldn't matter, but in the case of a stream -- where you've got a recursive definition -- this makes a difference.
Is this how it works, or is it more subtle than this? Are there other cases one should be aware of regarding this difference?
Making random-stream an argument-less function is the correct solution.
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
I will explain why.
When you define a stream normally with (define my-stream (stream-cons ....)), there is only one value for the stream. Any reference to my-stream will produce the same value.
(define my-stream (stream-cons (random 1 11) my-stream))
The my-stream inside the "rest" is literally the same value eq? to the one my-stream.
> (eq? my-stream (stream-rest my-stream))
#true
So because they are the same value, they can be substituted in function calls. If (stream-first my-stream) returns 5, then (stream-first (stream-rest my-stream)) must also return 5. (This is because stream-first is a "pure" function in the sense that it returns the same output for the same inputs.)
> (eq? (stream-first my-stream) (stream-first (stream-rest my-stream)))
#true
This is not the case with the function version because every time the function is called it creates a new stream value.
(define (random-stream) (stream-cons (random 1 11) (random-stream)))
> (eq? (random-stream) (random-stream))
#false
> (eq? (stream-first (random-stream)) (stream-first (random-stream)))
#false
Since the "rest" field also calls (random-stream), the rest is different from the whole.
> (define generated-stream (random-stream))
> (eq? generated-stream (stream-rest generated-stream))
#false
> (eq? (stream-first generated-stream) (stream-first (stream-rest generated-stream)))
#false
I agree with the other answer that the problem with OP code is that random-stream is a stream for which (stream-first random-stream) is some random number, while (stream-rest random-stream) is also the same stream beginning with the same number.
I don't quite agree with "an argument-less function is the correct solution," though.
One alternative solution would be to use stream-map to map random numbers over the natural numbers:
(define random-stream/1-10
(stream-map (lambda (x) (random 1 11)) (in-naturals)))
It would be even better to create a function that makes a stream of random numbers:
(define (random-stream a b)
(stream-map (lambda (x) (random a b)) (in-naturals)))
This function can be used to create a stream (note that in-naturals is also a function that creates streams):
random_streams.rkt> (define my-stream (random-stream 1 11))
random_streams.rkt> (stream->list (stream-take my-stream 10))
'(1 1 2 7 5 7 4 2 2 9)
Using this idea of a function that creates streams, the stream-cons method can be rescued:
(define (random-stream-cons a b)
(stream-cons (random a b) (random-stream-cons a b)))
When stream-first is called on a stream created with random-stream-cons, a random number is returned; when stream-rest is called on the same stream, another stream with a random number as its first element is returned.
The created streams are persistent:
random_streams.rkt> (stream->list (stream-take random-stream/1-10 10))
'(10 9 9 1 2 7 6 2 6 6)
random_streams.rkt> (stream->list (stream-take random-stream/1-10 15))
'(10 9 9 1 2 7 6 2 6 6 10 1 2 8 5)
random_streams.rkt> (define my-stream-1 (random-stream 1 11))
random_streams.rkt> (stream->list (stream-take my-stream-1 10))
'(1 4 1 10 7 9 9 9 2 9)
random_streams.rkt> (stream->list (stream-take my-stream-1 15))
'(1 4 1 10 7 9 9 9 2 9 2 3 9 9 10)
random_streams.rkt> (define my-stream-2 (random-stream-cons 1 11))
random_streams.rkt> (stream->list (stream-take my-stream-2 10))
'(10 4 6 1 4 2 10 5 3 6)
random_streams.rkt> (stream->list (stream-take my-stream-2 15))
'(10 4 6 1 4 2 10 5 3 6 1 5 7 5 5)
This random-stream-cons/1-10 function is essentially the same as the earlier random-stream-cons function (but with no arguments); yet neither of them are streams. Both of them are functions that create streams:
(define (random-stream-cons/1-10) (stream-cons (random 1 11) (random-stream-cons/1-10)))
Each time that one of these stream creation functions is called, a new stream is returned:
random_streams.rkt> (stream->list (stream-take (random-stream-cons/1-10) 10))
'(10 8 3 10 8 8 1 8 4 5)
random_streams.rkt> (stream->list (stream-take (random-stream-cons/1-10) 10))
'(1 8 7 3 8 2 2 10 6 5)
This might be just what is desired; such functions are very useful, for example, in iteration contexts:
random_streams.rkt> (for ([x (stream-take (random-stream 1 11) 5)])
(displayln x))
2
8
9
1
3
So, functions that return streams are useful, and the resulting streams can be bound to a symbol if desired. For streams that may be needed multiple times with different values, arguments can be provided in custom stream-creation functions. But for one-off streams, stream-map already does the job of returning a stream which can be bound to a symbol just as OP had originally written.

Racket's `in-range` is not working as expected

Why does the following result in an error?
(println ((in-range 1 10 2)))
;; results in:
application: not a procedure;
expected a procedure that can be applied to arguments
given: #<stream>
arguments...: [none]
Is println not a procedure?
The following works as expected:
(for (( x (in-range 1 10 2))) (println x))
Output:
1
3
5
7
9
>
Your code has a couple of incorrect parentheses - remember: in Scheme () around an expression means procedure application (and that's what the error states); try this instead:
(println (in-range 1 10 2))
=> #<stream>
Beware! the above outputs a stream; it works in the second snippet because for consumes it. If what you intended was to print the list of values in the given range, this is the way to do it:
(println (range 1 10 2))
=> '(1 3 5 7 9)

fetch n-elements from a list Racket

How can I fetch n-elements from a list,
I know about first, rest etc, but what if I want the first 3 elements in a list,
I.E
(get-first 3 (list 1 2 3 4 5 6)) -> (list 1 2 3)
(get-first 5 (list 54 33 2 12 11 2 1 22 3 44)) -> (list 54 33 2 12 11)
This is not homework, but this code will help me complete the bigger picture of an assignment, I am really stuck and just need a few hints.
I am not allowed to use Lambda or build-list and no recursion, I somehow need to b able to do this with just map, filter, foldr etc...
As was mentioned by #AlexisKing, you can simply use the take procedure that's built-in in Racket:
(take '(1 2 3 4 5 6) 3)
=> '(1 2 3)
(take '(54 33 2 12 11 2 1 22 3 44) 5)
=> '(54 33 2 12 11)
If for some reason that's not allowed you can still roll your own version using higher-order procedures and no explicit recursion, but do notice that not using lambda is impossible, the allowed procedures you mention (map, filter, foldr) all receive a lambda as a parameter, and anyway all procedures in Scheme are lambdas under the hood.
Here's a contrived solution, passing an accumulator that remembers in what index we're in the input list while traversing it, and building the output list in the cdr part. It can't be done without using a lambda, but if it bothers you to see it there, extract it to a helper procedure and pass it along:
(define (get-first n lst)
(reverse
(cdr
(foldr (lambda (e acc)
(if (= (car acc) n)
acc
(cons (add1 (car acc))
(cons e (cdr acc)))))
'(0 . ())
(reverse lst)))))
It still works as expected, but never do such a complicated thing when a built-in procedure will do the same:
(get-first 3 '(1 2 3 4 5 6))
=> '(1 2 3)
(get-first 5 '(54 33 2 12 11 2 1 22 3 44))
=> '(54 33 2 12 11)

What is the difference between map and apply in scheme?

I am trying to learn Scheme and I am having a hard time understanding the difference between map and apply.
As I understand, map applies the function to each element of the list, and apply applies something to the arguments of a procedure.
Can they be used interchangeably?
They are not the same! Their names can actually help remember which does what.
map will take as argument one procedure and one or more lists.
The procedure will be called once for each position of the lists, using as arguments the list of elements at that position:
(map - '(2 3 4))
; => (-2 -3 -4)
map called (- 2), (- 3), (- 4) to build the list.
(map + '( 1 2 3)
'(10 20 30))
; => (11 22 33)
map called (+ 1 10) (+ 2 20) (+ 3 30) to build the list.
(map * '(2 2 -1)
'(0 3 4)
'(5 4 2))
; => (0 24 -8)
map called (* 2 0 5) (* 2 3 4) (* -1 4 2) to build the list.
map has that name because it implements a "map" (function) on a set of values (in the lists):
(map - '(2 3 4))
arguments mapping "-" result
2 === (- 2) ===> -2
3 === (- 3) ===> -3
4 === (- 4) ===> -4
(map + '( 1 2 3)
'(10 20 30))
arguments mapping "+" result
1 10 === (+ 1 10) ===> 11
2 20 === (+ 2 20) ===> 22
3 30 === (+ 3 30) ===> 33
apply will take at least two arguments, the first of them being a procedure and the last a list. It will call the procedure with the following arguments, including those inside the list:
(apply + '(2 3 4))
; => 9
This is the same as (+ 2 3 4)
(apply display '("Hello, world!"))
; does not return a value, but prints "Hello, world!"
This is the same as (display "Hello, world!").
apply is useful when you have arguments as a list,
(define arguments '(10 50 100))
(apply + arguments)
If you try to rewrite the last line without using apply, you'll realize that you need to loop over the list summing each element...
apply may also be used with more than those two arguments. The first argument must be a callable object (a procedure or a continuation). The last one must be a list. The others (between the first and the last) are objects of any type. So calling
(apply PROC a b c ... y z '(one two ... twenty))
is the same as calling
(PROC a b c ... y z one two ... twenty)
Here's a concrete example:
(apply + 1 -2 3 '(10 20))
; => 32
This is the same as (+ 1 -2 3 10 20)
apply has that name because it allows you to "apply" a procedure to several arguments.
No, apply calls its first argument as a procedure, with all the rest as its arguments, with the last one -- list -- opened up, i.e. its contents "spliced in":
(apply f a b (list c d e)) == (f a b c d e)
E.g.:
(apply + 1 2 (list 3 4 5))
;Value: 15
It is just one call; whereas map is indeed calling its first argument for each member element of its second argument.
One combined use of map and apply is the famous transpose trick:
(apply map list '((1 2 3) (10 20 30)))
;Value: ((1 10) (2 20) (3 30))
As the top answer suggested, map
The procedure will be called once for each position of the lists, using as arguments the list of elements at that position
In contrast, apply
(apply function argument-list)
pass arguments in argument-list to function all at once. So function is called only once.

Way to explode list into arguments?

Assume I have a procedure upto that when called like (upto 1 10) will generate the list '(1 2 3 4 5 6 7 8 9 10).
If I want to use this list as arguments to a function like lcm that takes multiple arguments rather than a single list, like (lcm 1 2 3 4 5 6 7 8 9 10) is there a way to do this?
Use apply: e.g
(apply lcm (upto 1 10))
"apply" applies a function to a list of arguments.
One way I found to do this using eval is the following:
(eval (cons 'lcm (upto 1 10)))
In MIT-Scheme (unsure of others) you can use the dot in your function definition.
(define (func-with-multiple-args . args)
(let loop ((args args))
(if (null? args)
'done
(begin (display (car args)) (loop (cdr args))))))
Calling with
(func-with-multiple-args 1 2 3 4)
will do the job. Note that the args get put into a list.
Fun fact: the `list' procedure is actually defined in list.scm of the MIT-Scheme "runtime" source as:
(define (list . args)
args)

Resources