Is there a way to make a list that holds functions? What I'm trying to do is, make a list of some arithmetic operators (+ - * /) so I can easily manipulate their order and apply them to a list of numbers.
So, if I have that list, I'd use it like this:
(apply (map (lambda (x)
x)
'(+ - * /))
'(1 2 3 4))
I'm a novice programmer, so if there's a better way to do such operation, your advice is much appreciated.
Lists are made with the function LIST.
(list 1 2 3)
(list + - * /)
Applying a list of symbols makes no sense:
(apply (map (lambda (x) x) '(+ - * /)) '(1 2 3 4))
Would be (applying a list of functions still makes no sense):
(apply (map (lambda (x) x) (list + - * /)) '(1 2 3 4))
Simplified (still wrong):
(apply (list + - * /) '(1 2 3 4))
But, maybe you wanted this:
(map (lambda (f)
(apply f '(1 2 3 4)))
(list + - * /))
In Common Lisp:
(mapcar #'(lambda (f)
(apply f '(1 2 3 4)))
(list #'+ #'- #'* #'/))
Returns:
(10 -8 24 1/24)
I'm surprised no one has mentioned quasiquotation. :-) In Scheme, you could say:
`(,+ ,- ,* ,/)
or in Common Lisp:
`(,#'+ ,#'- ,#'* ,#'/)
In some cases, especially involving complex lists, quasiquotation makes the code much simpler to read than the corresponding list version.
Related
Using Common Lisp (SBCL), I can successfully evaluate in REPL:
CL-USER> (reduce #'+ '(1 2 3 4))
10
However, this fails:
> (reduce #'(lambda (e) (+ e 100)) '(1 2 3 4))
The debugger throws an error:
invalid number of arguments: 2
I was expecting an accumulating effect, so the sum would be 110.
How can I achieve the expected result? Do I need to use something else than reduce?
The reducing function must accept two arguments. Your lambda function accepts only one. Even if it worked it would add 100 to your result on each step of the additions along the list.
What you mean is specifying the initial value. The simplest hacky way is just to cons it onto your list, like
> (reduce #'+ (cons 100 '(1 2 3 4)))
110
The proper way, going by the specs, is to explicitly specify it with the :initial-value keyword parameter:
> (reduce #'+ '(1 2 3 4) :initial-value 100)
110
And if you do want to add the 100 on each reduction step,
> (reduce #'(lambda (a x) (+ 100 a x)) '(1 2 3 4))
310
You might want to add one more 100 by specifying is as the :initial-value as well.
Calling (reduce #'f '(1 2 3 4)) will compute
(f (f (f 1 2) 3) 4)
So for example
>>> (reduce #'(lambda (a b) (cons a b)) '(1 2 3 4))
(((1 . 2) . 3) . 4)
Thus, the function you pass to reduce needs to accept two arguments. This function is first called with the first two elements of the sequence. Then the function is called with result of the previous call and the next element in the sequence and so on (see [CLHS reduce]). To obtain the sum of all elements you need to call the following:
>>> (reduce #'(lambda (a b) (+ a b)) '(1 2 3 4))
10
The behavior of reduce can be altered by providing an initial value. Calling
(reduce #'f '(1 2 3 4) :initial-value 100)
will compute the following:
(f (f (f (f 100 1) 2) 3) 4)
Thus, if you want to get the desired result you can use:
>>> (reduce #'+ '(1 2 3 4) :initial-value 100)
110
To add 100 to each of the numbers and then compute the sum, you can use a combination of reduce and mapcar, which is a common pattern in functional programming:
>>> (reduce #'+ (mapcar #'(lambda (a) (+ a 100)) '(1 2 3 4)))
410
So I have this line of code:
(foldl cons '() '(1 2 3 4))
And the output I get when I run it is this:
'(4 3 2 1)
Can you please explain to me why I don’t get '(1 2 3 4) instead?
I read the documentation but I am still a bit confused about how foldl works. Also if I wanted to define foldl how would I specify in Racket that the function can take a variable amount of lists as arguments?
Thanks!
Yes. By the definition of left fold, the combining function is called with the first element of the list and the accumulated result so far, and the result of that call is passed (as the new, updated accumulated result so far) to the recursive invocation of foldl with the same combining function and the rest of the list:
(foldl cons '() '(1 2 3))
=
(foldl cons (cons 1 '()) '(2 3))
=
(foldl cons (cons 2 (cons 1 '())) '(3))
=
(foldl cons (cons 3 (cons 2 (cons 1 '()))) '())
=
(cons 3 (cons 2 (cons 1 '())))
And when the list is empty, the accumulated result so far is returned as the final result.
To your second question, variadic functions in Scheme are specified with the dot . in the argument list, like so:
(define (fold-left f acc . lists)
(if (null? (first lists)) ;; assume all have same length
acc
(apply fold-left ;; recursive call
f
(apply f (append (map first lists) ;; combine first elts
(list acc))) ;; with result so far
(map rest lists)))) ;; the rests of lists
Indeed,
(fold-left (lambda (a b result)
(* result (- a b)))
1
'(1 2 3)
'(4 5 6))
returns -27.
I am working on program related to the different of dealing with even numbers in C and lisp , finished my c program but still having troubles with lisp
isprime function is defined and I need help in:
define function primesinlist that returns unique prime numbers in a lis
here what i got so far ,
any help with that please?
(defun comprimento (lista)
(if (null lista)
0
(1+ (comprimento (rest lista)))))
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number number-list)
(when (isprime number)
( number result)))
(nreverse result)))
You need to either flatten the argument before processing:
(defun primesinlist (number-list)
(let ((result ()))
(dolist (number (flatten number-list))
(when (isprime number)
(push number result)))
(delete-duplicates (nreverse result))))
or, if you want to avoid consing up a fresh list, flatten it as you go:
(defun primesinlist (number-list)
(let ((result ()))
(labels ((f (l)
(dolist (x l)
(etypecase x
(integer (when (isprime x)
(push x result)))
(list (f x))))))
(f number-list))
(delete-duplicates (nreverse result))))
To count distinct primes, take the length of the list returned by primesinlist.
Alternatively, you can use count-if:
(count-if #'isprime (delete-duplicates (flatten number-list)))
It sounds like you've already got a primality test implemented, but for sake of completeness, lets add a very simple one that just tries to divide a number by the numbers less than it up to its square root:
(defun primep (x)
"Very simple implementation of a primality test. Checks
for each n above 1 and below (sqrt x) whether n divides x.
Example:
(mapcar 'primep '(2 3 4 5 6 7 8 9 10 11 12 13))
;=> (T T NIL T NIL T NIL NIL NIL T NIL T)
"
(do ((sqrt-x (sqrt x))
(i 2 (1+ i)))
((> i sqrt-x) t)
(when (zerop (mod x i))
(return nil))))
Now, you need a way to flatten a potentially nested list of lists into a single list. When approaching this problem, I usually find it a bit easier to think in terms of trees built of cons-cells. Here's an efficient flattening function that returns a completely new list. That is, it doesn't share any structure with the original tree. That can be useful, especially if we want to modify the resulting structure later, without modifying the original input.
(defun flatten-tree (x &optional (tail '()))
"Efficiently flatten a tree of cons cells into
a list of all the non-NIL leafs of the tree. A completely
fresh list is returned.
Examples:
(flatten-tree nil) ;=> ()
(flatten-tree 1) ;=> (1)
(flatten-tree '(1 (2 (3)) (4) 5)) ;=> (1 2 3 4 5)
(flatten-tree '(1 () () 5)) ;=> (1 5)
"
(cond
((null x) tail)
((atom x) (list* x tail))
((consp x) (flatten-tree (car x)
(flatten-tree (cdr x) tail)))))
Now it's just a matter of flatting a list, removing the number that are not prime, and removing duplicates from that list. Common Lisp includes functions for doing these things, namely remove-if-not and remove-duplicates. Those are the "safe" versions that don't modify their input arguments. Since we know that the flattened list is freshly generated, we can use their (potentially) destructive counterparts, delete-if-not and delete-duplicates.
There's a caveat when you're removing duplicate elements, though. If you have a list like (1 3 5 3), there are two possible results that could be returned (assuming you keep all the other elements in order): (1 3 5) and (1 5 3). That is, you can either remove the the later duplicate or the earlier duplicate. In general, you have the question of "which one should be left behind?" Common Lisp, by default, removes the earlier duplicate and leaves the last occurrence. That behavior can be customized by the :from-end keyword argument. It can be nice to duplicate that behavior in your own API.
So, here's a function that puts all those considerations together.
(defun primes-in-tree (tree &key from-end)
"Flatten the tree, remove elements which are not prime numbers,
using FROM-END to determine whether earlier or later occurrences
are kept in the list.
Examples:
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7))
;;=> (2 3 5 7)
(primes-in-list '(2 (7 4) ((3 3) 5) 6 7) :from-end t)
;;=> (2 7 3 5)"
;; Because FLATTEN-TREE returns a fresh list, it's OK
;; to use the destructive functions DELETE-IF-NOT and
;; DELETE-DUPLICATES.
(delete-duplicates
(delete-if-not 'primep (flatten-tree list))
:from-end from-end))
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))
I'm trying to solve a problem in Scheme which is demanding me to use a nested loop or a nested recursion.
e.g. I have two lists which I have to check a condition on their Cartesian product.
What is the best way to approach these types of problems? Any pointers on how to simplify these types of functions?
I'll elaborate a bit, since my intent might not be clear enough.
A regular recursive function might look like this:
(define (factorial n)
(factorial-impl n 1))
(define (factorial-impl n t)
(if (eq? n 0)
t
(factorial-impl (- n 1) (* t n))))
Trying to write a similar function but with nested recursion introduces a new level of complexity to the code, and I was wondering what the basic pattern is for these types of functions, as it can get very ugly, very fast.
As a specific example, I'm looking for the easiest way to visit all the items in a cartesian product of two lists.
In Scheme,
The "map" function is often handy for computing one list based on another.
In fact, in scheme, map takes an "n-argument" function and "n" lists and calls the
function for each corresponding element of each list:
> (map * '(3 4 5) '(1 2 3))
(3 8 15)
But a very natural addition to this would be a "cartesian-map" function, which would call your "n-argument" function with all of the different ways of picking one element from each list. It took me a while to figure out exactly how to do it, but here you go:
; curry takes:
; * a p-argument function AND
; * n actual arguments,
; and returns a function requiring only (p-n) arguments
; where the first "n" arguments are already bound. A simple
; example
; (define add1 (curry + 1))
; (add1 3)
; => 4
; Many other languages implicitly "curry" whenever you call
; a function with not enough arguments.
(define curry
(lambda (f . c) (lambda x (apply f (append c x)))))
; take a list of tuples and an element, return another list
; with that element stitched on to each of the tuples:
; e.g.
; > (stitch '(1 2 3) 4)
; ((4 . 1) (4 . 2) (4 . 3))
(define stitch
(lambda (tuples element)
(map (curry cons element) tuples)))
; Flatten takes a list of lists and produces a single list
; e.g.
; > (flatten '((1 2) (3 4)))
; (1 2 3 4)
(define flatten
(curry apply append))
; cartesian takes two lists and returns their cartesian product
; e.g.
; > (cartesian '(1 2 3) '(4 5))
; ((1 . 4) (1 . 5) (2 . 4) (2 . 5) (3 . 4) (3 . 5))
(define cartesian
(lambda (l1 l2)
(flatten (map (curry stitch l2) l1))))
; cartesian-lists takes a list of lists
; and returns a single list containing the cartesian product of all of the lists.
; We start with a list containing a single 'nil', so that we create a
; "list of lists" rather than a list of "tuples".
; The other interesting function we use here is "fold-right" (sometimes called
; "foldr" or "reduce" in other implementations). It can be used
; to collapse a list from right to left using some binary operation and an
; initial value.
; e.g.
; (fold-right cons '() '(1 2 3))
; is equivalent to
; ((cons 1 (cons 2 (cons 3 '())))
; In our case, we have a list of lists, and our binary operation is to get the
; "cartesian product" between each list.
(define cartesian-lists
(lambda (lists)
(fold-right cartesian '(()) lists)))
; cartesian-map takes a n-argument function and n lists
; and returns a single list containing the result of calling that
; n-argument function for each combination of elements in the list:
; > (cartesian-map list '(a b) '(c d e) '(f g))
; ((a c f) (a c g) (a d f) (a d g) (a e f) (a e g) (b c f)
; (b c g) (b d f) (b d g) (b e f) (b e g))
(define cartesian-map
(lambda (f . lists)
(map (curry apply f) (cartesian-lists lists))))
Without all the comments and some more compact function definition syntax we have:
(define (curry f . c) (lambda x (apply f (append c x))))
(define (stitch tuples element)
(map (curry cons element) tuples))
(define flatten (curry apply append))
(define (cartesian l1 l2)
(flatten (map (curry stitch l2) l1)))
(define cartesian-lists (curry fold-right cartesian '(()))))
(define (cartesian-map f . lists)
(map (curry apply f) (cartesian-lists lists)))
I thought the above was reasonably "elegant"... until someone showed me the equivalent Haskell definition:
cartes f (a:b:[]) = [ f x y | x <- a , y <- b ]
cartes f (a:b:bs) = cartes f ([ f x y | x <- a , y <- b ]:bs)
2 lines!!!
I am not so confident on the efficiency of my implementation - particularly the "flatten" step was quick to write but could end up calling "append"
with a very large number of lists, which may or may not be very efficient on some Scheme
implementations.
For ultimate practicality/usefulness you would want a version that could take "lazily evaluated" lists/streams/iterator rather than fully specified lists.... a "cartesian-map-stream" function if you like, that would then return a "stream" of the results... but this depends on the context (I am thinking of the "stream" concept as introduced in SICP)... and would come for free from the Haskell version thanks to it's lazy evaluation.
In general, in Scheme, if you wanted to "break out" of the looping at some point you could also use a continuation (like throwing an exception but it is accepted practise in Scheme for control flow).
I had fun writing this!
I'm not sure I see what the problem is.
I believe the main thing you have to understand in functional programming is : build complicated functions by composing several simpler functions.
For instance, in this case:
;compute the list of the (x,y) for y in l
(define (pairs x l)
(define (aux accu x l)
(if (null? l)
accu
(let ((y (car l))
(tail (cdr l)))
(aux (cons (cons x y) accu) x tail))))
(aux '() x l))
(define (cartesian-product l m)
(define (aux accu l)
(if (null? l)
accu
(let ((x (car l))
(tail (cdr l)))
(aux (append (pairs x m) accu) tail))))
(aux '() l))
You identify the different steps: to get the cartesian product, if you "loop" over the first list, you're going to have to be able to compute the list of the (x,y), for y in the second list.
There are some good answers here already, but for simple nested functions (like your tail-recursive factorial), I prefer a named let:
(define factorial
(lambda (n)
(let factorial-impl ([n n] [t 1])
(if (eq? n 0)
t
(factorial-impl (- n 1) (* t n))))))