6

Coming from a C++ background, I'm trying to figure out how arguments are passed into methods in Elisp. While I acknowledge that maybe the wording could be different, I'm wondering if it is closer to the C++ idea of passing by reference or passing by value? If I alter the parameter in the method itself, will it alter the parameter that was passed in in the function call?

sds
  • 58,617
  • 29
  • 161
  • 278
JosephTLyons
  • 2,075
  • 16
  • 39

2 Answers2

10

All Lisps (Emacs Lisp, Common Lisp) pass parameters by value, always:

(defparameter x 42)  ; defconst in Emacs Lisp
(defun test (x)
  (setq x 10))
(test x)
==> 10
x
==> 42

Note, however, that some values are actually pointers (or, rather, objects with components), so a function can modify their content by side effects:

(defparameter x (list 1 2))
(defun test (x)
  (setf (first x) 42
        (second x) 24
        x 17))
(test x)
==> 17
x
==> (42 24)

PS1. Cf. When to use ' (or quote) in Lisp? -- "quoted arguments" are evaluated too: the evaluation strips the quote.

PS2. Cf. add-to-list - it accepts a symbol (variable name) and modifies its value. This only works for global dynamic variables, not for lexical variables. Not a very good idea.

sds
  • 58,617
  • 29
  • 161
  • 278
2

Actually, in Emacs Lisp, there is no such thing like passing a argument by value or by reference, not to mention pointer. But all arguments passed to function will be evaluated in advance except those have a ' prefix. Always remember When you set a variable, you always just create symbol with a value.[1]

So if you want to modify a variable's value in a function, all you need to do is modifying the value of that variable's symbol in that function.

Check my code bellow.

(defvar my-val 1)

(defun my-func-value (val)
  (setq val 2))

(defun my-func-symbol (sym)
  ;; NOTE! using set instead of setq,
  ;; casue we want symbol "my-val" be evaluated from "sym" here
  (set sym 2))

(my-func-value my-val) ; evaluate my-val before passed into function
(message "my-val: %s" my-val) ; my-val: 1

(my-func-symbol 'my-val) ; pass my-val symbol directly into function
(message "my-val: %s" my-val) ; my-val: 2

Note! If the variable is a lexically-bound variable[2], it's still true that you can modified the symbol's value but not the value in the lexical environment.

Here is the code:

(let ((my-lexical-var 1))
  (my-func-symbol 'my-lexical-var)
  ;; evaluate from lexical environment
  (message "my-lexical-var: %s" my-lexical-var) ; my-lexical-var: 1
  ;; evaluate from the symbol
  (message "symbol my-lexical-var: %s" (symbol-value 'my-lexical-var))
  ; symbol my-lexical-var: 2
Francis
  • 737
  • 1
  • 7
  • 21
  • 2
    All function arguments are always evaluated. `'` is not a prefix, but a reader macro to abbreviate the [quote form](https://stackoverflow.com/q/134887/850781), which evaluates to its second term. – sds Jan 16 '19 at 14:34
  • Yes, I know it's a quote form, but also like a prefix to that variable. Anyway you are missing the point. Did you check out my code snipe above, that's what I try to point out.@sds – Francis Jan 17 '19 at 01:28
  • Note that if the variable has *lexical* scope (which isn't the case here), then it's not true that passing the variable's symbol allows you to modify the variable's value with `set` (because the lexical value and the symbol's value are not the same thing). – phils Jan 17 '19 at 03:31