views:

127

answers:

3

I'm not sure I am using ad-get-args and ad-get-arg right.

For example, the following code doesn't work.

(defun my-add (a b)
  (+ a b))
(defadvice my-add (after my-log-on activate)
  (message "my-add: %s" (ad-get-args)))
(my-add 1 2)

The last expression causes an error:

Debugger entered--Lisp error: (void-function ad-get-args).

The following doesn't work either.

(defun my-substract (a b)
  (- a b))
(defadvice my-substract (around my-log-on activate)
  (message "my-substract: %s" (ad-get-arg 0))
  (ad-do-it))
(my-substract 10 1)

The defadvice gives a warning:

Warning: `(setq ad-return-value (ad-Orig-my-substract a b))' is a malformed
    function

And the last expression gives an error:

Debugger entered--Lisp error: (invalid-function (setq ad-return-value (ad-Orig-my-substract a b)))
  (setq ad-return-value (ad-Orig-my-substract a b))()

I was trying to use defadvice to watch start-process arguments for debugging purposes and I found my way of using ad-get-arg didn't work.

Update: Answer,

From the answers it turns out that I should have used (ad-get-args 0) instead of (ad-get-args) in (defadvice my-add ..), and I should have used ad-do-it instead of (ad-do-it) in in (defadvice my-substract ..). And it's better to use trace-function.

+3  A: 

This works:

(defun my-add (a b) 
  (+ a b))

(defadvice my-add (after my-log-on activate) 
  (message "my-add: %d %d" (ad-get-arg 0) (ad-get-arg 1)))

(my-add 1 2) 

You have to consider the type of the argument you are retrieving, when passing it to the message function. I think the errors you are getting are obscured by the fact that they occur within advice. If the errors were not in advice, you'd see a clearer message, indicating a type mismatch.

When in doubt, or when you are passing an arg that is not a string to message, use (prin1-to-string arg)

like this:

(defadvice my-add (after my-log-on activate) 
  (message "my-add: %s %s"
           (prin1-to-string (ad-get-arg 0))
           (prin1-to-string (ad-get-arg 1))))
Cheeso
The expression (message "my-add: %s" (list 1 2)) runs fine.
RamyenHead
+4  A: 

You have two problems in your code. First (as you noted), you're using ad-get-args incorrectly. The docs say:

(ad-get-args <position>) will return the list of actual arguments supplied starting at <position>.

It looks like what you want is:

(defadvice my-add (after my-log-on activate)
  (message "my-add: %s" (ad-get-args 0)))

In your my-subtract, the problem is your use of ad-do-it, you have it surrounded by parentheses, it should not be. This is the correct use:

(defadvice my-substract (around my-log-on activate)
  (message "my-substract: %s" (ad-get-arg 0))
  ad-do-it)

From the docs in the advice library:

An around advice can specify where the forms of the wrapped or surrounded forms should go with the special keyword ad-do-it, which will be substituted with a progn containing the forms of the surrounded code.

The best tutorial and introduction to advice I've found is in the advice library itself (in the comments in the beginning).

M-x find-library advice RET
Trey Jackson
+3  A: 

There is no need to use ad-get-arg, you can use the same names in the body of the advice:

(defun my-add (a b)
  (+ a b))
(defadvice my-add (after my-add-log activate)
  (message "my-add: %d %d" a b))

Update:

If you just want to trace function calls for debugging purpose, emacs can generate a proper trace advice for you:

(defun my-add (a b)
  (+ a b))
(trace-function 'my-add) 
Jürgen Hötzel
I didn't know you could access the args without providing the arglist. The doc says `The optional arglist can be used to define the argument list for the sake of advice. This becomes the argument list of the combined definition that is generated in order to run the advice (see Combined Definition). Therefore, the advice expressions can use the argument variables in this list to access argument values. `
Cheeso
Of course directly using the arguments ties you to the argument names, which might change...
Trey Jackson