Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set local function definition using function (or closure) objects?

The problem with flet is that the functions bound therein must be defined inline. In other words, there's no way to do this:

(new-flet ((a (lambda (f x)
                (funcall f (* x 2))))
           (b (function-generator)))
    (a #'b 10))

I considered defining such a macro myself, but the problem is that flet seems to be the only way to set local function values. symbol-function always gets the global definition only, and function can't be used with setf. Anyone have an idea how this can be done fairly cleanly, if at all?

like image 219
nbtrap Avatar asked Aug 21 '13 15:08

nbtrap


People also ask

How do you define a local function?

Local functions are private methods of a type that are nested in another member. They can only be called from their containing member. Local functions can be declared in and called from: Methods, especially iterator methods and async methods.

What is a closure function objects?

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function's scope from an inner function.

What is __ closure __ in Python?

A closure is a function object that remembers values in enclosing scopes even if they are not present in memory. The __closure__ attribute of a closure function returns a tuple of cell objects. This cell object also has an attribute called cell_contents, which returns returns the contents of the cell.

How do you write a closure function in Python?

The criteria that must be met to create closure in Python are summarized in the following points. We must have a nested function (function inside a function). The nested function must refer to a value defined in the enclosing function. The enclosing function must return the nested function.


1 Answers

You can easily build a trampoline

(defun function-generator (x)
  (lambda (y) (* x y)))

(let ((fg (function-generator 42)))
  (flet ((a (f x) (funcall f (* x 2)))
         (b (x) (funcall fg x)))
    (a #'b 10)))

A macro implementation of new-flet with this approach is

(defmacro new-flet (bindings &body body)
  (let ((let-bindings (list))
        (flet-bindings (list))
        (args (gensym)))
    (dolist (binding bindings)
      (let ((name (gensym)))
        (push `(,name ,(second binding))
              let-bindings)
        (push `(,(first binding) (&rest ,args)
                 (apply ,name ,args))
              flet-bindings)))
    `(let ,(nreverse let-bindings)
       (flet ,(nreverse flet-bindings)
         ,@body))))

that expands in your example case as

(macroexpand-1 '(new-flet ((a (lambda (f x) (funcall f (* x 2))))
                           (b (function-generator)))
                  (a #'b 10)))

==> (LET ((#:G605 (LAMBDA (F X)
                    (FUNCALL F (* X 2))))
          (#:G606 (FUNCTION-GENERATOR)))
      (FLET ((A (&REST #:G604)
               (APPLY #:G605 #:G604))
             (B (&REST #:G604)
               (APPLY #:G606 #:G604)))
        (A #'B 10)))
like image 194
6502 Avatar answered Sep 18 '22 22:09

6502