Programming language: Scheme/DrRacket
We're currently going over map, filter, and foldr in my comp sci class. I understand that all three can be used to create abstract functions, but I am honestly a little confused about the difference between the three and when I'd use each one.
Anyone care to explain what each is used for and how they are different? Unfortunately my book is not very clear.
The basic idea is that all three are ways of applying some function to all the elements of a list.
Map is perhaps the simplest--you just apply the function to each element of the list. This is basically the same as a for-each loop in other languages:
(map (lambda (x) (+ x 1)) '(1 2 3))
=> (2 3 4)
Basically, map is like this: (map f '(1 2 3)) is the same as (list (f 1) (f 2) (f 3)).
Filter is also simple: the function acts like an arbiter, deciding whether to keep each number. Imagine a really picky eater going through a menu and whining about the things he won't eat ;)
(filter (lambda (x) (equal? x 1)) '(1 2 3))
=> (1)
Fold is the hardest to understand, I think. A more intuitive name would be "accumulate". The idea is that you're "combining" the list as you go along. There are some functions in ever day use that are actually folds--sum is a perfect example.
(foldr + 0 '(1 2 3))
=> 6
You can think of the fold as taking the function and putting it between each element in the list: (foldr + 0 '(1 2 3)) is the same as 1 + 2 + 3 + 0.
Fold is special because, unlike the other two, it usually returns a scalar value--something that was the element of the list rather than the list itself. (This isn't always true, but think of it this way for now anyway.)
Note that I may not have gotten every detail of the code perfect--I've only ever used a different, older implementation of Scheme so I might have missed some Racket details.
I can recommend these finger exercises (and the text that comes before):
http://htdp.org/2003-09-26/Book/curriculum-Z-H-27.html#node_idx_1464
Related
Let's take the following function to get a pair of numbers:
; (range 1 3) --> '(1 2 3)
(define (range a b)
(if (> a b) nil
(cons a (range (+ 1 a) b))))
; generate pair of two numbers with 1 <= i < j <= N
(define (get-pairs n)
(map (lambda (i)
(map (lambda (j) (list i j))
(range 1 (- i 1))))
(range 1 n)))
(get-pairs 2)
; (() ((2 1)))
(get-pairs 3)
(() ((2 1)) ((3 1) (3 2)))
Why does the above produce '() as the first element of the output? Comparing this with python, I would expect it to just give the three pairs, something like:
>>> for i in range(1,3+1): # +1 because the range is n-1 in python
... for j in range(1,i-1+1):
... print (i,j)
...
(2, 1)
(3, 1)
(3, 2)
I suppose maybe it has to do with when i is 1?
(map (lambda (j) (list 1 j)) '())
; ()
Is that just an identity in Scheme that a map with an empty list is always an empty list?
When i is 1, the inner map is over (range 1 0), which is () by your own definition. Since map takes a procedure and a list (or lists) of values, applies the procedure to each value in the list in turn, and returns a list containing the results, mapping any procedure over a list containing no values will return a list containing no values.
It might help to create a simple definition for map to see how this might work. Note that this definition is not fully featured; it only takes a single list argument:
(define (my-map proc xs)
(if (null? xs)
'()
(cons (proc (car xs))
(my-map proc (cdr xs)))))
Here, when the input list is empty, there are no values to map over, so an empty list is returned. Otherwise the procedure proc is applied to the first value in the input list, and the result is consed onto the result of mapping over the rest of the list.
A couple of observations:
First, the empty list is not represented by nil in either standard Scheme or vanilla Racket, and you should not be using it. In the early days of Scheme nil was allowed as a crutch for programmers coming from other lisps, but this has not been the case for a long time. I don't think that it was ever in any of the RnRS standards, but nil may have survived in some specific implementations until maybe R4RS (1991). SICP was from that era. Today you should use '() to represent empty list literals in Scheme so that your code can run on any Scheme implementation. Racket's #lang sicp allows code directly from the book to be run, but that should not keep you from using the common notation. Note that Common Lisp does use nil as a self-evaluating symbol to represent both the empty list, and boolean false. Seeing this in Scheme just doesn't look right today.
Second, you will probably be led astray more often than to wisdom by thinking in terms of Python when trying to understand Scheme code. In this particular case, map is an iteration construct, but it is not the same thing as a for loop. A for loop is usually used for side-effects, but map is used to transform a list. Scheme has a for-each form which is meant to be used for its side-effects, and in that sense is more like a for loop. The Python version that is posted above is not at all like the Scheme version, though. Instead of returning the results in a list, the results are printed. In the Scheme code, when i is 1, the inner mapping is over (range 1 0) --> (). But, in the Python code, when i is 1, the inner loop is over range(1, 1), so the body of this for loop is not executed and nothing is printed.
Better to think carefully about the Scheme code you want to understand, falling back on basic definitions, than to cobble together a model based on Python that has possibly unconsidered corner cases.
Programming language: Scheme/DrRacket
I see no difference in usage between foldr and apply
Can anyone explain how they are different? As far as I can tell you can the same thing with foldr that you can with apply. Thank you!
They're very different, although in some cases they may be equivalent.
(apply func '(1 2 3))
is equivalent to
(func 1 2 3)
(foldr func 0 '(1 2 3))
is equivalent to
(func (func (func 3 0) 2) 1)
In cases where the function is associative and commutative, and it allows you to provide a variable number of arguments, the results will be the same. For example
(apply + '(1 2 3)) == (foldr + 0 '(1 2 3))
But foldr can be used to combine the results of functions that just take two arguments, or use more flexible ways to combine the results.
For more information about foldr, see Map, Filter, Foldr in DrRacket/Scheme
I'm currently doing an introductory course in Racket/Scheme, and am currently studying map, apply, and fold. For the most part, I've been assuming that map can only work on lambdas that accept a single argument. However, for certain problems I would find it incredibly useful to get around this somewhat - say, having a function that can be mapped to a list whilst also carrying an accumulator that updates independently for each recursive function call. While I can't get much more specific than that for fear of violating Honor Code, is there any way to get around being unable to give each recursive call an accumulator if you plan to use map?
map takes as many lists as you want:
(map + '(1 2 3) '(3 2 1) '(3 3 3)) ; ==> (7 7 7)
fold has an accumulator:
(foldl (lambda (a b c acc) (+ a b c acc)) 1 '(1 2 3) '(3 2 1) '(3 3 3)) ; ==> 22
I am learning Scheme and just came across Closures. The following example provided, demonstrating the use of Closures:
(define (create-closure x)
(lambda () x))
(define val (create-closure 10))
From what I understand, when the above code is evaluated, val will equal to 10. I realize this is just an example, but I don't understand just how a closure would be helpful. What are the advantages and what would a scenario where such a concept would be needed?
val is not 10 but a closure. If you call it like (val) it returns the value of x. x is a closure variable that still exists since it's still in use. A better example is this:
(define (larger-than-predicate n)
(lambda (v) (> v n )))
(filter (larger-than-predicate 5) '(1 2 3 4 5 6 7 8 9 10))
; ==> (6 7 8 9 10)
So the predicate compares the argument with v which is a variable that still holds 5. In a dynamic bound lisp this is not possible to do because n will not exist when the comparison happens.
Lecical scoping was introduces in Algol and Scheme. JavaScript, PHP amd C# are all algol dialects and have inherited it from there. Scheme was the first lisp to get it and Common Lisp followed. It's actually the most common scoping.
From this example you can see that the closure allows the functions local environment to remain accessible after being called.
(define count
(let ((next 0))
(lambda ()
(let ((v next))
(set! next (+ next 1))
v))))
(count)
(count)
(count)
0..1..2
I believe in the example you give, val will NOT equal to 10, instead, a lambda object (lambda () 10) will be assigned to val. So (val) equals to 10.
In the world of Scheme, there are two different concepts sharing the same term "closure". See this post for a brief introduction to both of these terms. In your case, I believe by "closure" you mean "lexical closure". In your code example, the parameter x is a free variable to the returned lambda and is referred to by that returned lambda, so a lexical closure is kept to store the value of x. I believe this post will give you a good explanation on what (lexical) closure is.
Totally agree with Lifu Huang's answer.
In addition, I'd like to highlight the most obvious use of closures, namely callbacks.
For instance, in JavaScript, I might write
function setup(){
var presses = 0;
function handleKeyPress(evt){
presses = presses + 1;
return mainHandler(evt);
}
installKeyHandler(handleKeyPress);
}
In this case, it's important to me that the function that I'm installing as the key handler "knows about" the binding for the presses variable. That binding is stored in the closure. Put differently, the function is "closed over" the binding for presses.
Similar things occur in nearly every http GET or POST call made in JS. It crops up in many many other places as well.
Btw, create-closure from your question is known by some as the Kestrel combinator, from the family of Combinator Birds. It is also known as True in Church encoding, which encodes booleans (and everything else) using lambdas (closures).
(define (kestrel a)
(lambda (b) a))
(define (create-list size proc)
(let loop ((x 0))
(if (= x size)
empty
(cons (proc x)
(loop (add1 x))))))
(create-list 5 identity)
; '(0 1 2 3 4)
(create-list 5 (kestrel 'a))
; '(a a a a a)
In Racket (I'm unsure about Scheme), this procedure is known as const -
(create-list 5 (const 'a))
; '(a a a a a)
I am building a function that takes a set of integers, and returns a subset of the odd integers. I am running into the problem that I need to skip over the even integers in my map, but right now my function returns #<void> instead.
(define (oddSubset set)
(map
(lambda (x)
(cond
((odd? x) x)))
s))
In use:
> (oddSubset '(1 2 3))
'(1 #<void> 3)
Is there logic I can use like "else, continue onto next element"?
Note: I am trying to rewrite the built in filter function
map does not have the possibility to skip, but you can use filter instead:
(filter odd? '(1 2 3 4 5 6)) ; ==> (1 3 5)
Or you can use fold-right
(fold-right (lambda (e acc)
(if (odd? e)
(cons e acc)
acc))
'()
'(1 2 3 4 5 6)) ; ==> (1 3 5)
I assume #!r6rs. Both fold-right and filter are in the library (rnrs lists (6)). There is also SRFI-1 which gives both of these procedures for a R5RS language.
In the none standard language #!racket uses the name foldr in place of fold-right.
map looks like a weird choice for this. By definition it maps a function onto each element in a list and returns the list of the results, so trying to "skip" elements seems unnatural.
filter is what you're looking for.
(filter odd? '(1 2 3))
'(1 3)
map applies a function on all elements. Each invocation of the function is supposed to be independant from the others. Even if you introduce a state with a closure, you can't avoid map to build a list of same size as your input.
You want to (re-)implement the filter function. If you want to do it by yourself, you should try to use foldl and foldr instead.
(cond
((odd? x) x))
map check each element in the list: if it is odd, then return that element. But you did not tell your program what to do when the element is not odd, so map return void.
To solve your problem: use filter instead, since map will return something for each element in the list.
If you want to know how to implement filter, try reading the second chapter of SICP