0

I have code to enable Corfu text completion. I define two functions: corfu-armg loads the package, and corfu-go activates text completion. I use a wrapper function, launchport, which accepts a list of action symbols (like 'go), and calls the appropriate function (using funcall) when it processes each symbol.

Currently, corfu-go is defined as:

(defun corfu-go ()
  (setq corfu-auto t)
  (global-corfu-mode 1))

and launchport is:

(defun launchport (actm-seqr armg-fun go-fun)
  (catch 'exit
    (dolist (actm actm-seqr)
      (pcase actm
        ('armg (funcall armg-fun))
        ('go (funcall go-fun) ))) )

Finally I make a wrapper function

(defun wrapper (actm-seqr)
  (launchport actm-seqr #'corfu-armg #'corfu-go))

Suppose I now want corfu-go to take an argument (for example, myarg):

(defun corfu-go (myarg)
  (message "Arg: %s " myarg)
  (setq corfu-auto t)
  (global-corfu-mode 1))

The basic Usage of funcall is:

(funcall FUNCTION ARG1 ARG2 ...)

But I can't figure out how funcall can use ARG1. How would the launchport call be modified inside wrapper to allow corfu-go with ARG1?

10
  • "What can I do if I want corfu-go to allow arguments?" -- you would make it accept some arguments. Presumably &optional arguments. Commented Jul 27 at 13:38
  • Correct. But then how would launchport accept functions with arguments and make the arguments available for execution in the funcall clause? Commented Jul 27 at 15:08
  • Paste in the documentation of funcall so that we know you have read it. Commented Jul 27 at 15:13
  • 2
    This question is similar to: How to call a function that is the value of a variable?. If you believe it’s different, please edit the question, make it clear how it’s different and/or how the answers on that question are not helpful for your problem. Commented Jul 27 at 16:25
  • 1
    I would find it difficult to relate your suggested similarity to this instance here. Commented Jul 27 at 17:04

1 Answer 1

0

As described in the comments, you can pass along as many arguments as you need just by adding them to the argument lists of your launchport function.

That said, you should probably simplify it by making your init functions take those arguments and return lambdas instead:

(defun corfu-go (myarg)
  (lambda ()
    (message "Arg: %s " myarg)
    (setq corfu-auto t)
    (global-corfu-mode 1)))

(defun launchport (actm-seqr armg-fun go-fun)
  (catch 'exit
    (dolist (actm actm-seqr)
      (pcase actm
        ('armg (funcall armg-fun))
        ('go (funcall go-fun) ))) )

(launchport #'corfu-armg (corfu-go 42))
5
  • You illustrated my difficulty. you did not add myarg to (funcall go-fun). And no arguments were passed to (defun launchport (actm-seqr armg-fun go-fun) Commented Jul 27 at 17:01
  • I know I didn’t. I deliberately made corfu-go return a lambda, and called it before I called launchport. The result is that the lambda has already captured the argument and launchport does not need to know what the argument was. Commented Jul 27 at 17:12
  • Is this an idiomatic, natural and common approach pattern to pre-fill arguments via closure and pass around zero-argument functions? Briefly confusing for the less experienced code readers. Commented Jul 27 at 17:25
  • It is idiomatic and extremely common. But you’re doing something kinda dumb with them. It doesn’t matter though. Commented Jul 27 at 17:30
  • I will not be using the arguments in this way. Looks dumb to avoid complicating with things some would ask for me to remove. Does the approach work in all use cases? Commented Jul 27 at 17:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.