I've just started to play around with Lisp (Common-Lisp), here's a function that calculates the average of a list of numbers
CL-USER> (defun average (list) (/ (apply #'+ list) (length list)))
AVERAGE
CL-USER> (average '(1 2 3 4))
5/2
however if I rewrite the function like so
CL-USER> (defun average (list) (/ (+ list) (length list)))
it doesn't work since (+ '(list-of-numbers)) can't be evaluated, hence the arguement of length and the expression in the + are incompatible.
is there a way of cajoling (list) to be evaluated naturally as an expression by + and passed as data to length ? rather than using apply #'
I've tried this:
(defun average (list) (/ (+ list) (length '(list))))
but this doesn't seem to do it either !
See Common lisp: How many argument can a function take?
It would be preferable to use (reduce #'+ list) instead (apply #'+ list) because apply is subject to the limit of number of argument a that function can take.
So your average function should looks like:
(defun average (list)
(/ (reduce #'+ list)
(length list)))
BTW, the code (length '(list)) returns 1 because it returns the lenght of a list containing the symbol "list".
There is no reason not to use APPLY or, better, REDUCE. Here REDUCE is the correct function.
If you program in Lisp, most of the time you have to use a symbol, naming your operation, followed by arguments. This is the general basic expression style in Lisp. You might expect that there are shorter ways to write something like reducing a list with a function. But there isn't, in basic Lisp.
(+ (list 1 2 3 4)) is an error because + expects numbers, not a list.
If you want to sum all numbers in a list, you have to use REDUCE. This operation is also known as folding.
Summing the numbers in a list:
(reduce #'+ (list 1 2 3 4))
Another simple way is to use LOOP:
(loop for n in (list 1 2 3 4) sum n)
Writing something like (length '(list)) makes no sense, since you are quoting a list. A quoted list is treated as data and not code. Since it is constant data, the result is always 1.
One of the Lisp ways to get to short programs is to build up a vocabulary of reusable functions. One doesn't use the shortest notation, but instead one is creating reusable functions with obvious names. Thus, if we sum a lot, we write a sum function:
(defun sum (list)
(reduce #'+ list))
Then average is:
(defun average (list)
(/ (sum list) (length list)))
Related
(defun *smaller* (x y)
( if (> x y) y
x))
(defun *minimum* (lst)
(do ((numbers lst (cdr numbers))
(result (car numbers) (*smaller* result (car numbers))))
((null numbers) result)))
LISP says that variable "numbers" in "minimum" function is an unbound one although I think I've bound it to "lst". What am I missing?
Do binds in parallel. The expression for the initial value of result is (cdr numbers), and numbers is unbound there. Do* would work here.
Another approach to this problem is to try and think about it inductively.
an empty list has no minimum;
if the list is not empty, its first element is a candidate minimum:
if the rest of the list is empty it's the answer
else the candidate minumum is the smaller of the current candidate and the first element of the list, and carry on through the rest of the list.
This translates very naturally into Lisp:
(defun smaller (x y)
(if (< x y) x y))
(defun running-minimum (candidate tail)
(if (null tail)
candidate
(running-minimum (smaller candidate (first tail)) (rest tail))))
(defun minimum (list)
(when (null list)
(error "?")) ;ed is the standard text editor
(running-minimum (first list) (rest list)))
Notes
For good, if now mostly historical, reasons, CL makes no guarantees that code like this will be turned into an iterative process. Many implementations do so, but a conforming implementation need not, and even implementation which do so may not always do so, for instance in interpreted code or code compiled for ease of debugging. So a minimum function like the above is not really very idiomatic CL, and is certainly not completely safe if the code is meant to be portable.
However that is not my goal in this answer: one of the important things that you should get from learning lisp, in my opinion, is the ability to think inductively about solving problems. In other words to think about a class of problems which can be solved by starting from a simple base case and then steps which get from some general case closer to the base case, and then expressing this in code. This is a very different approach to programming than the approach which is natural in more imperative languages, and once you understand it it's a very powerful way of thinking.
As someone whose first serious language was FORTRAN (in the days when that was the correct way of writing its name even!) I think that this inductive approach is very important, and it's that which I wanted to get across here.
(defun smaller (x y)
"returns the smaller number"
(if (> x y)
y
x))
(defun minimum (list)
"returns the smallest number of a list"
(do* ((numbers list (rest numbers))
(result
(first numbers)
(if numbers
(smaller result (first numbers))
result)))
((null numbers) result)))
First of all, as pointed above, you should use do* instead of do, in order to bind the variables sequentially.
Second, you are testing (null numbers) to end the loop. However, when only one element is left to process, numbers is not nil but then it becomes (cdr numbers) which is nil. This nil value is what is being passed to *smaller* as second argument, and that's why you get the error message. To avoid this, you should test for (null (cdr numbers)) instead:
(defun *smaller* (x y)
( if (> x y) y
x))
(defun *minimum* (lst)
(do* ((numbers lst (cdr numbers))
(result (car numbers) (*smaller* result (car numbers))))
((null (cdr numbers)) result)))
This exits the loop when there is only one item left in the list.
I was reading Roots of Lisp by Paul Graham where he claims that any lisp functionality can be build with the combination of this 7 base functions: quote, atom, eq, cond, cons, car, cdr.
Question: are Lisp dialects really based solely on those functions? How can we define a 'sum' or 'plus' function using the aforementioned 7 primitive functions? e.g. Our own (+ 1 2) function
Note: I'm totally newbie to Lisp but I'm also starting to get very excited about the language. The purpose of this question is purely genuine interest
The author refers to a very famous paper written in 1960 by the Turing Award and Lisp inventor John McCarthy “Recursive Functions of Symbolic Expressions and Their Computation by Machine”, in which he defined the semantics of Lisp as a new computational formalism, equivalent in power to the Turing Machine.
In the paper (and in the Lisp 1.5 Manual) McCarthy described the interpreter for the language, that can be completely written by using only the seven primitive functions mentioned by Graham.
The language was devoted primarily to symbolic computations, and the interpreter presented in the papers concerned only those computations, without resorting to numbers or other data types different from atoms and pairs.
As Graham says in a note at page 11 of Root of Lisp, “It is possible to do arithmetic in McCarthy's 1960 Lisp by using e.g. a list of n atoms to represent the number n”, so performing a sum is simply equivalent to appending two lists.
Of course this way of doing is very inefficient: it is presented only to show the equivalence with other computational formalisms, and in the real interpreters/compilers integers are represented as usual, and have the usual operators.
as far as i remember, there was also an approach to do this using list nesting level (don't really remember, where). Starting from () as zero, (()) == 1 and so on. Then you can simply define inc as list and dec as car:
CL-USER> (defun zero? (x) (eq () x))
ZERO?
CL-USER> (zero? nil)
T
CL-USER> (zero? 1)
NIL
CL-USER> (defparameter *zero* ())
*ZERO*
CL-USER> (defun inc (x) (list x))
INC
CL-USER> (defun dec (x) (car x))
DEC
CL-USER> (defun plus (x y)
(if (zero? y) x (plus (inc x) (dec y))))
PLUS
CL-USER> (plus *zero* (inc (inc *zero*)))
((NIL))
CL-USER> (defparameter *one* (inc *zero*))
*ONE*
CL-USER> (defparameter *two* (inc *one*))
*TWO*
CL-USER> (defparameter *three* (inc *two*))
*THREE*
CL-USER> (plus *two* *three*)
(((((NIL)))))
CL-USER> (equal *two* (dec (dec (dec (plus *two* *three*)))))
T
TL; DR: No. Modern lisp systems have many more primitives than the first lisp and a new primitives are needed for each new primitive data type.
The first Lisp didn't have numbers but it was turing complete. That means it can do any computation that is possible in any other language, but it doesn't mean it would be practical to do so. Number were not hard to mimic, but calculations were slow. There are rumers today about slow arithmetic dating back pre Lisp 1.5.
When I made my first lisp interpreter I couldn't care much for numbers. It's not really an interesting aspect of an interpreter. I did however implement fibonacci as an example and this is how it looks like:
;; This is NOT Common Lisp code. It's Zozotez
(setq + (lambda (x y)
(if x (cons (car x)
(+ (cdr x) y))
y)))
(setq - (lambda (z w)
(if w (- (cdr z)
(cdr w))
z)))
(setq fibonacci
(lambda (n a1 a2)
(if n
(fibonacci (- n '(1))
a2
(+ a2 a1))
a1)))
(fibonacci '(1 1 1 1 1 1 1 1 1) () '(1))
; ==> (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)
No numbers! (1 in my language is a symbol so it needs to be quoted or else it will be evaluated like a variable)
As alternative number system I have implemented a positional system, pretty much like how we write numbers with the same rules for adding/multiplying etc. Perhaps a tad faster than lits of length n but more complex to make.
If the Lisp has closures you can do church numerals. Using the same as lambda calculus you can compute anything with just closures. You only need one primitive, lambda. (Again, not the easiest to work with)
I know that you can compare two arguments in Racket using (> 3 2) something like that. But how about three number sets? can you use something like
(define smallest-of-three
(lambda (a b c)
(cond (and (> a b) (> a c))a)))
For example?
Thank you
If you want to find the minimum of three numbers do this:
(min a b c)
As a more general solution, you could instead use foldl, like this:
(foldl (lambda (a b) ;; our comparison function
(if (< a b) a b))
a ;; our initial value
(list b c)) ;; the rest of our values
Now we can do much more complicated comparisons, since we can use any procedure that takes two arguments and only returns one of them.
Using a higher order function, we can generalize this even further:
(define (compare-multiple comp-func)
(lambda (first . rest)
(foldl comp-func ;; our comparison function
first ;; our initial value
rest))) ;; the rest of our values
;; I want to make my own min function
(define my-min (compare-multiple (lambda (a b) (if (< a b) a b)))
;; result is 1
(my-min 42 1 45)
I'm trying to write a function that can calculate GPA. Now I can do limited calculation(only 3 ),but I stuck on how to calculate more , without using loop or recursion (that's the requirement of subject) how to expend nth function? like: (nth n) ,if so ,is that mean i need to write a lambda expression? As an newbie, I maynot describe the question clearly, really need some help..
Glist is grade points Clist is credit hours.
GPA=( gradepoint *credithour + gradepoint *credithour) / ( the sum of credithour) like: (3*1+3*2+4*1)/(1+2+1)
here is my code:
(defun gpa (Glist Clist)
(format t "~3,2f~%"
(/
(+(nth 0 (mapcar #' * Glist Clist))
(nth 1 (mapcar #' * Glist Clist))
(nth 2 (mapcar #' * Glist Clist)))
(+ (nth 0 Clist)
(nth 1 Clist)
(nth 2 Clist))
);end "/"
);end "format"
(values) );end
EDIT
This seems like a good opportunity to emphasize some common (little c) Lisp ideas, so I fleshed out my answer to illustrate.
As mentioned in another answer, you could use a sum function that operates on lists (of numbers):
(defun sum (nums)
(reduce #'+ nums))
The dot product is the multiplicative sum of two (equal-length) vectors:
(defun dot-product (x y)
(sum (mapcar #'* x y)))
The function gpa is a simple combination of the two:
(defun gpa (grades credits)
(/ (dot-product grades credits) (sum credits)))
The example from the question results in the answer we expect (minus being formatted as a float):
(gpa '(3 3 4) '(1 2 1))
> 13/4
There are a few things worth mentioning from this example:
You should learn about map, reduce, and their variants and relatives. These functions are very important to Lisp and are very useful for operating on lists. map* functions generally map sequences to a sequence, and reduce usually transforms a sequence into to a single value (you can however use forms like (reduce #'cons '(1 2 3))).
This is a good example of the "bottom-up" approach to programming; by programming simple functions like sum that are often useful, you make it easy to write dot-product on top of it. Now the gpa function is a simple, readable function built on top of the other two. These are all one-liners, and all are easily readable to anyone who has a basic knowledge of CL. This is in contrast to the methodology usually applied to OOP.
There is no repetition of code. Sure, sum is used more than once, but only where it makes sense. You can do very little more to abstract the notion of a sum of the elements of a list. It's more natural in Scheme to write functions with functions, and that's a whole different topic. This is a simple example, but no two functions are doing the same thing.
If you're using nth to traverse a list, you're doing it wrong. In this case, you might want to write a summing function:
(defun sum (items)
(reduce #'+ items))
I trying to iterate through a sequence, conditionally perform an operation on each element and then collect it (but only if it matched the criteria). Here is a simplified example that works, I just want to know if this is proper or best practice in lisp:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n )
collect it)
yields
(2 4)
This works, it just looks funny to me and not so much of the when-when but because I feel like I am having to rig the condition to return what I want. I get that the anaphoric it works on the evaluation of the when but this just seems a little artificial to me. Am I missing something? I have only been a lisper for a few weeks.
Edit: Actually, I am somewhat confused when I tried to apply this. What I really want to do is this:
(loop for n in '(1 2 3 4 5)
when (when (equal (mod n 2) 0) n)
collect it
do (format t "~A" it))
but the second it seems to become unbound... how do I do this?
I don't see why you need anaphor here.
(loop for n in '(1 2 3 4 5)
when (evenp n)
collect n and
do (format t "~A" n))
Delete the keyword AND if you want the FORMAT unconditionally.