How to Create a Temporary Function in Emacs Lisp

前端 未结 3 1045
北海茫月
北海茫月 2020-12-16 10:56

I\'m making some tedious calls to a bunch of functions, but the parameters will be determined at runtime. I wrote a simple function to keep my code DRY but giving it a name

相关标签:
3条回答
  • 2020-12-16 11:11

    You can do this the ANSI Common Lisp way (though I think there are some Emacs devels that will give you nasty looks):

    (flet ((do-work (x y z)
                    (do-x x)
                    (do-y y)
                    ;; etc
                    ))
      (cond (test-1 (do-work 'a 'b 'c))
            (test-2 (do-work 'i 'j 'k))))
    

    Dunno if you'll first have to (require 'cl) (or cl-macs?) to use flet. If you want to define recursive functions you'll need to use labels IIRC.

    0 讨论(0)
  • 2020-12-16 11:17

    Like other lisps (but not Scheme), Emacs Lisp has separate namespaces for variables and functions (i.e. it is a ‘Lisp2’, not a ‘Lisp1’; see Technical Issues of Separation in Function Cells and Value Cells for the origin and meaning of these terms).

    You will need to use funcall or apply to call a lambda (or other function) that is stored in a variable.

    (cond (test-1 (funcall do-work 'a 'b 'c))
          (test-2 (funcall do-work 'i 'j 'k))
    

    Use funcall if you will always send the same number of arguments. Use apply if you need to be able to send a variable number of arguments.

    The internal mechanism is that each symbol has multiple “cells”. Which cell is used depends on where the symbol is in an evaluated form. When a symbol is the first element of an evaluated form, its “function” cell is used. In any other position, its “value” cell is used. In your code, do-work has the function in its value cell. To access it as a function you use funcall or apply. If it were in the function cell, you could call it directly by using its name as the car of an evaluated form. You can accomplish this with flet or labels from the cl package.

    0 讨论(0)
  • 2020-12-16 11:26

    Do (require 'cl) to pull in the Common Lisp package, then use flet instead of let:

    (flet ((do-work (x y z)
              (do-x x)
              (do-y y)
              ;; etc
              ))
      (cond (test-1 (do-work 'a 'b 'c))
            (test-2 (do-work 'i 'j 'k))))
    
    0 讨论(0)
提交回复
热议问题