unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* ELisp function prototypes and local function name
@ 2011-04-06 13:36 Ted Zlatanov
  2011-04-06 15:19 ` Robert Pluim
  0 siblings, 1 reply; 11+ messages in thread
From: Ted Zlatanov @ 2011-04-06 13:36 UTC (permalink / raw)
  To: emacs-devel

I often find myself needing to know the prototype of a function I'm
calling dynamically.  Is there a way to get that?  The ELisp reference
manual doesn't have the info AFAICT.

Also I'd like to have a simple way (tracing backwards through frames is
not it, because every form and its cousin get in there) to get the
symbol of the currently running function.  So I could say:

(defun blah ()
  (format "running in function %s" __FUNCTION_NAME__))

=> "running in function blah"

(defun info (function-name)
  (format "called from function %s" function-name))

(defun blah ()
   (info __FUNCTION_NAME__))

=> "called from function blah"

Is that possible?

Thanks
Ted




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-06 13:36 ELisp function prototypes and local function name Ted Zlatanov
@ 2011-04-06 15:19 ` Robert Pluim
  2011-04-06 15:58   ` Ted Zlatanov
  0 siblings, 1 reply; 11+ messages in thread
From: Robert Pluim @ 2011-04-06 15:19 UTC (permalink / raw)
  To: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

> I often find myself needing to know the prototype of a function I'm
> calling dynamically.  Is there a way to get that?  The ELisp reference
> manual doesn't have the info AFAICT.
>

You mean like eldoc-mode?

    eldoc-mode is an interactive compiled Lisp function in `eldoc.el'.

    (eldoc-mode &optional ARG)

    Toggle ElDoc mode on or off.
    In ElDoc mode, the echo area displays information about a
    function or variable in the text where point is.  If point is
    on a documented variable, it displays the first line of that
    variable's doc string.  Otherwise it displays the argument list
    of the function called in the expression point is on.

Robert




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-06 15:19 ` Robert Pluim
@ 2011-04-06 15:58   ` Ted Zlatanov
  2011-04-07  0:25     ` Stephen J. Turnbull
  0 siblings, 1 reply; 11+ messages in thread
From: Ted Zlatanov @ 2011-04-06 15:58 UTC (permalink / raw)
  To: emacs-devel

On Wed, 06 Apr 2011 17:19:49 +0200 Robert Pluim <rpluim@gmail.com> wrote: 

RP> Ted Zlatanov <tzz@lifelogs.com> writes:
>> I often find myself needing to know the prototype of a function I'm
>> calling dynamically.  Is there a way to get that?  The ELisp reference
>> manual doesn't have the info AFAICT.

RP> You mean like eldoc-mode?

Oh yes, I didn't think to check there.  It looks like that calls the
following (example with `mapc'):

