I want to create a list of functions in Scheme. As I figured out it would be something like this
(define (sqr x) (* x x))
(define (dbl x) (* 2 x))
(define (add-5 x) (+ 5 x))
(define list-of-funs '(sqr dbl add-5))
but I wonder how I can call separate functions from the list. Is there a better way to define a list of functions and call them separately?
Yes, there is a better way. You should use list, rather than quoting:
(define list-of-funs (list sqr dbl add-5))
The reason for this is that '(sqr dbl add-5) produces a list of symbols, whereas (list sqr dbl add-5) produces a list of procedure objects. You can invoke procedure objects. You cannot invoke symbols.
You can access the functions individually, by using first, second, or third (from SRFI 1) to pick elements out of the list, e.g.,
((first list-of-funs) 49) ; => 7
Or else you might decide you want to map through them, or whatever. e.g.,
(define (square-double-and-add5 x)
(map (lambda (f) (f x)) list-of-funs))
Related
So, I have a homework assignment that is asking me to make a function that counts the number of elements in a list without using recursion. (Which seems crazy to me, since Scheme is all about recursion from what I've learned so far, but that's a different discussion.) We're also not allowed to use the built-in length function.
I'm assuming this involves map somehow, but beyond that, I'm stuck, and everything I've googled for help offers a recursive solution (or uses !set, which the class hasn't taught us about and which I'm assuming is not the answer they're looking for).
If you take a rather fussy definition of recursion: a function is recursive iff it calls its own name, either directly or indirectly, then you can write things which are not 'recursive' in this very limited sense, by, really, noting that functions that don't have names can't be recursive (again: in this limited sense).
So you can start with this slightly odd function:
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l))))))
This is a function which takes another function, f as an argument and returns a function which takes a list as an argument and which:
if the list is empty will correctly compute its length;
if the list is not empty, then if (f f) is a function which will correctly compute the length of the cdr of the list, this function will compute the length of the whole list, by adding one to it.
So, wait: this function, if given another function which, when called with itself as an argument, will return a function which will compute the length of the rest of a list, will compute the length of a list. That means that this function itself is a candidate for this f function: when called with itself as an argument it should return a function which computes the length of a list. So, OK, we can wrap it up a bit to make this proposed length-computing function:
((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l)))))))
Should be a function which computes the length of a list. And we can try it:
> (((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l)))))))
'(1 2 3))
3
Well, it does seem to compute the length of the list. So we can, finally, give this thing a name to make it easier to call:
(define list-length
((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l))))))))
And now
> (list-length '())
0
> (list-length '(a b c d))
4
OK.
So, conventionally, this is done by giving the thing that applies a function to itself a name: it's the U combinator:
(define U
(λ (f) (f f)))
And then we can rewrite list-length in terms of U:
(define list-length
(U (λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((U f) (cdr l))))))))
And the question is: is list-length recursive? Well, maybe?
I am writing a function that will take a list from a user and will flatten this list into one simplified list. The function seems to only return the first item on the list and not the rest? Any suggestions on why it is doing this?
Example:
> (flatten '(a () b (c d))
(a b c d)
This is what I have so far
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t(append (flatten (first list))
(flatten (rest list)))
(t(cons (first list (flatten (rest list))))))))
The output it is giving
> (flatten '(a () b (c d)))
(NIL B (C D))
You are editing the original question with updated code, which makes it a moving target. Currently, your code is the following one, after I ask Emacs to indent it with M-q (lisp-mode):
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t (append (flatten (first list))
(flatten (rest list)))
(t (cons (first list (flatten (rest list))))))))
;; ^^^ Something is not good, why is the clause indented?
Parentheses structure the code for the computer, whereas indentation is a way to print this structure for human readers. This redundancy allows you to detect problems in source code when one does not match the other. Here, the (t cons) is not a cond clause, it is nested inside the previous clause.
Second, as said in comments, cond will go to the first clause for which the test succeeds. If you wrote (cond (t X) ...), nothing in the ... part would change the meaning of the code, which always returns X. In your code, you test as follows:
(null list) tests whether list is eq to nil.
list does not test whether list is a list. There is a predicate named listp to detect that. When you put list alone like this, you are asking whether list is a generalized true value, which is necessarily true when you previously ruled out nil (the previous clause).
The default clause (t ...) has no way to be used, because the previous test cannot fail.
Here is a skeleton:
(defun flatten (form)
(cond
((null list) ...)
((consp list) ...)
(t ...)))
Instead of consp you could write listp, but note that by definition a list is either nil or a cons cell, so consp is a little more explicit and does not overlap with a test for nil. Note also that I always test against the type of form, which is a pattern that is often found. That's why you might prefer to use typecase.
I am new to Lisp. Deletion of an item in a list by a function gets reflected outside the function but insertion doesn't. How can I do the same for insertion?
For example
(defun test (a b)
(delete 1 a)
(delete 5 b)
(append '(5) b)
(member '5 b))
(setq x '(2 3 1 4))
(setq y '(8 7 5 3))
(test x y)
;;x and y after function ends
x
(2 3 4)
y
(8 7 3)
Why doesn't append affect list y? How can I insert something into y from within the function?
Append isn't supposed to modify anything
Why doesn't append affect list y?
The first sentence of the documentation on append is (emphasis added):
append returns a new list that is the concatenation of the copies.
No one ever said that append is supposed to modify a list.
You can't change the value of a lexical binding outside its scope
How can I insert something into y from within the function?
In the most general sense, you cannot. What happens if the value of y is the empty list? There's no way with a function (as opposed to a macro) to make something like this work in Common Lisp:
(let ((list '())
(insert list 1)
l)
;=> (1)
A function cannot change the lexical binding of a variable outside its scope1, so there's no way for insert to change the value of list.
You can, of course, modify the internal structure of an object, so if the value of list is some non-empty list, then you could modify the structure of that list. The value of list wouldn't change (i.e., it would still the same cons cell), but the list represented by that cons cell would change. E.g.,
(defun prepend (list element)
(let ((x (first list)))
(setf (rest list) (list* x (rest list))
(first list) element)))
(let ((list (list 1 2)))
(prepend list 'a)
list)
;=> (a 1 2)
Save return values
In general, you need to get into the habit of saving the results of functions. Most functions won't modify their arguments, so you need to save their results. Some functions are permitted, but not required, to modify their arguments, and they don't have to modify in a predictable way, so you need to save their results too. E.g., your code could be:
(defun test (a b)
(setf a (delete 1 a))
(setf b (delete 5 b))
(setf b (append '(5) b))
(member 5 b))
(test ...)
;=> true
1 You could work around this by giving it a setter function that closed over the binding, etc. But those kind of techniques would be workarounds.
I was wondering what (cons? list-name) does. Does it just check that list-name is not a non-empty list? Is it just like the opposite of (empty? list-name)? If so, then is it not better to just say (empty? list-name) and then say else instead of cons?? For example:
(define (f list-name)
(cond
[(empty? list-name) empty]
[(cons? list-name) "do something]))
jozefg's answer is right in pointing out that (cons? x) is not the same as (not (empty? x)), in general, because there are things (e.g., numbers) that are neither cons cells nor the empty list.
However, your variable was list-name, so you may have some reason to expect that its value is, in fact a list. A list, in Scheme, is either:
the empty list; or
a cons cell whose car is the first element of a list and whose cdr is the rest of the list.
Because of this, if you're writing a function that requires a list be passed in, then it does make sense to simply check for the trivial case (the empty list) with empty?, and to assume, since you've required a list, that anything that doesn't match that case is a cons cell on which you can call cdr and cdr. This is because while
(cons? x) == (not (empty? x))
is not true of values in general, it is true for lists. That is, if you already know that lst is a list, then
(cons? lst) == (not (empty? lst))
is true. There are a number of functions that do the same thing when we're talking about lists and cons cells. E.g., empty? and null? do the same thing, but they signal a slightly different intent on the part of the programmer. Similarly, car and cdr do the same thing as first and rest, but car and cdr signal that you might be treating something as a pair of two things, whereas first and rest clearly signal the intent that you're working with a list.
Your code, since it seems to expect a list, should probably be the following, since, for a list, if it's not the empty list, it must be a cons.
(define (f lst)
(cond
[(empty? lst) empty]
[else "do something]))
More generally, the code you write should depend on what kind of input you expect. E.g., in the first case, it's fine to check for empty, and assume a cons otherwise, because you're expecting a list. In the second case, you have to check for all the different kinds of things you might see.
(define (frob-list lst)
(cond
[(empty? lst) empty] ; arg is ()
[else ...])) ; arg is (x . y)
(define (frob-object obj)
(cond
[(null? obj) ...] ; arg is ()
[(cons? obj) ...] ; arg is (x . y)
[(number? obj) ...] ; arg is r
... ; arg is ...
[else ...])) ; else ...
cons? checks whether the value is a cons cell, e.g., something that's (cons foo bar) for some foo and bar.
> (cons? 1)
#f
> (cons? '())
#f
> (cons? (list 1 2 3))
#t
> (cons? (cons 1 2))
#t
If (cons? a) is true, then it is safe to use car and cdr on a.
This isn't the opposite of empty? since empty? is true if and only if the argument is the empty list, so (empty? 1) == (cons? 1) == #f.
Sidenote: Please don't put PLEASE HELP!! or similar in your question titles, everyone here is happy to help, but it's a bit obnoxious to read. Just something to keep in mind in the future. Welcome to SO.
This is #7 of of 99 Lisp problems: transform a list, possibly holding lists as elements into a `flat' list by replacing each list with its elements (recursively). I have tried several solutions, e.g from #2680864 or from here. They all work, but I run into a problem if I am flattening a list containing a quoted element. E.g.:
> '(a 'b c)
(A 'B C)
> '(a (quote b) c)
(A 'B C)
> (flatten '(a 'b c))
(A QUOTE B C)
In the latter case I would like to get:
(A 'B C)
It seems that the internal representation of ' gets in the way for this task! SBCL, CLISP, ECL, ... they all behave the same way.
Quoted elements in a list? That usually does not make sense. Why would you have it quoted?
(a b c) is a list of three symbols. Why would you quote elements in the list? like in (a 'b c)? Why? What would be the purpose of the quote?
In Common Lisp ' is a readmacro which expands 'a into (QUOTE A). Since this is a normal list, a typical flatten operation will collect the symbols QUOTE and A into the flat list. This is because a flatten function typicall checks whether something is an atom or not. If you don't want this, your flatten function needs to check if something is an atom or a two-element list with QUOTE as its first symbol.
But as I said above, the default usage is just to flatten symbols, since quoted symbols are usually not useful inside a list. You need to extend the flatten function otherwise.
For example:
(defun flatten (l &key (test #'atom))
(cond ((null l) nil)
((funcall test l) (list l))
(t (loop for a in l nconc (flatten a :test test)))))
CL-USER > (flatten '(a (('b) c) ('d) )
:test (lambda (item)
(or (atom item)
(and (eq (first item) 'quote)
(null (cddr item))))))
(A (QUOTE B) C (QUOTE D))