Scheme pass variables to a variadic function - recursion

I have the following variadic function (define doSomething (lambda (x . rest) .... The function is called by using numbers, for example: (doSomething 1 2 3 4 5) (so with that call x would be 1 and rest would be (2 3 4 5)).
When I try to recursively call the function and put the second number (2) as x and rest as (3 4 5) I somehow receive the rest parameter as a list of list: ((3 4 5)).
This is how I currently try to call the function again:
(+ x (doSomething (car rest) (cdr rest)))
It is worth mentioning that I'm using Pretty Big. Please advise, thanks.

So you're mix and matching what rest is, in your first call
(doSomething 1 2 3 4 5) ; x = 1 rest = '(2 3 4 5)
In your subsequent calls you'll end up with
(doSomething (car rest) (cdr rest)) ; x=2 rest = '((3 4 5))
because rest is a variadic argument, so it takes everything after the first argument and makes it a list called rest for you, hence the double-listing. You'll probably want to be using apply or something, ie something like:
(define doSomething (lambda (x . rest)
(display x)
(if (not (null? rest))
(apply doSomething rest)
#f)))

Related

Non-tail recursive function that returns the last element in list without using reverse?

Im trying to make a non-tail recursive function returns the last element of a list without using reverse, map, iteration, mutation of any sort (built in or user-built). So far I have successfully made a tail-recursive version and a non-tail version that uses reverse func. But I just cannot figure how to make a non-tail recursive function.
I really appreciate your help!
Imagine you have the tail recursive version like this:
(define (last-element lst)
(if base-case-expression
result-expression
recursion-expression))
Now in order to not make it tail recursive you just make your function do something with the result. eg. cache it in a binding and then return:
(define (last-element lst)
(if base-case-expression
result-expression
(let ((result recursion-expression))
result)))
Here the recursive call is not the tail position. However a sufficiently smart compiler might make compiled code that is tail recursive. Eg. a lot of Scheme implementations transform code to continuation passing style and then every call becomes a tail call and stack is replaced with growing closures. The result of that on both versions will be very similar.
Note: for some reason I wrote this answer using Common Lisp, before noticing that the question was tagged with scheme, racket, and lisp. In any case, Common Lisp falls under the latter tag, and the code is easily adapted to either Scheme or Racket.
For a function to be non-tail recursive, you need to place recursive calls so that they are not in tail position, i.e., so that no further operations are needed on the results of the recursive call before it is returned. So, you need a recursive strategy for getting to the last element of a list that does further operations on the result of recursive calls.
One strategy would be to build a "reversed list" on the way back up from the base case, taking that list apart at the same time so that the desired result is left at the end. Here is a reversal function to show the idea without taking anything apart:
(defun reversal (xs)
(if (cdr xs)
(cons (reversal (cdr xs)) (car xs))
xs))
The above function builds a nested dotted list with the elements of the input list in reverse:
CL-USER> (reversal '(1 2 3 4 5))
(((((5) . 4) . 3) . 2) . 1)
Now, the car function could be called numerous times on this result to get the last element of the input, but we can just do this as the new list is constructed:
(defun my-last (xs)
(car (if (cdr xs)
(cons (my-last (cdr xs)) (car xs))
xs)))
Here the my-last function is called after calling (trace my-last):
CL-USER> (trace my-last)
(MY-LAST)
CL-USER> (my-last '(1 2 3 4 5))
0: (MY-LAST (1 2 3 4 5))
1: (MY-LAST (2 3 4 5))
2: (MY-LAST (3 4 5))
3: (MY-LAST (4 5))
4: (MY-LAST (5))
4: MY-LAST returned 5
3: MY-LAST returned 5
2: MY-LAST returned 5
1: MY-LAST returned 5
0: MY-LAST returned 5
5
This solution requires two operations on the result of calling my-last, i.e., cons and car. It does seem possible that an optimizer could notice that car is being called on the result of a cons, and optimize my-last to something like:
(defun my-last-optimized (xs)
(if (cdr xs)
(my-last-optimized (cdr xs))
(car xs)))
If this were the case, then the optimized code would be tail recursive, and tail call optimizations could then be applied. I do not know if any lisp implementations can do this sort of optimization.
An alternate strategy would be to store the original list and then to take it apart on the way back up from the base case using cdr. Here is a solution using a helper function:
(defun my-last-2 (xs)
(car (my-last-helper xs xs)))
(defun my-last-helper (xs enchilada)
(if (cdr xs)
(cdr (my-last-helper (cdr xs) enchilada))
enchilada))
This also works as expected. Here is an example, again using trace to see the function calls. This time both my-last-2 and my-last-helper have been traced:
(trace my-last-2 my-last-helper)
(MY-LAST-2 MY-LAST-HELPER)
CL-USER> (my-last-2 '(1 2 3 4 5))
0: (MY-LAST-2 (1 2 3 4 5))
1: (MY-LAST-HELPER (1 2 3 4 5) (1 2 3 4 5))
2: (MY-LAST-HELPER (2 3 4 5) (1 2 3 4 5))
3: (MY-LAST-HELPER (3 4 5) (1 2 3 4 5))
4: (MY-LAST-HELPER (4 5) (1 2 3 4 5))
5: (MY-LAST-HELPER (5) (1 2 3 4 5))
5: MY-LAST-HELPER returned (1 2 3 4 5)
4: MY-LAST-HELPER returned (2 3 4 5)
3: MY-LAST-HELPER returned (3 4 5)
2: MY-LAST-HELPER returned (4 5)
1: MY-LAST-HELPER returned (5)
0: MY-LAST-2 returned 5
5
In this case, the only operation required after recursive calls to my-last-2 return is cdr, but that is enough to prevent this from being a tail call.

Functional programming for 3 lists in Racket

I could manage following code to replaces items in a list using 2 other lists. Orilist and newlist have original and new terms in order. The replacement is done using orilist and newlist- if orilist items are present in slist, slist is changed to have corresponding new items from newlist:
(define (list-replace-from-lists slist orilist newlist)
(define replaced #f)
(define outl '())
(for ((item slist))
(set! replaced #f)
(for ((ori_ orilist) (i (in-naturals)) #:when (equal? item ori_))
(set! outl (cons (list-ref newlist i) outl))
(set! replaced #t))
(when (not replaced)
(set! outl (cons item outl))))
(reverse outl))
To replace 2 and 5 to 12 and 15, respectively, in (list 1 2 3 4 5 6) :
(list-replace-from-lists (list 1 2 3 4 5 6) (list 2 5) (list 12 15))
Output is:
'(1 12 3 4 15 6)
However, above code does not look functional and has many set! statements. How can this be converted to functional code? Should I use structures or some other data-types for above purpose?
Edit: items may recur in original list, e.g. (list 1 2 3 4 5 2 6)
You can still use lists and keep everything functional. :-) Here's my solution:
(define (replace-all haystack needles new-needles)
(define replace-alist (map cons needles new-needles))
(define (replace-one item)
(cond ((assoc item replace-alist) => cdr)
(else item)))
(map replace-one haystack))
Explanation of the code:
First, we build a replacement association list (alist). This is a list of pairs, of which the keys correspond to the needles and the values correspond to new-needles.
Then we define a replace-one function that takes an item, and sees if it matches any of the keys in the alist. If so, we return the corresponding value; otherwise, we return the original item.
Finally, we map the haystack through replace-one. Yay higher-order functions!
Note that this code is O(m*n) where m is the size of haystack and n is the size of needles, which is the same runtime as your version. If needles is large, you will want to use a hashtable instead of an alist, which will amortise the runtime of the function to O(m).
This is a functional solution that uses hash to keep the associations. That makes this solution O(haystack-length log needle-length) since immutable hashes are implemented with trees.
(define (list-replace-all haystack needles new-values)
;; make a dictionary of elements to be replaced
(define hash
(foldl (λ (needle new-value hash)
(hash-set hash needle new-value))
#hash()
needles
new-values))
;; do the replace. If not in hash the actual key is default
(map (λ (e) (hash-ref hash e e)) haystack))
(list-replace-all '(1 2 3 4 5 6) '(2 5) '(12 15))
; ==> (1 12 3 4 15 6)

Average using &rest in lisp

So i was asked to do a function i LISP that calculates the average of any given numbers. The way i was asked to do this was by using the &rest parameter. so i came up with this :
(defun average (a &rest b)
(cond ((null a) nil)
((null b) a)
(t (+ (car b) (average a (cdr b))))))
Now i know this is incorrect because the (cdr b) returns a list with a list inside so when i do (car b) it never returns an atom and so it never adds (+)
And that is my first question:
How can i call the CDR of a &rest parameter and get only one list instead of a list inside a list ?
Now there is other thing :
When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there.
My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
EDIT: I know the function only does the + operation, i know i have to divide by the length of the b list + 1, but since i got this error i'd like to solve it first.
(defun average (a &rest b)
; ...
)
When you call this with (average 1 2 3 4) then inside the function the symbol a will be bound to 1 and the symbol b to the proper list (2 3 4).
So, inside average, (car b) will give you the first of the rest parameters, and (cdr b) will give you the rest of the rest parameters.
But when you then recursively call (average a (cdr b)), then you call it with only two arguments, no matter how many parameters where given to the function in the first place. In our example, it's the same as (average 1 '(3 4)).
More importantly, the second argument is now a list. Thus, in the second call to average, the symbols will be bound as follows:
a = 1
b = ((3 4))
b is a list with only a single element: Another list. This is why you'll get an error when passing (car b) as argument to +.
Now there is other thing : When i run this function and give values to the &rest, say (average 1 2 3 4 5) it gives me stackoverflow error. I traced the funcion and i saw that it was stuck in a loop, always calling the function with the (cdr b) witch is null and so it loops there. My question is:
If i have a stopping condition: ( (null b) a) , shouldnt the program stop when b is null and add "a" to the + operation ? why does it start an infinite loop ?
(null b) will only be truthy when b is the empty list. But when you call (average a '()), then b will be bound to (()), that is a list containing the empty list.
Solving the issue that you only pass exactly two arguments on the following calls can be done with apply: It takes the function as well as a list of parameters to call it with: (appply #'average (cons a (cdr b)))
Now tackling your original goal of writing an average function: Computing the average consists of two tasks:
Compute the sum of all elements.
Divide that with the number of all elements.
You could write your own function to recursively add all elements to solve the first part (do it!), but there's already such a function:
(+ 1 2) ; Sum of two elements
(+ 1 2 3) ; Sum of three elements
(apply #'+ '(1 2 3)) ; same as above
(apply #'+ some-list) ; Summing up all elements from some-list
Thus your average is simply
(defun average (&rest parameters)
(if parameters ; don't divide by 0 on empty list
(/ (apply #'+ parameters) (length parameters))
0))
As a final note: You shouldn't use car and cdr when working with lists. Better use the more descriptive names first and rest.
If performance is critical to you, it's probably best to fold the parameters (using reduce which might be optimized):
(defun average (&rest parameters)
(if parameters
(let ((accum
(reduce #'(lambda (state value)
(list (+ (first state) value) ;; using setf is probably even better, performance wise.
(1+ (second state))))
parameters
:initial-value (list 0 0))))
(/ (first accum) (second accum)))
0))
(Live demo)
#' is a reader macro, specifically one of the standard dispatching macro characters, and as such an abbreviation for (function ...)
Just define average*, which calls the usual average function.
(defun average* (&rest numbers)
(average numbers))
I think that Rainer Joswig's answer is pretty good advice: it's easier to first define a version that takes a simple list argument, and then define the &rest version in terms of it. This is a nice opportunity to mention spreadable arglists, though. They're a nice technique that can make your library code more convenient to use.
In most common form, the Common Lisp function apply takes a function designator and a list of arguments. You can do, for instance,
(apply 'cons '(1 2))
;;=> (1 . 2)
If you check the docs, though, apply actually accepts a spreadable arglist designator as an &rest argument. That's a list whose last element must be a list, and that represents a list of all the elements of the list except the last followed by all the elements in that final list. E.g.,
(apply 'cons 1 '(2))
;;=> (1 . 2)
because the spreadable arglist is (1 (2)), so the actual arguments (1 2). It's easy to write a utility to unspread a spreadable arglist designator:
(defun unspread-arglist (spread-arglist)
(reduce 'cons spread-arglist :from-end t))
(unspread-arglist '(1 2 3 (4 5 6)))
;;=> (1 2 3 4 5 6)
(unspread-arglist '((1 2 3)))
;;=> (1 2 3)
Now you can write an average* function that takes one of those (which, among other things, gets you the behavior, just like with apply, that you can pass a plain list):
(defun %average (args)
"Returns the average of a list of numbers."
(do ((sum 0 (+ sum (pop args)))
(length 0 (1+ length)))
((endp args) (/ sum length))))
(defun average* (&rest spreadable-arglist)
(%average (unspread-arglist spreadable-arglist)))
(float (average* 1 2 '(5 5)))
;;=> 3.25
(float (average* '(1 2 5)))
;;=> 2.66..
Now you can write average as a function that takes a &rest argument and just passes it to average*:
(defun average (&rest args)
(average* args))
(float (average 1 2 5 5))
;;=> 3.5
(float (average 1 2 5))
;;=> 2.66..

New to Scheme, stuck on this one

write a scheme function workit that takes a predicate and a list of integers as arguments. the function should multiply each item in the list that satisfies the predicate by 2 and adds the results. For example::
(workit even? '(1 2 3 4 5 6)) ==> 4+8+12=24
(workit odd? '(1 2 3 4 5 6)) ==> 2+6+10=18
You may not use map, remove, filter, or any other higher order function.
Could someone at least help me get a head start on this? Decided to learn Scheme for a job that I am interested in applying for.... Any help would be great! Thanks
First define even?
(define (even? x) (= 0 (modulo x 2)))
You can define odd? in terms of not even
(define (odd? x) (not (even? x)))
Your workit function is pretty self-explanatory
(define (workit predicate xs)
(define (iter sum xs)
(cond ((empty? xs) sum)
((predicate (first xs)) (iter (+ sum (* 2 (first xs))) (rest xs)))
(else (iter sum (rest xs)))))
(iter 0 xs))
I defined an inner iter function to step through the list of provided numbers, xs, while keeping track of the output, sum.
If the list we're iterating through is empty?, we're done, so return the sum
Else, if (predicate x) is true, add (* 2 x) to the sum and continue iteration
Otherwise, the predicate is false, do not alter the sum for this iteration
I chose to use the auxiliary iter function in order to achieve proper tail recursion. This allows workit to operate in constant space.
Outputs
(print (workit even? '(1 2 3 4 5 6))) ;; => 24
(print (workit odd? '(1 2 3 4 5 6))) ;; => 18
If there are no elements in the list, the workit of the list is some base
value.
If the first element satisfies some condition, then the workit of the list is the result of some operation involving that first element, and the workit of the remainder of the list.
If the first element does not satisfy the condition, then the workit of the list is simply the workit of the remainder of the list.
Note that each time workit is called recursively (as in the second and third cases) the list is the remainder of the list in the the previous call.

Processing pairs of successive elements in a list with standard mapping functions?

I have a small exercise in Lisp:
Write a function test-delta with parameters delta and lst, which will
check if the difference between successive elements in lst is smaller than
delta. Write the function in two ways:
recursively
using a mapping function
I have no problem writing that function recursively, but I don't know which mapping function I should use. All the standard mapping functions work with only one element of the list at a time. reduce cannot be used either, because I do not have some operation to use between successive elements. What function could I use here?
All standard functions are working only with one element at time.
Reduce function cannot be use either
because i do not have some operation to use between to elements.
There's already an answer by uselpa showing that you can do this with reduce, but it feels a bit awkward to me to bend reduce to this case.
It's much more natural, in my opinion, to recognize that the standard mapping functions actually let you work with multiple lists. I'll show mapcar and loop first, and then every, which I think is the real winner here. Finally, just for completeness, I've also included maplist.
mapcar
The standard mapcar can take more than one list, which means that you can take elements from two different lists at once. Of particular note, it could take a list and (rest list). E.g.,
(let ((list '(1 2 3 4 5 6)))
(mapcar 'cons
list
(rest list)))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
loop
You can use loop to do the same sort of thing:
(loop
with l = '(1 2 3 4 5 6)
for a in l
for b in (rest l)
collect (cons a b))
;=> ((1 . 2) (2 . 3) (3 . 4) (4 . 5) (5 . 6))
There are some other variations on loop that you can use, but some of them have less conventient results. E.g., you could loop for (a b) on list, but then you get a (perhaps) unexpected final binding of your variables:
(loop for (a b) on '(1 2 3 4 5 6)
collect (list a b))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
This is similar to what maplist will give you.
every
I think the real winners here, though, are going to the be every, some, notevery, and notany functions. These, like mapcar can take more than one list as an argument. This means that your problem can simply be:
(let ((delta 4)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> T
(let ((delta 2)
(lst '(1 2 4 7 9)))
(every (lambda (x y)
(< (abs (- x y)) delta))
lst
(rest lst)))
;=> NIL
maplist
You could also do this with maplist, which works on successive tails of the list, which means you'd have access to each element and the one following. This has the same 6 NIL at the end that the second loop solution did, though. E.g.:
(maplist (lambda (tail)
(list (first tail)
(second tail)))
'(1 2 3 4 5 6))
;=> ((1 2) (2 3) (3 4) (4 5) (5 6) (6 NIL))
reduce can be used:
(defun testdelta (delta lst)
(reduce
(lambda (r e)
(if (< (abs (- r e)) delta)
e
(return-from testdelta nil)))
lst)
t)
or, without return-from (but possibly slower):
(defun testdelta (delta lst)
(and
(reduce
(lambda (r e)
(and r (if (< (abs (- r e)) delta) e nil)))
lst)
t))

Resources