How to invert the predicate here? - scheme

I have the following filter procedure:
; (2) filter
(define (filter test sequence)
; return a list of the elements that pass the predicate test
(let ((elem (if (null? sequence) nil (car sequence)))
(rest (if (null? sequence) nil (cdr sequence))))
(cond ((null? sequence) nil)
((test elem) (cons elem (filter test rest)))
(else (filter test rest)))))
And here would be an example of using it to return the even-numbered elements of a list:
(define even? (lambda (x) (= (modulo x 2) 0)))
(define sequence '(1 2 3 4 5 8 9 11 13 14 15 16 17))
(filter even? sequence)
; (2 4 8 14 16)
Is there a simple way to use the not test to invert the selection? For example, I thought the following might work:
(filter (not even?) sequence)
But it returns an error. I can define odd separately, of course:
(define odd? (lambda (x) (not (even? x))))
But I'm trying not to do this. Is there a way to write the odd procedure without defining it directly, but instead using the not directly like I'm trying to do above?

There is a complement function in Common Lisp that does what I think you are looking for. complement is a higher-order procedure that takes a procedure as its argument, and returns a procedure that takes the same arguments as the input procedure and performs the same actions, but the returned truth value is inverted.
Racket has a similar procedure, negate, and it is easy enough to implement this in Scheme:
(define (complement f)
(lambda xs (not (apply f xs))))
> (filter even? '(1 2 3 4 5))
(2 4)
> (filter (complement even?) '(1 2 3 4 5))
(1 3 5)
> (> 1 2 3 4 5)
#f
> ((complement >) 1 2 3 4 5)
#t
And in Racket:
scratch.rkt> (filter even? '(1 2 3 4 5))
'(2 4)
scratch.rkt> (filter (negate even?) '(1 2 3 4 5))
'(1 3 5)
scratch.rkt> (> 1 2 3 4 5)
#f
scratch.rkt> ((negate >) 1 2 3 4 5)
#t

The general answer to this is to simply compose not and the function you care about. Racket has a compose function which does this, but you can easily write a simple one yourself:
(define (compose-1 . functions)
;; simple-minded compose: each function other than the last must
;; take just one argument; all functions should return just one
;; value.
(define (compose-loop fns)
(cond
((null? fns)
(λ (x) x))
((null? (cdr fns))
(car fns))
(else
(λ (x) ((car fns) ((compose-loop (cdr fns)) x))))))
(compose-loop functions))
Making it efficient and more general takes more work of course.
Then you can define odd? (which is already defined of course):
(define odd? (compose-1 not even)
Or in fact define a more general CL-style complement function:
(define (complement f)
(compose-1 not f))

One option is to write an invert function which will curry things along (so the initial function still accepts one argument) until the final evaluation occurs:
(define invert (lambda (func) (lambda (x) (not (func x)))))
(define sequence '(1 2 3 4 5 6 8 9 11 13 14 15 16 17))
(filter (invert even?) sequence)
; (1 3 5 9 11 13 15 17)

Related

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.

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)

Printing Numbers in Scheme

Im trying to do the following in the list below: Let say list one consists of (1234) and list 2 is (5678) I am trying to print it in the following way (15263748) This is what I have for now but I am not sure where to go after this. Of course right now the code below prints it like 12 34 it should be 1 3 2 4
(define (arrange-list lst1 lst2)
(append lst1 lst2))
(arrange-list '(12) '(34))
This is a common procedure, usually known as interleave. Assuming that the input lists have the same length, we can write the following implementation from scratch, using explicit recursion:
(define (interleave lst1 lst2)
(if (null? lst1)
'()
(cons (car lst1)
(interleave lst2 (cdr lst1)))))
The trick is taking one element from one list, and then from the other until both lists are exhausted. A more idiomatic solution in Racket would be to use built-in procedures, like this:
(define (interleave lst1 lst2)
(flatten (map cons lst1 lst2)))
Either way it works as expected:
(interleave '(1 2 3 4) '(5 6 7 8))
=> '(1 5 2 6 3 7 4 8)
If the lists aren't of equal length, this is my solution which works albeit is not as elegant as the one mentioned in the other answer.
Basically, we maintain a variable x while recursively calling the procedure that indicates which list needs processing currently. The first list is indicated by 1 and the second, 2.
(define (print-alt A B x)(cond
((and (null? A) (null? B)) '())
((= 1 x) (cond
((null? A) (print-alt A B 2))
(else (append (list (car A)) (print-alt (cdr A) B 2)))))
(else (cond
((null? B) (print-alt A B 1))
(else (append (list (car B)) (print-alt A (cdr B) 1)))))))
Here is the output:
(print-alt (list 1 2 3 4 5 6) (list 5 6 7 8 9 10 11 12 123) 1)
(1 5 2 6 3 7 4 8 5 9 6 10 11 12 123)

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)

Scheme problem (using a function as a parameter)

I'm a Scheme newbie and trying to make sense of my homework.
I've a function I made earlier called duplicate, and it looks like this:
( DEFINE ( duplicate lis )
(IF (NULL? lis) '())
((CONS (CAR lis) (CONS (CAR lis) (duplicate (CDR lis))))
))
A typical i/o from this would be i: (duplicate '(1 2 3 4)) o: (1 1 2 2 3 3 4 4), so basicly it duplicates everything in the list.
Moving on:
Now I'm supposed to make a function that's called comp.
It's supposed to be built like this:
(DEFINE (comp f g) (lambda (x) (f (g (x))))
Where I could input '(1 2 3 4) and it would return (1 1 4 4 9 9 16 16)
so f = duplicate and g = lambda.
I know lambda should probably look like this:
(lambda (x) (* x x))
But here's where the problem starts, I've already spent several hours on this, and as you can see not made much progress.
Any help would be appreciated.
Best regards.
Use map:
> (map (lambda (x) (* x x)) (duplicate '(1 2 3 4)))
=> (1 1 4 4 9 9 16 16)
or, modify duplicate to take a procedure as its second argument and apply it to each element of the list:
(define (duplicate lst p)
(if (null? lst) ()
(append (list (p (car lst)) (p (car lst))) (duplicate (cdr lst) p))))
> (duplicate '(1 2 3 4) (lambda (x) (* x x)))
=> (1 1 4 4 9 9 16 16)
One way to do is as follows:
(define (comp f g) (lambda (x) (f (g x))))
(define (square x) (* x x))
(define (dup x) (list x x))
(define (duplicate-square lst)
(foldr append '() (map (comp dup square) lst)))
Now at the repl, do:
> (duplicate-square '(1 2 3 4))
'(1 1 4 4 9 9 16 16)

Resources