(help-split-fundoc (documentation 'mapc t) 'mapc)

That seems nasty, taking text documentation and splitting it back to get
the function arguments.  Is that really the only way to get back the
prototype?  It seems like `eldoc-get-fnsym-args-string' should be able
to do something simpler.

The interpreter knows how many arguments a function expects and signals
an error if the count is incorrect.  Can that be used instead of the
above?

Ted




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-06 15:58   ` Ted Zlatanov
@ 2011-04-07  0:25     ` Stephen J. Turnbull
  2011-04-07  2:27       ` Ted Zlatanov
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen J. Turnbull @ 2011-04-07  0:25 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > That seems nasty, taking text documentation and splitting it back to get
 > the function arguments.

function-arglist?



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07  0:25     ` Stephen J. Turnbull
@ 2011-04-07  2:27       ` Ted Zlatanov
  2011-04-07  3:27         ` Stephen J. Turnbull
  0 siblings, 1 reply; 11+ messages in thread
From: Ted Zlatanov @ 2011-04-07  2:27 UTC (permalink / raw)
  To: emacs-devel

On Thu, 07 Apr 2011 09:25:12 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> That seems nasty, taking text documentation and splitting it back to get
>> the function arguments.

SJT> function-arglist?

`help-function-arglist' is almost there...

(format "%S" (help-function-arglist 'mapc))

=> (arg1 arg2 &rest rest)

But it doesn't correspond to the advertised prototype
"(mapc FUNCTION SEQUENCE)" and loses the argument names.

It uses `subr-arity' which I can examine, but that doesn't tell me the
names of the arguments either.

Ted




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07  2:27       ` Ted Zlatanov
@ 2011-04-07  3:27         ` Stephen J. Turnbull
  2011-04-07  3:55           ` Jambunathan K
  2011-04-07 20:51           ` Ted Zlatanov
  0 siblings, 2 replies; 11+ messages in thread
From: Stephen J. Turnbull @ 2011-04-07  3:27 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > But it doesn't correspond to the advertised prototype
 > "(mapc FUNCTION SEQUENCE)" and loses the argument names.

Oh well.

(function-arglist 'mapc) => (mapc FUNCTION SEQUENCE &rest SEQUENCES)

where I live.  I think Aidan Kehoe knows most about that code
currently, but I don't know what the assignment status is.  BTW,

(flet ((foo (bar &optional baz))) (function-arglist 'foo)) => (foo BAR &optional BAZ)

works as expected too (not too surprising, I suppose).



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07  3:27         ` Stephen J. Turnbull
@ 2011-04-07  3:55           ` Jambunathan K
  2011-04-07  5:43             ` Stephen J. Turnbull
  2011-04-07 20:51           ` Ted Zlatanov
  1 sibling, 1 reply; 11+ messages in thread
From: Jambunathan K @ 2011-04-07  3:55 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Ted Zlatanov, emacs-devel


> (function-arglist 'mapc) => (mapc FUNCTION SEQUENCE &rest SEQUENCES)

Just curious, from what library function-arglist comes from? 






^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07  3:55           ` Jambunathan K
@ 2011-04-07  5:43             ` Stephen J. Turnbull
  0 siblings, 0 replies; 11+ messages in thread
From: Stephen J. Turnbull @ 2011-04-07  5:43 UTC (permalink / raw)
  To: Jambunathan K; +Cc: Ted Zlatanov, emacs-devel

Jambunathan K writes:
 > 
 > > (function-arglist 'mapc) => (mapc FUNCTION SEQUENCE &rest SEQUENCES)
 > 
 > Just curious, from what library function-arglist comes from? 

XEmacs.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07  3:27         ` Stephen J. Turnbull
  2011-04-07  3:55           ` Jambunathan K
@ 2011-04-07 20:51           ` Ted Zlatanov
  2011-04-08  4:01             ` Stephen J. Turnbull
  1 sibling, 1 reply; 11+ messages in thread
From: Ted Zlatanov @ 2011-04-07 20:51 UTC (permalink / raw)
  To: emacs-devel

On Thu, 07 Apr 2011 12:27:52 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> But it doesn't correspond to the advertised prototype
>> "(mapc FUNCTION SEQUENCE)" and loses the argument names.

SJT> Oh well.

SJT> (function-arglist 'mapc) => (mapc FUNCTION SEQUENCE &rest SEQUENCES)

SJT> where I live.  I think Aidan Kehoe knows most about that code
SJT> currently, but I don't know what the assignment status is.

Interesting.  So, disregarding the string-oriented help.el functions, in
Emacs we have `semanticdb-elisp-sym-function-arglist' which extracts the
actual function from the symbol:

#+begin_src lisp
(defun semanticdb-elisp-sym-function-arglist (sym)
  "Get the argument list for SYM.
Deal with all different forms of function.
This was snarfed out of eldoc."
  (let* ((prelim-def
	  (let ((sd (and (fboundp sym)
			 (symbol-function sym))))
	    (and (symbolp sd)
		 (condition-case err
		     (setq sd (indirect-function sym))
		   (error (setq sd nil))))
	    sd))
         (def (if (eq (car-safe prelim-def) 'macro)
                  (cdr prelim-def)
                prelim-def))
         (arglist (cond ((null def) nil)
			((byte-code-function-p def)
			 ;; This is an eieio compatibility function.
			 ;; We depend on EIEIO, so use this.
			 (eieio-compiled-function-arglist def))
                        ((eq (car-safe def) 'lambda)
                         (nth 1 def))
                        (t nil))))
    arglist))

#+end_src

but that returns nil for everything when I tried it.  Also it calls
`eieio-compiled-function-arglist' which is:

#+begin_src lisp
(eval-and-compile
;; About the above.  EIEIO must process its own code when it compiles
;; itself, thus, by eval-and-compiling outselves, we solve the problem.

;; Compatibility
(if (fboundp 'compiled-function-arglist)

    ;; XEmacs can only access a compiled functions arglist like this:
    (defalias 'eieio-compiled-function-arglist 'compiled-function-arglist)

  ;; Emacs doesn't have this function, but since FUNC is a vector, we can just
  ;; grab the appropriate element.
  (defun eieio-compiled-function-arglist (func)
    "Return the argument list for the compiled function FUNC."
    (aref func 0))

  )
#+end_src

So `eieio-compiled-function-arglist' is what I need, but `aref' doesn't
work on any functions I've tried:

(aref (indirect-function 'mapcar) 0)
=> (wrong-type-argument arrayp #<subr mapcar>)

(aref (symbol-function 'mapcar) 0)
=> (wrong-type-argument arrayp #<subr mapcar>)

;; aref still doesn't work, but nth does on lambdas
(nth 1 (lambda (a b)))
=> (a b)

It looks like the XEmacs `function-arglist' is not useful, in any case.
It depends too much on the underlying implementation.

Ted




^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-07 20:51           ` Ted Zlatanov
@ 2011-04-08  4:01             ` Stephen J. Turnbull
  2011-04-08  5:43               ` Ted Zlatanov
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen J. Turnbull @ 2011-04-08  4:01 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov writes:

 > It looks like the XEmacs `function-arglist' is not useful, in any case.
 > It depends too much on the underlying implementation.

Sure, but in XEmacs there's only one such (with three parts: one for
subrs, one for lambda lists, and one for byte-code objects).  Random
third-party stuff won't work, but it doesn't have to; random third
parties can and should use the defined API.  That's hardly a
controversial concept.

Evidently this won't work in Emacs out of the box, but surely it's
worth moving in that direction, and having third parties with "better
ideas" for basic introspection contribute them to core rather than
implement them in complex and fragile packages like eieio?



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: ELisp function prototypes and local function name
  2011-04-08  4:01             ` Stephen J. Turnbull
@ 2011-04-08  5:43               ` Ted Zlatanov
  0 siblings, 0 replies; 11+ messages in thread
From: Ted Zlatanov @ 2011-04-08  5:43 UTC (permalink / raw)
  To: emacs-devel

On Fri, 08 Apr 2011 13:01:31 +0900 "Stephen J. Turnbull" <stephen@xemacs.org> wrote: 

SJT> Ted Zlatanov writes:
>> It looks like the XEmacs `function-arglist' is not useful, in any case.
>> It depends too much on the underlying implementation.

SJT> Sure, but in XEmacs there's only one such (with three parts: one for
SJT> subrs, one for lambda lists, and one for byte-code objects).  Random
SJT> third-party stuff won't work, but it doesn't have to; random third
SJT> parties can and should use the defined API.  That's hardly a
SJT> controversial concept.

SJT> Evidently this won't work in Emacs out of the box, but surely it's
SJT> worth moving in that direction, and having third parties with "better
SJT> ideas" for basic introspection contribute them to core rather than
SJT> implement them in complex and fragile packages like eieio?

I'm OK with `function-arglist' in Emacs but I'm not the one to implement
it.  I don't know enough about the concepts.  I looked through the C
source to learn more and here's what I found:

1) my examples with `mapc' and `mapcar' were not good, since those are
built-in functions.  `help-function-arglist' is in fact the best Emacs
in-core solution and will provide the arguments when possible.  I think
the same situation is valid in XEmacs.  I simply didn't understand what
it does when I tested it on `mapc' and assumed it generally couldn't
provide the arguments.

2) Lambdas, closures, macros, and byte-compiled functions have the
arguments to build the function arglist with the argument names.  You
just need to look with `aref' or `nth' in the right place.

3) built-in functions like `mapc' don't provide their argument names,
just the number of arguments with `subr-arity'.  So their
`symbol-function' will return a #subr object and the symbol doesn't have
a function definition in its "function" slot (nor can it, since it's C
code).  

So `*function-arglist' in Emacs and XEmacs do the best they can, but it
would be nice if DEFUN could do more to provide the names of the
arguments.  It would involve either changing DEFUN, though, or trusting
the docstring as `eldoc-function-argstring' does.

I think it would make sense to put at least some of this in the ELisp
manual.  If it's already in there, I didn't see it.  It was really
educational to discover it for myself :)

Ted




^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-04-08  5:43 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-06 13:36 ELisp function prototypes and local function name Ted Zlatanov
2011-04-06 15:19 ` Robert Pluim
2011-04-06 15:58   ` Ted Zlatanov
2011-04-07  0:25     ` Stephen J. Turnbull
2011-04-07  2:27       ` Ted Zlatanov
2011-04-07  3:27         ` Stephen J. Turnbull
2011-04-07  3:55           ` Jambunathan K
2011-04-07  5:43             ` Stephen J. Turnbull
2011-04-07 20:51           ` Ted Zlatanov
2011-04-08  4:01             ` Stephen J. Turnbull
2011-04-08  5:43               ` Ted Zlatanov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).