Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

(define (average ....)) in Lisp

I'm just playing around with scheme/lisp and was thinking about how I would right my own definition of average. I'm not sure how to do some things that I think are required though.

  • define a procedure that takes an arbitrary number of arguments
  • count those arguments
  • pass the argument list to (+) to sum them together

Does someone have an example of defining average? I don't seem to know enough about LISP to form a web search that gets back the results I'm looking for.

like image 288
Eric Schoonover Avatar asked Jul 14 '10 02:07

Eric Schoonover


People also ask

How do you define a function in a Lisp?

In Lisp, a symbol such as mark-whole-buffer has code attached to it that tells the computer what to do when the function is called. This code is called the function definition and is created by evaluating a Lisp expression that starts with the symbol defun (which is an abbreviation for define function).

What are the three functions required by Lisp?

Use defun to define your own functions in LISP. Defun requires you to provide three things. The first is the name of the function, the second is a list of parameters for the function, and the third is the body of the function -- i.e. LISP instructions that tell the interpreter what to do when the function is called.

How many functions does a Lisp have?

13 Functions This chapter explains what functions are, how they accept arguments, and how to define them.


2 Answers

The definition would be a very simple one-liner, but without spoiling it, you should look into:

  • a "rest" argument -- this (define (foo . xs) ...xs...) defines foo as a function that takes any number of arguments and they're available as a list which will be the value of xs.

  • length returns the length of a list.

  • apply takes a function and a list of values and applies the function to these values.

When you get that, you can go for more:

  • see the foldl function to avoid applying a list on a potentially very big list (this can matter in some implementations where the length of the argument list is limited, but it wouldn't make much difference in Racket).

  • note that Racket has exact rationals, and you can use exact->inexact to make a more efficient floating-point version.





And the spoilers are:

  • (define (average . ns) (/ (apply + ns) (length ns)))

  • Make it require one argument: (define (average n . ns) (/ (apply + n ns) (add1 (length ns))))

  • Use foldl: (define (average n . ns) (/ (foldl + 0 (cons n ns)) (add1 (length ns))))

  • Make it use floating point: (define (average n . ns) (/ (foldl + 0.0 (cons n ns)) (add1 (length ns))))

like image 177
Eli Barzilay Avatar answered Oct 03 '22 15:10

Eli Barzilay


In Common Lisp, it looks like you can do:

(defun average (&rest args)
  (when args
    (/ (apply #'+ args) (length args))))

although I have no idea if &rest is available on all implementations of Lisp. Reference here.

Putting that code into GNU CLISP results in:

[1]> (defun average (&rest args)
       (when args
         (/ (apply #'+ args) (length args))))
AVERAGE
[2]> (average 1 2 3 4 5 6)
7/2

which is 3.5 (correct).

like image 45
paxdiablo Avatar answered Oct 03 '22 13:10

paxdiablo