I am learning how to use higher-order functions in scheme. I get the idea of using higher-order functions, however I am having trouble using them. For this learning exercise, I would prefer to only use some combination of filter, fold, and/or map.
For example, I want to construct the set difference between two lists call them A and B. I am defining set difference as x such that x is an element of A but x is not an element of B. I only want to use the functions map, filter and fold. For example:
Let A = (1 8 6 2)
Let B = (5 7 9 1 6)
The set difference of A and B would be (8 2)
The idea is to construct a new list by iterating over the elements of A and seeing if an element of A equals an element of B, if so don't add a to the new list; otherwise add a to the new list.
My algorithm idea goes something like this:
Let neq be "not equal to"
For each a in A and b in B evaluate the expression: (neq? a b)
For a = 1 we have:
(and (neq? 1 5) (neq? 1 7) (neq? 1 9) (neq? 1 1) (neq ? 1 6))
If this expression is true then a goes in the new list; otherwise don't add a to the new list. In our example (neq? 1 1) evaluates to false and so we do not add 1 to the new list.
Pretty much my entire procedure relies on 1, and this is where I have a trouble.
How do I do step 1?
I see that in step 1 I need some combination of the map and fold functions, but how do I get the and a neq b distributed?
EDIT This is the closest sample I have:
(fold-right (trace-lambda buggy (a b c) (and (neq? a b))) #t A B)
|(buggy 3 5 #t)
|#t
|(buggy 2 4 #t)
|#t
|(buggy 1 1 #t)
|#f
#f
The above shows a trace of my anonymous function attempting to perform the (and (neq? a b)) chain. However, it only performs this on elements in A and B at the same position/index.
All help is greatly appreciated!
A simplified version of member is easy to implement using fold, of course:
(define (member x lst)
(fold (lambda (e r)
(or r (equal? e x)))
#f lst))
Now, with that, the rest is trivial:
(define (difference a b)
(filter (lambda (x)
(not (member x b)))
a))
If you want to amalgamate all that into one function (using your neq?), you can do:
(define (difference a b)
(filter (lambda (x)
(fold (lambda (e r)
(and r (neq? e x)))
#t b))
a))
In Haskell, fold is capable of short-circuiting evaluation because of lazy evaluation.
But in Scheme it is impossible. That's why in Racket e.g., there's a special function supplied for that, ormap, which is capable of short-circuiting evaluation. IOW it is a special kind of fold which must be defined explicitly and separately in Scheme, because Scheme is not lazy. So according to your conditions I contend it is OK to use it as a special kind of fold.
Using it, we get
(define (diff xs ys)
(filter
(lambda (y)
(not (ormap (lambda (x) (equal? x y)) ; Racket's "ormap"
xs)))
ys))
If your elements can be ordered, it is better to maintain the sets as ordered (ascending) lists; then diff can be implemented more efficiently, comparing head elements from both lists and advancing accordingly, working in linear time.
Using Racket:
(define A '(1 8 6 2))
(define B '(5 7 9 1 6))
(filter-not (lambda (x) (member x B)) A)
==> '(8 2)
Of course, it is possible in Scheme to implement member on top of fold that short-circuits on the first match:
(define (member x lst)
(call-with-current-continuation
(lambda (return)
(fold (lambda (e r)
(if (equal? e x)
(return #t)
r))
#f lst))))
Related
I want to create a function using abstract list functions that will apply a list of functions onto each other, without a starting element (take the starting point as 0)
So '(list add1 sqr add1) -> 2
What I have so far creates a list of what those function do individually, so for the above example '(1 0 1)
Any help? An explanation would be nice if you could spare one, I'm still iffy about things such as foldr, map, etc
(define (apply_functions lof)
(map (lambda (lof) (lof 0)) lof))
I previously defined a composite function as below in case its helpful at all?
(define (composite f g)
(lambda (x) (f (g x))))
Could the initial problem also be translated to a function which takes in a list of function and an initial number (other than 0) and produces the number result
for example:
'( add1 sqr sub1) 4 -> 10
EDIT::
So looking at the question, it wanted something such as (check-expect ((composite-list (list add1 sqr sub1)) 3) 5), where the start number is not included as a variable. I've tried multiple variations of the code but can't make it work.
This is a perfect situation for using foldr, it behaves as expected:
(define (apply-functions lof)
(foldr (lambda (f acc) (f acc))
0
lof))
(apply-functions (list add1 sqr add1))
=> 2
It works because we apply each f in turn to the accumulated result, starting with 0. Notice that foldr applies the functions in the list in a right-to-left order (that is: the first function applied is the last one in the list, then the result of that is passed to the second-to-last function and so on). If you want to enforce a left-to-right order use foldl instead.
For the last part of your question (after the edit): we can start with a different initial number by simply passing the right parameter to foldr, and returning a curried function:
(define ((composite-list lof) init)
(foldr (lambda (f acc) (f acc))
init
lof))
((composite-list (list add1 sqr sub1)) 3)
=> 5
You can even do it more general than that. You can actually make a generic compose:
(define (my-compose . procedures)
(let* ((proc-in-order (reverse procedures))
(init-proc (car proc-in-order))
(remaining-procs (cdr proc-in-order)))
(lambda g
(foldl (lambda (x acc) (x acc))
(apply init-proc g)
remaining-procs))))
;; test first makes a list of it's arguments,
;; then takes the length, then negates that value
(define test (my-compose - length list))
(test 1 2 3 4) ; ==> -4
The first procedure in the chain (last argument) is applied with the initial argument as a list so it takes many arguments while the rest of the chain takes exactly one.
So I'm currently stuck on a "simple?" function in Racket. It's using the Intermediate Student with lambda language.
Some restrictions on this are that NO recursion is allowed, neither are local functions. It's plain and simple abstract list functions.
What this function is supposed to do is to take in a list of numbers, and output a list of pairs in which each pair has the first element as the number with the second element being the number it has occurred in the list.
Examples:
(1 1 2 3) => ((1 2) (2 1) (3 1))
(2 3 4 3) => ((2 1) (3 2) (4 1))
I have a function that produces the number of occurrences by inputting a list of numbers and a number which is:
(define (occurrences lon n)
(length (filter (lambda (x) (= x n)) lon)))
My approach, which was clearly wrong was:
(define (num-pairs-occurrences lon)
(list (lambda (x) (map (occurrences lon x) (remove x lon)) x))
I thought the above would work, but apparently my lambda isn't placed properly. Any ideas?
It's a bit trickier than you imagine. As you've probably noticed, we must remove duplicate elements in the output list. For this, is better that we define a remove-duplicates helper function (also using abstract list functions) - in fact, this is so common that is a built-in function in Racket, but not available in your current language settings:
(define (remove-duplicates lst)
(foldr (lambda (e acc)
(if (member e acc)
acc
(cons e acc)))
'()
lst))
Now it's easy to compose the solution using abstract list functions:
(define (num-pairs-occurrences lon)
(map (lambda (e) (list e (occurrences lon e)))
(remove-duplicates lon)))
The above might return and output list in a different order, but that's all right. And before you ask: yes, we do need that helper function. Please don't ask for a solution without it...
An easy, self-contained solution would be:
(define (num-pairs-occurences lst)
(foldl (lambda (e r)
(if (or (null? r) (not (= (caar r) e)))
(cons (list e 1) r)
(cons (list e (add1 (cadar r))) (cdr r))))
null
(sort lst >)))
Basically, you sort the list first, and then you fold over it. If the element (e) you get is the same as the first element of the result list (r), you increment the count, otherwise you add a new sublist to r.
If you sort by > (descending), you can actually use foldl which is more memory-efficient. If you sort by < (ascending), you need to use foldr which is less efficient.
How would you define a function which takes one argument, which should be a list, and returns the elements in the
list which are themselves lists?
(check-expect (find-sublists ’(1 2 () (3) (a b c) a b c))
’(() (3) (a b c)))
Do you have experience designing functions that can filter through a list?
A simpler problem with the same flavor as the original is something like this: design a function that takes a list of numbers and keeps only the even numbers. Would you be able to do that function?
Looking at http://www.ccs.neu.edu/home/matthias/HtDP2e/htdp2e-part2.html and going through its guided exercises may also help.
Two useful tools which should start you on your way:
1) Traversing through a list:
; traverse: takes a list of numbers
; Goes through each element, one-by-one, and alters it
(define traverse
(lambda (the_list)
(if (empty? the_list)
empty
(cons (+ 1 (first the_list))
(traverse (rest the_list))))))
(traverse (cons 3 (cons 4 empty))) returns (cons 4 (cons 5 empty))
2) list?:
(list? (list 1 2 3)) returns #t
(list? 5) returns #f
In Python, I can do something like this:
t = (1, 2)
a, b = t
...and a will be 1 and b will be 2. Suppose I have a list '(1 2) in Scheme. Is there any way to do something similar with let? If it makes a difference, I'm using Racket.
In racket you can use match,
(define t (list 1 2))
(match [(list a b) (+ a b)])
and related things like match-define:
(match-define (list a b) (list 1 2))
and match-let
(match-let ([(list a b) t]) (+ a b))
That works for lists, vectors, structs, etc etc. For multiple values, you'd use define-values:
(define (t) (values 1 2))
(define-values (a b) (t))
or let-values. But note that I can't define t as a "tuple" since multiple values are not first class values in (most) scheme implementations.
A bare-bones idiom is to use apply with lambda where you'd use let, like:
(define t '(1 2))
(apply (lambda (a b)
;; code that would go inside let
)
t)
The advantage is that it works on any implementation. Of course this can only be used on simple cases, but sometimes that's all you need.
The general term for what you're looking for (at least in Lisp-world) is destructuring and a macro that implements it is known as destructuring-bind. In Common Lisp, it works like this:
(destructuring-bind (a b c) '(1 2 3)
(list a b c)) ;; (1 2 3)
it also works for multiple "levels" of nesting:
(destructuring-bind (a (b c) d) '(1 (2 3) 4)
(list a b c d)) ;; (1 2 3 4)
It looks like there's a nice implementation of destructuring-bind as a scheme macro.
I think this is what you are looking for:
http://www.phyast.pitt.edu/~micheles/scheme/scheme16.html
Look at let-values or let+.
This works in Racket if you don't want to bring in the match dependency:
From a list:
(let-values ([(a b c) (apply values '(1 2 3))])
(+ a b c))
Or directly from a values expression:
(let-values ([(a b c) (values 1 2 3)])
(+ a b c))
Here is a simple destructuring-bind macro for schemes with case-lambda (such as Racket or Chez Scheme):
(define-syntax bind
(syntax-rules ()
((_ arg pat def body)
(apply
(case-lambda
[pat body]
[x def] )
arg ))))
Here is the example that motivated me to write this macro. Putting the default before the body makes for readable code:
(define (permutations l)
;
(define (psub j k y)
;
(define (join a b)
(bind a (ah . at) b
(join at (cons ah b)) ))
;
(define (prec a b z)
(bind b (bh . bt) z
(prec (cons bh a) bt
(psub (cons bh j) (join a bt) z) )))
;
(if (null? k)
(cons (reverse j) y)
(prec (list) k y) ))
;
(psub (list) (reverse l) (list)) )
Here are benchmarks for computing permutations of length 9, on various schemes:
0m0.211s Chez Scheme
0m0.273s Bigloo
0m0.403s Chicken
0m0.598s Racket
The translation to GHC Haskell is 5x faster than Chez Scheme. Guile is much slower than any of these schemes.
Aside from the ease of leveraging the existing case-lambda code, I like how this macro accepts exactly the same syntax as function definition argument lists. I love the simplicity of scheme. I'm old enough to remember programming Fortran on punched cards, where the allowed syntax varied wildly with context. Scheme is supposed to be better than that. The impulse is overwhelming to guild the lily on macros like this. If you can't justify changing the syntax for function definitions too, then don't change that syntax here either. Having an orthogonal grammar is important.
I'm trying to write a function in scheme that takes a list and squares every item on the list, then returns the list in the form (list x y z). However, I'm not sure how to write a code that will do that. So far, I have
(define (square=list list)
(cond
[(empty? list) false]
[else (list (sqr (first a-list))(square-list (rest a-list)))]))
but it returns the list in the form
(cons x (cons y (cons z empty)))
What can I do to make it return the list just in the form (list x y z)? Thanks!
You're almost there -- make sure you understand the difference between cons and list (the textbook How to Design Programs explains this in Section 13. You can find the online copy here).
cons will take an item as its first element and (usually) a (possibly empty) list for the 'rest' part. As an example, (cons 1 empty) has the number 1 as its first element and the empty list as the 'rest'. (cons 1 (cons 2 empty)) has the number 1 as the first element, and (cons 2 empty) as the 'rest'.
list is just an easy shorthand for making lists, taking an arbitrary number of items. Thus:
(list 1 2 3 4 5)
is the same as...
'(1 2 3 4 5)
which is the same as
(cons 1 (cons 2 (cons 3 (cons 4 (cons 5 empty))))).
But be careful. (list 1 (list 2 (list 3))) is not the same as (cons 1 (cons 2 (cons 3 empty))). In fact, it is (cons 1 (cons 2 (cons 3 empty) empty) empty).
If you're still confused, feel free to post a comment.
The problem is that you're using list in the else statement. You are saying build me a list with this value as the first entry, and a list as the second entry.
You want to cons the first entry onto the list created by recursive call.
(list 'a '(b c d))
; gives you
'(a (b c d))
(cons 'a '(b c d))
; gives you
'(a b c d)
This is probably not what your TA is looking for, but I'll throw it in anyway because it may help you grok a tiny bit more of Scheme. The idiomatic (in Scheme) way to write what you are trying to do is to use map:
> (map (lambda (x) (* x x)) '(1 2 3 66 102 10403))
(1 4 9 4356 10404 108222409)
map applies a function (here, (lambda (x) (* x x)) - a nameless function that returns the square of its input) to each element of a list and returns a new list containing all of the results. Scheme's map basically does the same iteration you are doing in your code, the advantage being that by using map you never have to explicitly write such iterations (and, nominally at least, a Scheme implementation might optimize map in some special way, though that's not really that important in most cases). The important thing about map is that it reduces your code to the important parts - this code squares each element of the list, this other code takes the square root of each element, this code adds one to it, etc, without having to repeat the same basic loop iteration code again and again.