for-each doesn't output values - scheme

I understand that for-each in scheme doesn't create a new list but in my output, I expected:
4
9
16
done.
I'm just getting "done".
What's going on here?
(define (for-each proc list)
(cond ((null? list) "done")
(else
(proc (car list))
(for-each proc (cdr list)))))
(define square (lambda(x)(* x x)))
(square 5)
(for-each square (list 2 3 4))

In your code, the line (proc (car list)) gets executed for the effect, but its result will be ignored. If you just want to print the results of the square function, try this:
(for-each (lambda (x) (display (square x)) (newline)) ; applies function on each element
'(2 3 4))
=> 4
9
16
done
If you want to obtain the results of applying the procedure on each element of the input list, you have to use map, not for-each:
(map square '(2 3 4))
=> '(4 9 16)
for-each iterates over an input list and performs an operation over each element, but only for its effect (say, printing each element). It doesn't accumulate the result in an output list, it doesn't even print them unless explicitly stated - on the other hand, map iterates over an input list, performs an operation over each element and accumulates the result in an output list.

Related

Improving an iterative function in scheme

I often struggle writing iterative functions in scheme: it makes writing recursive procedures much simpler. Here is an example of trying to square items in a list using an iterative procedure:
(define square (lambda (x) (* x x)))
(define (square-list items)
(define result nil) ; set result
(define (iter items-remaining)
(if (null? items-remaining)
result
(set! result (cons (car items-remaining) (iter (cdr items-remaining))))))
(iter items))
(square-list '(1 2 3 4 5))
; (4 9 16 25)
My main question about this is:
Is there a way to do this procedure without having to first define the result before the inner procedure? I was trying to make the iterative procedure have the function prototype of define (iter items-remaining answer) but was having a hard time implementing it that way.
And if not, why isn't that possible?
The posted code does not work; but even when fixed up so that it does work, this would not be an idiomatic Scheme solution.
To make the posted code work:
nil must be replaced with '(), since Scheme does not represent the empty list with nil
square must be called on the car of items-remaining
set! should modify result by adding squared numbers to it, not by trying to add the result of a recursive call. This won't work at all here because set! returns unspecified values; but even if it did work, this would not be tail-recursive (i.e., this would not be an iterative process)
The value of result must be returned, and it will have to be reversed first since result is really an accumulator
Here is a fixed-up version:
(define (square-list-0 items)
(define result '()) ; set result
(define (iter items-remaining)
(cond ((null? items-remaining)
result)
(else
(set! result (cons (square (car items-remaining))
result))
(iter (cdr items-remaining)))))
(iter items)
(reverse result))
A better solution would not use mutation, and would not need (define result '()):
(define (square-list-1 xs)
(define (iter xs acc)
(if (null? xs)
(reverse acc)
(iter (cdr xs) (cons (square (car xs)) acc))))
(iter xs '()))
Here an accumulator, acc, is added to the lambda list for the iter procedure. As results are calculated, they are consed onto acc, which means that at the end of this process the first number in acc is based on the last number in xs. So, the accumulator is reversed before it is returned.
Another way to do this, and probably a more idiomatic solution, is to use a named let:
(define (square-list-2 xs)
(let iter ((xs xs)
(acc '()))
(if (null? xs)
(reverse acc)
(iter (cdr xs) (cons (square (car xs)) acc)))))
This is a bit more concise, and it lets you bind arguments to their parameters right at the beginning of the definition of the iter procedure.
All three of the above solutions define iterative processes, and all three give the same results:
> (square-list-0 '(1 2 3 4 5))
(1 4 9 16 25)
> (square-list-1 '(1 2 3 4 5))
(1 4 9 16 25)
> (square-list-2 '(1 2 3 4 5))
(1 4 9 16 25)
Of course, you could just use map:
> (map square '(1 2 3 4 5))
(1 4 9 16 25)

How to define my own version of filter procedure in racket?

I am new in Racket and I was assigned to do my own filter procedure. It should work similar to the Racket filter procedure. Currently, my-filter has two arguments: the even procedure to check the items in the list, and a list of items.
So far, I have been only able to check whether the items in the list are even or not. my-filter is supposed to iterate through a list of numbers, retrieve the numbers that are even and save them in a second list. How can I iterate through the list and store the even numbers in the second list?
(define (my-filter f lst)
(if (empty? lst)
empty
(cons
(f (first lst))
(my-filter f (rest lst)))))
> (my-filter even? '(1 2 3 4 5 6))
'(#f #t #f #t #f #t)
There are three cases that you need to consider:
Input list is empty -> we're done.
Current element satisfies the predicate function -> add it to the output and continue with next element.
Current element doesn't satisfy the predicate function -> skip it and continue with next element.
You're mixing the last two cases into a single case. And notice that you must not add (f (first lst)) to the output, that's just the condition that we want to evaluate, we should add (first lst) instead. This is what I mean:
(define (my-filter f lst)
(cond ((empty? lst) empty)
((f (first lst))
(cons (first lst) (my-filter f (rest lst))))
(else (my-filter f (rest lst)))))
It works as expected:
(my-filter even? '(1 2 3 4 5 6))
=> '(2 4 6)

multiplying list of items by a certain number 'x'

How would you write a procedure that multiplies each element of the list with a given number (x).If I give a list '(1 2 3) and x=3, the procedure should return (3 6 9)
My try:
(define (mul-list list x)
(if (null? list)
1
(list(* x (car list))(mul-list (cdr list)))))
The above code doesnt seem to work.What changes do I have to make ? Please help
Thanks in advance.
This is the text book example where you should use map, instead of reinventing the wheel:
(define (mul-list lst x)
(map (lambda (n) (* x n)) lst))
But I guess that you want to implement it from scratch. Your code has the following problems:
You should not call list a parameter, that clashes with the built-in procedure of the same name - one that you're currently trying to use!
The base case should return an empty list, given that we're building a list as output
We build lists by consing elements, not by calling list
You forgot to pass the second parameter to the recursive call of mul-list
This should fix all the bugs:
(define (mul-list lst x)
(if (null? lst)
'()
(cons (* x (car lst))
(mul-list (cdr lst) x))))
Either way, it works as expected:
(mul-list '(1 2 3) 3)
=> '(3 6 9)
For and its extensions (for*, for/list, for/first, for/last, for/sum, for/product, for/and, for/or etc: https://docs.racket-lang.org/reference/for.html) are very useful for loops in Racket:
(define (ml2 lst x)
(for/list ((item lst))
(* item x)))
Testing:
(ml2 '(1 2 3) 3)
Output:
'(3 6 9)
I find that in many cases, 'for' implementation provides short, simple and easily understandable code.

Scheme operation on a function

Is it possible to do an operation on a previous function, i have a list of values say (1,2,3,4,5), first function needs to multiply them by 2, while 2nd function adds 1 to result of previous function, so first we would get (2,4,6,8,10), and then (3,5,7,9,11) i got this, function g does extra work, is it possible nstead of doing operations on the element do it on function F or results from function F
#lang racket
(define test (list 1 1 2 3 5))
(define (F)
(map (lambda (element) (* 2 element))
test))
(define (G)
(map (lambda (element) (+ 1 (* 2 element)))
test))
First you need to correctly define your procedures to take a list parameter (called lst in this case):
(define (F lst)
(map (lambda (e) (* 2 e)) lst))
(define (G lst)
(map add1 lst))
Then
> (F '(1 2 3 4 5))
'(2 4 6 8 10)
> (G '(2 4 6 8 10))
'(3 5 7 9 11)
or, if you need to combine both procedures:
> (G (F '(1 2 3 4 5)))
'(3 5 7 9 11)
This is a follow-up to your previous question. As stated in my answer there, you should pass the right parameters to the functions - in particular, pass the input lists as parameter, so you can use the result from one function as input for the next function:
(define test (list 1 1 2 3 5))
(define (multiply-list test)
(map (lambda (element) (* 2 element))
test))
(define (add-list test)
(map (lambda (element) (+ 1 element))
test))
Now, if we want to add one to each element in the input list:
(add-list test)
=> '(3 3 5 7 11)
Or if we want to multiply by two each element in the input list:
(multiply-list test)
=> '(2 2 4 6 10)
And if we want to add one first, then multiply by two we can chain the functions! the result from one becomes the input for the other, and the final result will be as follows:
(multiply-list (add-list test))
=> '(6 6 10 14 22)
NB! You have tagged scheme but you use racket (the language). Not all of my examples will work in scheme.
Yes! you even do it yourself in your definition of G where you add a value and the result of a multiplication.
Its possible to chain map
(map f3 (map f2 (map f1 lst)))
Thus if you instead make a function that takes a list and doubles it:
(define (list-double lst)
(map (lambda (x) (* x 2)) lst))
You can chain it to quadruple it:
(define (list-quadruple lst)
(list-double (list-double lst)))
Now it's not optimal to chain map if you can avoid it. Instead you can compose the procedures together:
(define (double x) (* x 2))
(define (list-quadrouple lst)
(map (compose1 double double) lst))
compose1 here is the same as making a anonymous function where you chain the arguments. Eg. the last would be (lambda (x) (double (double x))). A more complex one compose can do more than one value between procedures. eg. (compose + quotient/remainder)

List of lengths from list of strings using map, filter, or fold-right

You are given a list of strings.
Generate a procedure such that applying this procedure to such a list
would result in a list of the lengths of each of the strings in the
input.
Use map, filter, or fold-right.
(lengths (list "This" "is" "not" "fun")) => (4 2 3 3)
(define lengths (lambda (lst) your_code_here))
I got stuck in the following code and I do not understand how can I use filter.
(define lengths
(lambda (lst)
(if (null? lst)
nil
(fold-right list (string-length (car lst)) (cdr lst)))))
This seems like a work for map, you just have to pass the right procedure as a parameter:
(define (lengths lst)
(map string-length lst))
As you should know, map applies a procedure to each of the elements in the input list, returning a new list collecting the results. If we're interested in building a list with the lengths of strings, then we call string-length on each element. The procedure pretty much writes itself!
A word of advice: read the documentation of the procedures you're being asked to use, the code you're writing is overly complicated. This was clearly not a job for filter, although fold-right could have been used, too. Just remember: let the higher-order procedure take care of the iteration, you don't have to do it explicitly:
(define (lengths lst)
(fold-right (lambda (x a)
(cons (string-length x) a))
'()
lst))
This looks like homework so I'll only give you pointers:
map takes a procedure and applies to to every element of a list. Thus
(define (is-strings lst)
(map string? lst))
(is-strings '("hello" 5 sym "89")) ; (#t #f #f #t)
(define (add-two lst)
(map (lambda (x) (+ x 2)) lst))
(add-two '(3 4 5 6)) ; ==> (5 6 7 8)
filter takes procedure that acts as a predicate. If #f the element is omitted, else the element is in the resulting list.
(define (filter-strings lst)
(filter string? lst))
(filter-strings '(3 5 "hey" test "you")) ; ==> ("hey" "you")
fold-right takes an initial value and a procedure that takes an accumulated value and a element and supposed to generate a new value:
(fold-right + 0 '(3 4 5 6)) ; ==> 18, since its (+ 3 (+ 4 (+ 5 (+ 6 0))))
(fold-right cons '() '(a b c d)) ; ==> (a b c d) since its (cons a (cons b (cons c (cons d '()))))
(fold-right - 0 '(1 2 3)) ; ==> -2 since its (- 1 (- 2 (- 3 0)))
(fold-right (lambda (e1 acc) (if (<= acc e1) acc e1)) +Inf.0 '(7 6 2 3)) ; ==> 2
fold-right has a left handed brother that is iterative and faster, though for list processing it would reverse the order after processing..
(fold-left (lambda (acc e1) (cons e1 acc)) '() '(1 2 3 4)) ; ==> (4 3 2 1)

Resources