Trying to make a procedure called map-odd-mapper in scheme - dictionary

I'm trying to make a procedure called map-odd-mapper where I take a proc that can then be applied to a list
ex:
((make-odd-mapper add-one) (list 14 38 29 10 57))
(15 30 58)
I was thinking of putting it as a let function as in
(define (make-odd-mapper f)
(let (..........something using ret-odds to allow for the indices so that you can get the odd numbers....
ret-odds is defined as
(define (ret-odds lst)
(if (null? lst) null
(cons (car lst) (if (null? (cdr lst)) null (ret-odds (cdr (cdr lst))))))) the point of this is just to make a proc which will allow me to apply a procedure such as add-one to a list of odd indices....

This problem can be broken down into two smaller ones. At the risk of being pedantic: can you describe what these two smaller problems would be, and provide test cases for them?

(define (make-odd-mapper f)
(lambda (lst) (ret-odds (map f lst))))

Related

Racket: Compare elements in list recursively

This function is supposed to take a list (full of strings or ints, which is why it starts with that 'if' statement) and check to see if it is in ascending order.
I haven't been able to figure out how to keep it from crashing, as on the last recursive call, the 'cadr' has nothing to pull from, as the 'car' is the final element.
(define (my-sorted? lst)
(if (number? (car lst))
(if (< (car lst) (cadr lst))
(my-sorted? (rest lst))
#f)
#f)
)
I know that the sorted function exists, but I need to implement this function recursively.
Thanks for any help.
The two most basic lists that you should try are:
(my-sorted? '()) ; ==> #t (empty list is always sorted)
(my-sorted? '(1)) ; ==> #t (one element list is always sorted)
Your current code just does car and cadr on its argument so it will fail at different levels with these two tests.
The there is how to compare a number and something which is not a number. < expects both arguments to be numbers, but your list can be both strings and numbers. What is smaller of "x" and 7? You cannot do (< 7 "x").
Instead of nesting if you might consider cond which is lisps way of doing if-elseif-else. Basically you can do your code with cond like this:
(cond
((not (number? (car lst))) #f)
((< (car lst) (cadr lst)) (my-sorted? (rest lst))
(else #f))
EDIT
Since the list should either be all elements as string or all as number you simply can just determine the comparison function by looking at the first element and do your recursion with a named let and reuse the one based on the first element.
(define (my-sorted lst)
;; determine what comparison function to use, bind it to greater?
(define greater?
(if (and (pair? lst) (number? (car lst)))
>
string>?))
;; main recursive loop uses that one function
;; this can be done with define + call as well
(let loop ((lst lst))
(cond ((or (null? lst) (null? (cdr lst))) ...)
((greater? (car lst) (cadr lst)) ...)
(else (loop ...)))))

Scheme/Racket: most idiomatic way to append single element to end of list

I want to append the element b to the list a (let's say (a1, a2, ... an)), e.g. appending the number 3 to (1 2) gives (1 2 3)
So far I've been doing
(append a (list b)), which is kind of long and inelegant, so I wonder if there's a "better" way...
Are you building a list piecemeal, an item at a time? If so, the idiomatic way to do this is to build the list backward, using cons, and then reversing the final result:
(define (map-using-cons-and-reverse f lst)
(let loop ((result '())
(rest lst))
(if (null? rest)
(reverse result)
(loop (cons (f (car rest)) (cdr rest))))))
Alternatively, if your list-building is amenable to a "right-fold" recursive approach, that is also idiomatic:
(define (map-using-recursion f lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (f (car rest)) (recur (cdr rest))))))
The above code snippets are just for illustrating the solution approach to take in the general case; for things that are directly implementable using fold, like map, using fold is more idiomatic:
(define (map-using-cons-and-reverse f lst)
(reverse (foldl (lambda (item result)
(cons (f item) result))
'() lst)))
(define (map-using-recursion f lst)
(foldr (lambda (item result)
(cons (f item) result))
'() lst))
How frequent do you have to append to the end?
If you want to do it a lot (more than cons'ing to the front), then you are doing it wrong. The right way is to flip things around: think that cons put things to the back, first retrieves the last element, rest retrieves everything but last, etc. Then, you can use list normally.
However, if you want to put things to the end of the list as frequent as to cons things to the front, then this is the best that you can do with one list. You could write a function to wrap what you consider "inelegant". Traditionally it's called snoc (backward cons)
(define (snoc lst e) (append lst (list e)))
Or if you prefer to implement the whole thing by yourself:
(define (snoc lst e)
(cond
[(empty? lst) (list e)]
[(cons? lst) (cons (first lst) (snoc (rest lst) e))]))
Note that both approaches have the same time complexity: O(n) where n is length of the list.
But if you want it to be efficient, you can use a data structure called double-ended queue, which is very efficient (constant time per operation). See http://www.westpoint.edu/eecs/SiteAssets/SitePages/Faculty%20Publication%20Documents/Okasaki/jfp95queue.pdf for more details.

Referencing variables in racket

I'm trying to write a simple procedure for finding the n:th prime but I don't think I understand how to reference variables correctly in racket.
What I want is for the inner procedure sieve-iter to add primes to the list primlst which is in the namespace of sieve but I get an infinite loop. My guess is that primlst within sieve-iter is causing issues.
(define (sieve n) ;; returns the n:th prime (n>0)
(let [(primlst '(2))
(cand 3)]
(define (sieve-iter i lst)
(cond ((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;prime
((= (length primlst) n) (car primlst)) ;;end
((= (modulo i (car lst)) 0) (sieve-iter (+ i 2) primlst)) ;;non-prime
(#t (sieve-iter n (cdr lst))))) ;;unclear if prime
(sieve-iter cand primlst)))
Any help is appreciated!
First of all, you shouldn't refer to primlist at all within the sieve-iter function. Instead, you should refer to lst.
Second of all, you appear to be mistaken on the effect of this expression:
(and (cons i primlst) (sieve-iter (+ i 2) primlst))
You seem to be interpreting that as meaning "Add i to the primlist and then start the next iteration."
(cons i primlist) changes nothing. Instead, it creates a new list consisting of primlist with i in front of it and then evaluates to that value. The original primlist (which should have been lst anyway) is left untouched.
Also, and is for Boolean logic, not for stringing commands together. It evaluates each of its subexpressions separately until it finds one that evaluates to #f and then it stops.
You should replace that whole expression with this:
(sieve-iter (+ i 2) (cons i lst))
...which passes the new list created by cons to the next run of sieve-iter.
Your trying to do too much in one function, let prime-iter just worry about the iteration to build up the list of primes. Make another internal function to recurse down the existing primes to test the new candidate.
(define (sieve n) ;; returns the n:th prime (n>0)
(define (sieve-iter i lst remaining)
(cond ;((null? lst) (and (cons i primlst) (sieve-iter (+ i 2) primlst))) ;;should never be null, we are building the list up
((<= remaining 0) (car lst)) ;;checking length every time gets expensive added a variable to the function
((sieve-prime? i lst) ;;if prime add to lst and recurse on next i
(sieve-iter (+ i 2) (cons i lst) (- remaining 1)))
(else
(sieve-iter (+ i 2) lst remaining)))) ; else try next
(define (sieve-prime? i lst)
(cond ((null? lst) #t)
((= 0 (modulo i (car lst))) #f)
(else (sieve-prime? i (cdr lst)))))
(let ((primlst '(2)) ;;you generally don't modify these,
(cand 3)) ;mostly they just bind values to name for convenience or keep from having to re-calculate the same thing more than once
(sieve-iter cand primlst (- n 1))))
You could have used set! to modify primlist where it was before, but the procedure is no longer obviously a pure function.
There is another low-handing optimization possible here, when calling sieve-prime? filter the lst argument to remove values larger than the square root of i.

What is "named let" and how do I use it to implement a map function?

I'm totally new to Scheme and I am trying to implement my own map function. I've tried to find it online, however all the questions I encountered were about some complex versions of map function (such as mapping functions that take two lists as an input).
The best answer I've managed to find is here: (For-each and map in Scheme). Here is the code from this question:
(define (map func lst)
(let recur ((rest lst))
(if (null? rest)
'()
(cons (func (car rest)) (recur (cdr rest))))))
It doesn't solve my problem though because of the usage of an obscure function recur. It doesn't make sense to me.
My code looks like this:
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
I do understand the logic behind the functional approach when programming in this language, however I've been having great difficulties with coding it.
The first code snippet you posted is indeed one way to implement the map function. It uses a named let. See my comment on an URL on how it works. It basically is an abstraction over a recursive function. If you were to write a function that prints all numbers from 10 to 0 you could write it liks this
(define (printer x)
(display x)
(if (> x 0)
(printer (- x 1))))
and then call it:
(printer 10)
But, since its just a loop you could write it using a named let:
(let loop ((x 10))
(display x)
(if (> x 0)
(loop (- x 1))))
This named let is, as Alexis King pointed out, syntactic sugar for a lambda that is immediately called. The above construct is equivalent to the snippet shown below.
(letrec ((loop (lambda (x)
(display x)
(if (> x 0)
(loop (- x 1))))))
(loop 10))
In spite of being a letrec it's not really special. It allows for the expression (the lambda, in this case) to call itself. This way you can do recursion. More on letrec and let here.
Now for the map function you wrote, you are almost there. There is an issue with your two last cases. If the list is not empty you want to take the first element, apply your function to it and then apply the function to the rest of the list. I think you misunderstand what you actually have written down. Ill elaborate.
Recall that a conditional clause is formed like this:
(cond (test1? consequence)
(test2? consequence2)
(else elsebody))
You have any number of tests with an obligatory consequence. Your evaluator will execute test1? and if that evaluated to #t it will execute the consequence as the result of the entire conditional. If test1? and test2? fail it will execute elsebody.
Sidenote
Everything in Scheme is truthy except for #f (false). For example:
(if (lambda (x) x)
1
2)
This if test will evaluate to 1 because the if test will check if (lambda (x) x) is truthy, which it is. It is a lambda. Truthy values are values that will evaluate to true in an expression where truth values are expected (e.g., if and cond).
Now for your cond. The first case of your cond will test if L is null. If that is evaluated to #t, you return the empty list. That is indeed correct. Mapping something over the empty list is just the empty list.
The second case ((f (car L))) literally states "if f is true, then return the car of L".
The else case states "otherwise, return the result mymap on the rest of my list L".
What I think you really want to do is use an if test. If the list is empty, return the empty list. If it is not empty, apply the function to the first element of the list. Map the function over the rest of the list, and then add the result of applying the function the first element of the list to that result.
(define (mymap f L)
(cond ((null? L) '())
(f (car L))
(else (mymap (f (cdr L))))))
So what you want might look look this:
(define (mymap f L)
(cond ((null? L) '())
(else
(cons (f (car L))
(mymap f (cdr L))))))
Using an if:
(define (mymap f L)
(if (null? L) '()
(cons (f (car L))
(mymap f (cdr L)))))
Since you are new to Scheme this function will do just fine. Try and understand it. However, there are better and faster ways to implement this kind of functions. Read this page to understand things like accumulator functions and tail recursion. I will not go in to detail about everything here since its 1) not the question and 2) might be information overload.
If you're taking on implementing your own list procedures, you should probably make sure they're using a proper tail call, when possible
(define (map f xs)
(define (loop xs ys)
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys))))
(loop (reverse xs) empty))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)
Or you can make this a little sweeter with the named let expression, as seen in your original code. This one, however, uses a proper tail call
(define (map f xs)
(let loop ([xs (reverse xs)] [ys empty])
(if (empty? xs)
ys
(loop (cdr xs) (cons (f (car xs)) ys)))))
(map (λ (x) (* x 10)) '(1 2 3 4 5))
; => '(10 20 30 40 50)

Scheme: high order procedure and recursion

I'm using scheme as part of a course I'm taking. I've been told to use high order functions in my homework. However this instruction seems somewhat unclear.
I don't fully understand the idea of a high order procedure. I'm able to do all the questions using recursion but that it's the same thing. Can anyone explain it with an example of a recursive function vs one written with a high order procedure.
As a second question:
Example: try to grab all the odd numbers
I could use (flatten (map odd ((1 4 5) (4 5 1 4 9)))), but what if there were nested lists, can I use map on a nested lists like:
(flatten (map odd ((1 3 (9 5 7)))) ; is there a function for this or a clean way to do it?
The point of a higher-order function is to reduce the boilerplate in your code, and to decrease coupling between the looping (technically it's a recursion, but its purpose is looping, so I will refer to it as such) and the actual logic. Here's an example (re grabbing all the odd numbers): a manual loop would look like this:
(define (filter-odd lst)
(cond ((null? lst) '())
((odd? (car lst)) (cons (car lst) (filter-odd (cdr lst))))
(else (filter-odd (cdr lst)))))
But notice that you've got the looping and the filtering in one function. This makes it harder to figure out what the function is doing, since these two unrelated operations are coupled together. With higher-level functions, you can do differently:
(define (filter pred lst)
(cond ((null? lst) '())
((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))
(else (filter pred (cdr lst)))))
(define (filter-odd lst)
(filter odd? lst))
Notice now, how odd? is separated from the looping logic, which has now been separated into filter? filter now takes a function object which decides whether the item is to be kept or not, and callers of filter can slot in any function of their choice.
That is what is meant by a higher-order function: it's a function that takes a function object as a parameter, to customise its operation.
As mentioned in the original edit of your question, map is another higher-order function, but instead of filtering items from a list, it returns a transformation of every item in the original list, where the specific transformation is given by map's caller via a parameter.
To answer your actual question about flattening, etc., (map filter-odd '((1 3 (9 5 7)))) will return a list with a single item, the result of calling (filter-odd '(1 3 (9 5 7))). So no, map will not recurse into sublists for you (and neither will filter).
But you can flatten the input first (since you're flattening the output anyway), then call filter-odd on that directly. I hope that will give you the result you expect.
(I renamed your odd to filter-odd, since that is less likely to be confused with odd? (the predicate).)
Bonus material
By the way, both filter and map are specialisations of a much more general higher-order function, called a fold (or more specifically, a right-fold). Folds can express things that cannot be accommodated by either filter or map, but that somehow involve traversing all the items in a list. Here's an example of a length function, expressed as a fold:
(define (foldl func init lst)
(if (null? lst) init
(foldl func (func (car lst) init) (cdr lst))))
(define (length lst)
(foldl (lambda (elem count)
(+ count 1))
0 lst))
The benefit here is that the length function does not have to worry about traversing the list: that is handled by the fold. It only needs to worry about what to do at each iteration (which, here, is simply adding 1 to count, which starts out as 0).
In this case, the length is the same whether we traverse from the left or the right, and in Scheme, traversing from the left is more space-efficient, so we prefer that. But for implementing map and filter, a right-fold is necessary (otherwise the elements come out reversed---try substituting the foldr with foldl in the below functions and you'll see):
(define (foldr func init lst)
(if (null? lst) init
(func (car lst) (foldr func init (cdr lst)))))
(define (map func lst)
(foldr (lambda (elem result)
(cons (func elem) result))
'() lst))
(define (filter pred lst)
(foldr (lambda (elem result)
(if (pred elem)
(cons elem result)
result))
'() lst))

Resources