Applying apply in Scheme - scheme

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

Related

Is append the identity function for map?

In doing some tests I've noticed that append always gives me the same output as input when using map:
#lang sicp
(map append '(1 2 3 4 5))
(map (lambda (x) x) '(1 2 3 4 5))
; (1 2 3 4 5)
; (1 2 3 4 5)
(map append '((1 2)(3 4)))
(map (lambda (x) x) '((1 2)(3 4)))
; ((1 2) (3 4))
; ((1 2) (3 4))
That seems pretty neat/unexpected to me. Is this in fact the case? If so, how does the append work to give the identity property?
The append procedure takes zero or more list arguments, and a final argument that can be any object. When the final argument is a list, the result of appending is a proper list. When the final argument is not a list, but other list arguments have been provided, the result is an improper list. When only one argument is provided, it is just returned. This behavior with one argument is exactly the behavior of an identity procedure.
> (append '(1 2) '(3))
(1 2 3)
> (append '(1 2) 3)
(1 2 . 3)
> (append '(1 2))
(1 2)
> (append 3)
3
The call (map append '(1 2 3 4 5)) is equivalent to:
> (list (append 1)
(append 2)
(append 3)
(append 4)
(append 5))
(1 2 3 4 5)
Here, append is just acting as an identity procedure, as described above.

Adding Elements In a List Scheme

In Scheme, I am trying to iterate through a list adding each element from a portion of the list.
For example, if I had ((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()) for a list, I am trying to add the first part ( 1 2 5 ) and then the second part ( 1 2 ) and so on in order to see if each element adds up to a specific number.
Hope this makes sense, tried my best to explain this.
If someone could help me figure this problem out, I would really appreciate it.
To add the numbers of a (small) list you can use apply:
> (apply + '(1 2 3))
6
which is the same as
> (+ 1 2 3)
6
In order to apply this to a list of sublists, use map:
(define (f lst)
(map (lambda (sublst) (apply + sublst))
lst))
> (f '((1 2 5) (1 2) (1 5) (1) (2 5) (2) (5) ()))
'(8 3 6 1 7 2 5 0)
For larger list you might want to replace apply by foldl or equivalent.

in Scheme, is there syntactical sugar for an ordinary, unquoted list?

In Scheme, if I wanted a list, say (1 2 3), I would just write '(1 2 3). Usually, this is fine, but it is actually equivalent to (quote (1 2 3)), which is not exactly the same as (list 1 2 3). An example of when this would give different results:
'(1 2 (+ 0 3)) -> (1 2 (+ 0 3))
(list 1 2 (+ 0 3)) -> (1 2 3)
Is there a syntactical sugar for the second line here? For vectors there is. For example:
#(1 2 (+ 0 3)) -> #(1 2 3)
(vector 1 2 (+ 0 3)) -> #(1 2 3)
If there is no such sugar for list, that would be pretty ironic, because lists are used way more often than vectors in Scheme!
If you need to evaluate a part of the list, you can use quasiquoting and unquoting, like this:
`(1 2 ,(+ 0 3))
=> '(1 2 3)

What does '(list 1 2) means in Scheme?

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.

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.

Resources