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)
Related
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.
I'm studying SICP and at the beginning of section 2.2.2 it gives the following code: (cons '(list 1 2) (list 3 4))) and says it constructs a list like ((1 2) 3 4). But when I typed it into DrRacket(I'm using Racket here actually) it produces '((list 1 2) 3 4) and if I write (cons (list 1 2) (list 3 4)) then it'll be alright. I know in Scheme '(1 2) is equal to (list 1 2) but what does '(list 1 2) mean?
It should mean "a list consisting of the atom list, the atom 1, and the atom 2". Until Scheme evaluates the list (which the single quote prevents), it doesn't treat "list" differently from any other string.
Scheme has a convenient syntax for representing data literals: prefix any expression with ' (single quote) and the expression, rather than being evaluated, will be returned as data
For more informations:
http://courses.cs.washington.edu/courses/cse341/04wi/lectures/14-scheme-quote.html
Fix output style
First off, When you use the #!racket language in DrRacket, the default way of printing is not printing it's representation but an expression that evaluates to the same. You can turn it off from the menu language >> choose language. You select Show details and under Output style you select write
After pressing Run, when evaluating 'test you will get the output test.
Typo in expression
In section 2.2.2 there is an expression (cons (list 1 2) (list 3 4)). It is not the same as what you wrote in the question, (cons '(list 1 2) (list 3 4)). While an expression (list 1 2) applies the procedure list with values 1 and 2 and thus becomes (1 2), the expression '(list 1 2) just return the quoted data (list 1 2) unchanged.
Thus:
(cons (list 1 2) (list 3 4)) ; ==> ((1 2) 3 4)
(cons '(list 1 2) (list 3 4)) ; ==> ((list 1 2) 3 4)
'(cons '(list 1 2) (list 3 4)) ; ==> (cons '(list 1 2) (list 3 4))
The notation 'foo makes a symbol named foo.
The notation '(foo bar) makes a list with two symbols named foo and bar.
In the same way '(list foo bar) makes a list of three symbols. The symbol 'list happens to be called list.
Now (list 'foo 'bar) makes a list of two symbols called foo and bar.
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.
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
What am I missing here? I was playing with apply in Scheme, and wrote:
(apply apply '(+ (1 2 3)))
The way I understand it, the first apply should do:
(apply + '(1 2 3))
and the second should do:
(+ 1 2 3)
But both Ypsilon and Gauche give about the same error (this is Ypsilon's):
error: attempt call non-procedure: (+ 1 2 3)
backtrace:
0 (apply apply '(+ (1 2 3)))
..."/dev/stdin" line 1
What have I failed to understand?
The problem with '(+ (1 2 3)) is that the + is quoted and thus interpreted as a symbol.
You would have to use eval to get a value for the + symbol.
In other words, what you are trying to do, is not going to work.
Edit: Another option is quasiquote. Eg:
(apply apply `(,+ (1 2 3))) ; => 6
Or (without quasiquote)
(apply apply (list + '(1 2 3))); => 6