Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Currying a function in emacs lisp

Tags:

elisp

emacs24

I have many handy functions which operate on the current word or region, and due to laziness etc. I've build them out of a template...

For example

(defun lower-camelcase-at-point-or-region ()
  "lowerCamelCaseTheCurrent dashed or snake_case word or any words in text selection."
  (interactive)
  (let (pos1 pos2 meat)
    (if (and transient-mark-mode mark-active)
        (setq pos1 (region-beginning)
              pos2 (region-end))
      (setq pos1 (car (bounds-of-thing-at-point 'symbol))
            pos2 (cdr (bounds-of-thing-at-point 'symbol))))
    (setq meat (s-lower-camel-case (buffer-substring-no-properties pos1 pos2)))
    (delete-region pos1 pos2)
    (insert  meat)    
    )
  )

Effectively this is all boiler plate, except for this line...

(setq meat (s-lower-camel-case (buffer-substring-no-properties pos1 pos2)))

Where I call s-lower-camel-case on the buffer substring. I want to reuse the at point or region stuff, but without duplicating it everywhere, (because that's stupid, and a headache to maintain.)

So what I really want to know is, can I curry functions in Emacs Lisp?

When I tried this...

(defun do-stuff-on-point-or-region ()
  "Do stuff."
  (interactive)
  (operate-on-point-or-region 's-lower-camel-case)
)

With operate-on-point-or-region defined as...:

(defun operate-on-point-or-region (fn)
  "Pick the substring at point, or region 
   and replace it with the output of fn"
  (let (pos1 pos2 meat)
    (if (and transient-mark-mode mark-active)
        (setq pos1 (region-beginning)
              pos2 (region-end))
      (setq pos1 (car (bounds-of-thing-at-point 'symbol))
            pos2 (cdr (bounds-of-thing-at-point 'symbol))))
    (setq meat (fn (buffer-substring-no-properties pos1 pos2)))
    (delete-region pos1 pos2)
    (insert  meat)    
    )
)

I get : Symbol's function definition is void: fn

Am I foolishly assuming currying is possible in Emacs Lisp!? Or am I just doing it wrong?

like image 916
ocodo Avatar asked Jan 30 '13 07:01

ocodo


2 Answers

I wish to add that in Emacs lisp currying is not possible -- function application is not currying, because it does not follow the curry's formula.

Currying means to apply a function to partial arguments, and return another function. This is not possible in Elisp, due to the dynamic scope.

EDIT: UPDATE

Now emacs-gnu has closures.

like image 151
alinsoar Avatar answered Oct 10 '22 18:10

alinsoar


First, emacs-lisp is, kinda, sorta, a 2-lisp, so the following is invalid:

(defun foo (fn)
  (fn 3)) ;; DOES NOT WORK!

Instead, you have to do the following:

(defun foo (fn)
  (funcall fn 3))

So if you replace (setq meat (fn with (setq meat (funcall fn the code ought to work.

like image 25
Vatine Avatar answered Oct 10 '22 17:10

Vatine