How to use foldr in scheme? - scheme

When you use foldr, the procedure you use has 2 arguments, the current value of the list and the accumulator. Let's say the list you iterate over is a list of list of numbers, all the same length. Then as you iterate through them, you want to multiply the numbers of the same index and store it as the accumulator.
If you use lambda (x acc) (map * x acc) inside the foldr, this fails because acc I believe is an empty list in the beginning. How can you handle the base case like this?

This can be solved using foldr all right, the trick is to correctly initialize the accumulated value at the beginning. No need to do fancy stuff (like macros) here!
(define lst '((1 2 3) (2 3 5) (3 5 7)))
(foldr (lambda (x acc) (map * x acc))
(car lst)
(cdr lst))
=> '(6 30 105)
Of course, if the list is empty (car lst) will fail. So you might want to handle the empty list as a separate case before invoking foldr.

Say you have a list of lists as follows:
((1 2 3) (2 3 5) (3 5 7))
You want to reduce it to:
(6 30 105)
I would simple do:
(define-syntax mul
(syntax-rules ()
((_ (lists ...)) (map * 'lists ...))))
The you can use it as follows:
(mul ((1 2 3) (2 3 5) (3 5 7))) ; => (6 30 105)
The above code simply expands to:
(map * '(1 2 3) '(2 3 5) '(3 5 7))
Then you can fold the resulting list. For example:
(foldr + 0 (mul ((1 2 3) (2 3 5) (3 5 7)))) ; => 141

Related

just started learning Scheme

I don't know why this does not work. I get an error saying "Error: 1 is not a function[(anon)]"
(define (mem lst ele)
(cond ;if the list is empty return false
((null? lst) #f)
;if the first element is equal to the given element return true
;otherwise call the function with rest of the list
(else (if (= ele (car lst))
#t
(mem (cdr lst) ele)))))
(mem ’(1) ’(1 4 -2))
It works for me; how are you calling mem? I am guessing that you did something like: (mem (1 2 3 4) 1). Procedure calls always evaluate their arguments in Scheme, so in the procedure call (mem (1 2 3 4) 1) the expression (1 2 3 4) is evaluated; but lists are evaluated as if the first member is a procedure, so 1 is treated as a function; it is not, and this raises an exception.
You could quote the list: (mem (quote (1 2 3 4)) 1), or you can use the shorthand (mem '(1 2 3 4) 1). quote is a special form that does not evaluate its argument; instead it just returns whatever datum it is given. You can try this out at the REPL:
> (+ 1 2)
3
> (quote (+ 1 2))
(+ 1 2)
> '(+ 1 2)
(+ 1 2)
Here the naked expression (+ 1 2) evaluates to 3, but the quoted expressions just return the expressions given to quote. That is, (quote (+ 1 2)) evaluates to the expression (+ 1 2), not to the result of evaluating the expression (+ 1 2). In the case of (1 2 3 4):
> (quote (1 2 3 4))
(1 2 3 4)
> '(1 2 3 4)
(1 2 3 4)
> (1 2 3 4)
Exception: attempt to apply non-procedure 1
Type (debug) to enter the debugger.
The procedure call (mem '(1 2 3 4) 1) would evaluate the expression '(1 2 3 4) before passing that value to mem. Since the expression '(1 2 3 4) evaluates to a list, that list is the value which is passed to mem. This differs from the erroneous call (mem (1 2 3 4) 1), which attempts to evaluate the expression (1 2 3 4) by calling the (nonexistent) procedure 1 with the arguments 2, 3, and 4.
You could also use list to create the input: (mem (list 1 2 3 4) 1). list is also a procedure, and so it evaluates its arguments. Here the call to mem would evaluate the expression (list 1 2 3 4), and since list is a procedure the call to list would evaluate the arguments 1, 2, 3, and 4. Numbers are self-evaluating in Scheme, so the call to list would return a list (1 2 3 4); this list is the value passed to mem, which has now evaluated its argument (list 1 2 3 4).
Some Comments on the Posted Code
The cond form can take multiple conditional clauses, and there is no reason to use if here. Instead, you can do:
(define (mem lst ele)
(cond
((null? lst) #f)
((= ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
The = predicate only works for numbers; to handle more general inputs you might choose equal?:
(define (mem lst ele)
(cond
((null? lst) #f)
((equal? ele (car lst)) #t)
(else
(mem (cdr lst) ele))))
Now you can work with, e.g., lists of symbols, or lists of lists:
> (mem '(a b c d) 'c)
#t
> (mem '(a b c d) 'e)
#f
> (mem '(1 (2 3) 4) '(2 3))
#t
> (mem '(1 (2 (3 4)) 5) '(2 (3 4)))
#t
> (mem '(1 (2 3) 4) 3) ;; does not descend into nested lists
#f
Note that changing the equality predicate to equal? will allow lists to be searched for at the top level of the input list, but no deeper. The list (2 (3 4)) can be found in the list (1 (2 (3 4)) 5) because it is at the top level of the list, i.e., (2 (3 4)) is an element of the list (1 (2 (3 4)) 5). But, (3 4) is not an element of the top level list, so the current mem procedure can't find it here. Another definition for mem would be needed to search within nested lists.
It seems from your example that you are looking for the list '(1 4 -2) in the list '(1), which should evaluate to #f. However your implementation expects all elements to be numbers since you compare with = which is a number only comparison procedure. If you want to compare any type you should use equal? which compares two objects of any type and supports comparing structures.
You were using an acute-accent instead of a single-quote for your literals.
#lang racket
(define (mem ele lst) ;; easier to read with one element -then- list
;; ..plus that's how you wrote your call to it,
;; so this arg-order makes more sense here.
(cond ;; cond doesn't need "else"
((null? lst) #f)
((if (= ele (car lst)) #t
(mem ele (cdr lst)))) ;; element, then list now
)
)
(mem 1 '(1 4 -2))
;; don't know why element needed to be wrapped in a '(1) literal list container
;; also literals require single-quote ' character, not the ’ acute-accent
https://docs.racket-lang.org/racket-cheat/index.html

The apply function in SICP/Scheme

I've asked a few questions here about Scheme/SICP, and quite frequently the answers involve using the apply procedure, which I haven't seen in SICP, and in the book's Index, it only lists it one time, and it turns out to be a footnote.
Some examples of usage are basically every answer to this question: Going from Curry-0, 1, 2, to ...n.
I am interested in how apply works, and I wonder if some examples are available. How could the apply procedure be re-written into another function, such as rewriting map like this?
#lang sicp
(define (map func sequence)
(if (null? sequence) nil
(cons (func (car sequence)) (map func (cdr sequence)))))
It seems maybe it just does a function call with the first argument? Something like:
(apply list '(1 2 3 4 5)) ; --> (list 1 2 3 4 5)
(apply + '(1 2 3)) ; --> (+ 1 2 3)
So maybe something similar to this in Python?
>>> args=[1,2,3]
>>> func='max'
>>> getattr(__builtins__, func)(*args)
3
apply is used when you want to call a function with a dynamic number of arguments.
Your map function only allows you to call functions that take exactly one argument. You can use apply to map functions with different numbers of arguments, using a variable number of lists.
(define (map func . sequences)
(if (null? (car sequences))
'()
(cons (apply func (map car sequences))
(apply map func (map cdr sequences)))))
(map + '(1 2 3) '(4 5 6))
;; Output: (5 7 9)
You asked to see how apply could be coded, not how it can be used.
It can be coded as
#lang sicp
; (define (appl f xs) ; #lang racket
; (eval
; (cons f (map (lambda (x) (list 'quote x)) xs))))
(define (appl f xs) ; #lang r5rs, sicp
(eval
(cons f (map (lambda (x) (list 'quote x))
xs))
(null-environment 5)))
Trying it out in Racket under #lang sicp:
> (display (appl list '(1 2 3 4 5)))
(1 2 3 4 5)
> (display ( list 1 2 3 4 5 ))
(1 2 3 4 5)
> (appl + (list (+ 1 2) 3))
6
> ( + (+ 1 2) 3 )
6
> (display (appl map (cons list '((1 2 3) (10 20 30)))))
((1 10) (2 20) (3 30))
> (display ( map list '(1 2 3) '(10 20 30) ))
((1 10) (2 20) (3 30))
Here's the link to the docs about eval.
It requires an environment as the second argument, so we supply it with (null-environment 5) which just returns an empty environment, it looks like it. We don't actually need any environment here, as the evaluation of the arguments has already been done at that point.

Pair combinations in scheme

I'm trying to find the various combinations that can be made with a list of N pairs in scheme. Here is where I'm at thus far:
(define (pair-combinations list-of-pairs)
(if (null? list-of-pairs)
nil
(let ((first (caar list-of-pairs))
(second (cadar list-of-pairs))
(rest (pair-combinations (cdr list-of-pairs))))
(append
(list (cons first rest))
(list (cons second rest))
))))
Now, I'm not sure if the logic is correct, but what I notice immediately is the telescoping of parentheticals. For example:
(define p1 '( (1 2) (3 4) (5 6) ))
(pair-combinations p1)
((1 (3 (5) (6)) (4 (5) (6))) (2 (3 (5) (6)) (4 (5) (6))))
Obviously this is from the repetition of the list (... within the append calls, so the result looks something like (list 1 (list 2 (list 3 .... Is there a way to do something like the above in a single function? If so, where am I going wrong, and how would it be properly done?
The answer that I'm looking to get would be:
((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
That is, the possible ways to choose one element from N pairs.
Here is one way to think about this problem. If the input is the empty list, then the result is (). If the input is a list containing a single list, then the result is just the result of mapping list over that list, i.e., (combinations '((1 2 3))) --> ((1) (2) (3)).
Otherwise the result can be formed by taking the first list in the input, and prepending each item from that list to all of the combinations found for the rest of the lists in the input. That is, (combinations '((1 2) (3 4))) can be found by prepending each element of (1 2) to each of the combinations in (combinations '((3 4))), which are ((3) (4)).
It seems natural to express this in two procedures. First, a combinations procedure:
(define (combinations xss)
(cond ((null? xss) '())
((null? (cdr xss))
(map list (car xss)))
(else
(prepend-each (car xss)
(combinations (cdr xss))))))
Now a prepend-each procedure is needed:
(define (prepend-each xs yss)
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs)))
Here the procedure prepend-each takes a list xs and a list of lists yss and returns the result of prepending each x in xs to the lists in yss. The inner map takes each list ys in yss and conses an x from xs onto it. Since the inner mapping produces a list of lists, and the outer mapping then produces a list of lists of lists, append is used to join the results before returning.
combinations.rkt> (combinations '((1 2) (3 4) (5 6)))
'((1 3 5) (1 3 6) (1 4 5) (1 4 6) (2 3 5) (2 3 6) (2 4 5) (2 4 6))
Now that a working approach has been found, this could be converted into a single procedure:
(define (combinations-2 xss)
(cond ((null? xss) '())
((null? (cdr xss))
(map list (car xss)))
(else
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
(combinations-2 (cdr xss))))
(car xss))))))
But, I would not do that since the first version in two procedures seems more clear.
It might be helpful to look just at the results of prepend-each with and without using append:
combinations.rkt> (prepend-each '(1 2) '((3 4) (5 6)))
'((1 3 4) (1 5 6) (2 3 4) (2 5 6))
Without using append:
(define (prepend-each-no-append xs yss)
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs))
combinations.rkt> (prepend-each-no-append '(1 2) '((3 4) (5 6)))
'(((1 3 4) (1 5 6)) ((2 3 4) (2 5 6)))
It can be seen that 1 is prepended to each list in ((3 4) (5 6)) to create a list of lists, and then 2 is prepended to each list in ((3 4) (5 6)) to create a list of lists. These results are contained in another list, since the 1 and 2 come from the outer mapping over (1 2). This is why append is used to join the results.
Some Final Refinements
Note that prepend-each returns an empty list when yss is empty, but that a list containing the elements of xs distributed among as many lists is returned when yss contains a single empty list:
combinations.rkt> (prepend-each '(1 2 3) '(()))
'((1) (2) (3))
This is the same result that we want when the input to combinations contains a single list. We can modify combinations to have a single base case: when the input is '(), then the result is (()). This will allow prepend-each to do the work previously done by (map list (car xss)), making combinations a bit more concise; the prepend-each procedure is unchanged, but I include it below for completeness anyway:
(define (combinations xss)
(if (null? xss) '(())
(prepend-each (car xss)
(combinations (cdr xss)))))
(define (prepend-each xs yss)
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
yss))
xs)))
Having made combinations more concise, I might be tempted to go ahead and write this as one procedure, after all:
(define (combinations xss)
(if (null? xss) '(())
(apply append
(map (lambda (x)
(map (lambda (ys)
(cons x ys))
(combinations (cdr xss))))
(car xss)))))

Scheme - Adding a list to a list of lists?

I am trying to answer a scheme question, for a part of this question I have to make a list of lists:
(define (join a b (result '()))
(cons (list a b) result))
So I am taking in two characters, and placing them in a list, then I need to place each sublist into a list of lists, this function is being called recursively with two characters each time, so it is supposed to work like this:
join 1 4
=> ((1 4))
join 2 5
=> ((1 4) (2 5))
join 3 6
=> ((1 4) (2 5) (3 6))
However, I am getting ((3 6) (2 5) (1 4)), so the elements need to be reversed, I tried reversing my cons function to (cons result (list a b)) but then I get (((() 1 4) 2 5) 3 6), how can I get the list the right way around, or is there an easier way to do what I'm doing?
If you need to add elements at the end of a list use append; cons is for adding elements at the head. Try this:
(define (join a b (result '()))
(append result (list (list a b))))
Notice that append combines two lists, that's why we have to surround the new element inside its own list. Also, it's not a good idea to add elements at the end, using append is more expensive than using cons - if possible, rethink your algorithm to add elements at the head, and reverse the result at the end.
This can easily be done like this:
(define (group-by-2 lst)
(let loop ((lst lst) (rlst '()))
(if (or (null? lst) (null? (cdr lst)))
(rcons->cons rlst)
(loop (cdr lst)
(rcons (list (car lst)
(cadr lst))
rlst)))))
(group-by-2 '(1 2 3 4 5 6 7 8))
; ==> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8))
Now rcons is like cons but it makes a reverse list. (rcons 1 (rcons 2 (rcons 3))) ; ==> {3 2 1} however it is not a list so you have to convert it to a list (rcons->list (rcons 1 (rcons 2 (rcons 3))) ; ==> (3 2 1)
The magic functions are really not that magical:
(define rcons cons)
(define rcons->cons reverse)
So in fact I didn't really have to make that abstraction, but hopefully I made my point. It doesn't matter how you organize the intermediate data structure in your programs so why not make the best for the job you are doing. For lists it's always best to iterate from beginning to end and make from end to beginning. Every insert O(1) per element and you do a O(n) reverse in the end. It beats doing append n times that would make it O(n²)

List length comparison

I wanted to write the code for comparing the size of two lists. I made use of the length and wrote this down.
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (length mtrx1) (length mtrx2))).
I thought this was going to work for me, but I found out it only checks the overall length, not the sublist. For example it returns true when it compares for. '((1 2 3 4) (4 5 6 6) (6 7 8 9)) and '(( 5 4) (3 2) (7 1)), but it's supposed to return false, because the first has 4 values within the list and the second has only two even though they both overally have same length. How do I go about this. Any help would be appreciated.
Try this instead:
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (map length mtrx1) (map length mtrx2)))
Notice that in your solution you're comparing the total length of each list (the number of rows in the matrix), but ignoring the length of each sublist (the number of columns for each row in the matrix). In my soultion, first we calculate the length of each sublist and after that we check if all the lengths are equal. For example, take this input:
(define mtrx1 '((1 2 3 4) (4 5 6 6) (6 7 8 9)))
(define mtrx2 '((5 4) (3 2) (7 1)))
(same-size-matrix? mtrx1 mtrx2)
First the same-size-matrix? evaluates this expression, which finds the length of each sublist in mtrx1. It's necessary to check all the lengths, not just the first one, in case we're dealing with a jagged array:
(map length mtrx1)
; evaluates to '(4 4 4)
And then we have this expression, which performs the same operation for mtrx2:
(map length mtrx2)
; evaluates to '(2 2 2)
Finally, we compare the two lists of lengths (in fact: the number of columns per row), returning the expected result:
(equal? '(4 4 4) '(2 2 2))
> #f
Notice that the last comparison will also detect if the lists are of different size, in case the matrices have a different number of rows.
is it scheme?
(define m1 `((1 2 3 4) (4 5 6 6 ) (6 7 8 9)))
(define m2 `((5 4) (3 2) (7 1)))
(define (same-size-matrix? m1 m2) (equal? (map length m1) (map length m2)))
(same-size-matrix? m1 m2) ; => #f
(same-size-matrix? m1 m1) ; => #t
Here is a simple definition of same-size?.
#lang racket
; A MATRIX is a list of ROWs.
; A ROW is a list of numbers.
; In a matrix all rows are of the same length.
(define (row-size list-of-rows)
(length list-of-rows))
(define (column-size matrix)
(define first-row (first matrix))
(length first-row))
(define (same-size? matrix1 matrix2)
(and (= (row-size matrix1) (row-size matrix2))
(= (column-size matrix1) (column-size matrix2))))
As a bonus here is a predicate that test whether an object
is a matrix or not. Compare it to the data definitions.
(define (row? object)
(and (list? object)
(andmap number? object)))
(define (matrix? object)
(and (list? object)
(andmap row? object)
(apply = (map row-size object))))
You need to clarify if you want to check 1) the exact shape of the matrix or 2) the overall 'flattened' length.
what should be the result for (same-size-matrix? '((1 2) (3 4) (5 6)) '((1 2 3) (4 5 6)))?
1) => #f
2) => #t
Óscar López's answer is for 1.
If your requirement is 2, based on Óscar's answer:
(define (same-size-matrix? mtrx1 mtrx2)
(equal? (apply + (map length mtrx1)) (apply + (map length mtrx2))))

Resources