Search code examples
lispelisp

How to generate adder function in lisp?


I need to make a function that generates functions like this:

(defun add3 (val) (+ 3 val))

It should be usable like this:

(setq adder7 nil)
(fset 'adder7 (make-adder 7))
(adder7 3)
     => 10

Ideally, function make-adder should return lambdas that do not have any symbols inside other then their parameter, for example:

(make-adder 7)
      => (lambda (val) (+ 7 val))

Update

I have tried following naive realisation:

(defun make-adder (n)
  (lambda (x) (+ n x)))

But that generates a lambdda that contains free symbol (not numeric constant!) and its usage fails.

(defalias 'add1 (make-adder 1))
(add1 2)
       => Debugger error void-variable n

(let ((n 5))
  (add1 2))
       => 7

Which is not what i want to get at all.


Solution

  • Emacs

    Emacs relies on dynamic scoping by default. That's why the n symbol inside the returned lambda refers to an unbound variable. Either you toggle lexical scoping or you build a lambda form with the current value of n, as follows:

    (defun make-adder (n)
      `(lambda (x) (+ ,n x)))
    

    And then:

    (defalias  'add1 (make-adder 1))
    (add1 3)
    => 4 
    

    Common Lisp

    I originally thought the question was about Common Lisp (fset should have given me a hint), where you only have to do this:

    (defun make-adder (n)
      (lambda (x) (+ n x)))
    

    Your function takes a n and returns an anonymous function, which takes another parameter x and produces the result. But wait, make-adder is just a special case of partially applying some arguments to a function (see this question for details on the distinction between currying and partial application). The general approach to partially apply functions is:

    (defun partial (function &rest partial-args)
      (lambda (&rest args)
        (apply function (append partial-args args))))
    

    For example:

    (let ((3+ (partial #'+ 3)))
      (funcall 3+ 7))
    => 10