4

Is there something like apply-partially

(apply-partially FUN &rest ARGS)

Return a function that is a partial application of FUN to ARGS.
ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with with which this
function was called.

But with the "last N arguments are fixed"

Or "all arguments are fixed except wildcard" ie:

(defun foo (a b c))
(defalias 'fix-a-c-in-foo 'apply-partially-wildcard 'foo "a valuel" '_ "c value")

_ - random symbol that means "wildcard"

JeanPierre
  • 7,323
  • 1
  • 18
  • 37
JAre
  • 175
  • 5
  • Is the `fset`-form in the following `progn` sufficient for your purpose? `(progn (defun f(a1 a2) (+ a1 a2)) (let ((a2 2)) (fset #'f2 \`(lambda (_) (f _ ,a2)))) (f2 1))` – Tobias Oct 23 '16 at 08:40
  • `subr.el` doesn't have one, but you could borrow one from here: https://github.com/magnars/dash.el#-rpartial-fn-rest-args – wvxvw Oct 23 '16 at 10:32
  • 1
    The latter sounds like `-cut` from dash.el – wasamasa Oct 23 '16 at 11:04
  • @wasamasa `-cut` looks promising. Thx! – JAre Oct 23 '16 at 18:10

2 Answers2

5

apply-partially was most useful back when Emacs did not have lexical binding, since it let you build "closures". But for your example, you don't even need a closure:

(defalias 'fix-a-c-in-foo (lambda (b) (foo "a_value" b "c_value")))

for a more general case, OTOH you do need closures, so you'll want to add -*- lexical-binding:t -*- to the first line of your file and then you can do things like:

(defun whatever (a c)
  (lambda (b) (foo a b c)))

Also, note that (lambda (x y) (foo a x y)) is implemented more efficiently than (apply-partially #'foo a).

Stefan
  • 26,154
  • 3
  • 46
  • 84
  • 1
    Why can't we use your function `whatever` with dynamic binding? For this special example I do not see a relevant difference between dynamic and lexical binding. Furthermore, Is something wrong with my answer? (I understand that I could/should use `defalias` instead of `fset`. But, beside of that...) – Tobias Oct 23 '16 at 16:28
  • Your answer is not *wrong*, but backquoting lambdas means you're generating source code at run-time, which prevents that code from being byte-compiled. – Stefan Oct 24 '16 at 00:29
  • Indeed, `mapcar` probably won't bind dynamically bind its own `a` or `c` so my example also worked in 99% of the cases with dynamic scoping. I've changed my example to really need lexical scoping. – Stefan Oct 24 '16 at 00:32
3

You have everything you need in the emacs-lisp core language with fset, lambda expressions and backticks. The following source code is an extension of your second example. The comma expression allows you to easily substitute something in a back-tick quoted lambda expression and you can assign that expression to a symbol's function-cell with fset.

(defun foo (a b c d)
  (message "a=%s b=%s c=%s d=%s" a b c d))

(let ((fix-a "a-value"))
  (fset #'fix-a-c-in-foo `(lambda (_d _b) (foo ,fix-a _b "c-value" _d)))
  )

(fix-a-c-in-foo "new-d-value" "new-b-value")

I have added one more argument to foo to have at least two fix parameters and two "template" parameters. The template parameters _b and _d are swapped which would not be possible if you just had one symbol for all such parameters. Furthermore, I've wrapped the fset (corresponding to your defalias) in my version in a let to show that we can use the value of a local variable as fixed parameter in the template. The part of the above source code that solves your problem is just:

(fset #'fix-a-c-in-foo `(lambda (_d _b) (foo ,fix-a _b "c-value" _d)))
Tobias
  • 32,569
  • 1
  • 34
  • 75