all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* function arguments optional default values
@ 2024-07-03 21:21 Heime
  2024-07-03 21:51 ` Stephen Berman
  2024-07-06 12:43 ` Jean Louis
  0 siblings, 2 replies; 11+ messages in thread
From: Heime @ 2024-07-03 21:21 UTC (permalink / raw
  To: Heime via Users list for the GNU Emacs text editor


Does elisp support function arguments optional default values ?





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

* Re: function arguments optional default values
  2024-07-03 21:21 function arguments optional default values Heime
@ 2024-07-03 21:51 ` Stephen Berman
  2024-07-03 21:56   ` Heime
  2024-07-06 12:43 ` Jean Louis
  1 sibling, 1 reply; 11+ messages in thread
From: Stephen Berman @ 2024-07-03 21:51 UTC (permalink / raw
  To: Heime; +Cc: Heime via Users list for the GNU Emacs text editor

On Wed, 03 Jul 2024 21:21:34 +0000 Heime <heimeborgia@protonmail.com> wrote:

> Does elisp support function arguments optional default values ?

The answer is in the Elisp manual (info "(elisp) Argument List"):

     If actual arguments for the optional and rest variables are omitted,
  then they always default to ‘nil’.  There is no way for the function to
  distinguish between an explicit argument of ‘nil’ and an omitted
  argument.  However, the body of the function is free to consider ‘nil’
  an abbreviation for some other meaningful value.  This is what
  ‘substring’ does; ‘nil’ as the third argument to ‘substring’ means to
  use the length of the string supplied.
  
       Common Lisp note: Common Lisp allows the function to specify what
       default value to use when an optional argument is omitted; Emacs
       Lisp always uses ‘nil’.  Emacs Lisp does not support ‘supplied-p’
       variables that tell you whether an argument was explicitly passed.

Steve Berman



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

* Re: function arguments optional default values
  2024-07-03 21:51 ` Stephen Berman
@ 2024-07-03 21:56   ` Heime
  2024-07-03 22:04     ` Stephen Berman
  0 siblings, 1 reply; 11+ messages in thread
From: Heime @ 2024-07-03 21:56 UTC (permalink / raw
  To: Stephen Berman; +Cc: Heime via Users list for the GNU Emacs text editor






Sent with Proton Mail secure email.

On Wednesday, July 3rd, 2024 at 9:51 PM, Stephen Berman <stephen.berman@gmx.net> wrote:

> On Wed, 03 Jul 2024 21:21:34 +0000 Heime heimeborgia@protonmail.com wrote:
> 
> > Does elisp support function arguments optional default values ?
> 
> 
> The answer is in the Elisp manual (info "(elisp) Argument List"):
> 
> If actual arguments for the optional and rest variables are omitted,
> then they always default to ‘nil’. There is no way for the function to
> distinguish between an explicit argument of ‘nil’ and an omitted
> argument. However, the body of the function is free to consider ‘nil’
> an abbreviation for some other meaningful value. This is what
> ‘substring’ does; ‘nil’ as the third argument to ‘substring’ means to
> use the length of the string supplied.
> 
> Common Lisp note: Common Lisp allows the function to specify what
> default value to use when an optional argument is omitted; Emacs
> Lisp always uses ‘nil’. Emacs Lisp does not support ‘supplied-p’
> variables that tell you whether an argument was explicitly passed.
> 
> Steve Berman

So not like common lisp (var default)

I have to use UNLESS, perhaps OR. 




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

* Re: function arguments optional default values
  2024-07-03 21:56   ` Heime
@ 2024-07-03 22:04     ` Stephen Berman
  2024-07-03 22:24       ` Stephen Berman
  0 siblings, 1 reply; 11+ messages in thread
From: Stephen Berman @ 2024-07-03 22:04 UTC (permalink / raw
  To: Heime; +Cc: Heime via Users list for the GNU Emacs text editor

On Wed, 03 Jul 2024 21:56:48 +0000 Heime <heimeborgia@protonmail.com> wrote:

> Sent with Proton Mail secure email.
>
> On Wednesday, July 3rd, 2024 at 9:51 PM, Stephen Berman
> <stephen.berman@gmx.net> wrote:
>
>> On Wed, 03 Jul 2024 21:21:34 +0000 Heime heimeborgia@protonmail.com wrote:
>> 
>> > Does elisp support function arguments optional default values ?
>> 
>> 
>> The answer is in the Elisp manual (info "(elisp) Argument List"):
>> 
>> If actual arguments for the optional and rest variables are omitted,
>> then they always default to ‘nil’. There is no way for the function to
>> distinguish between an explicit argument of ‘nil’ and an omitted
>> argument. However, the body of the function is free to consider ‘nil’
>> an abbreviation for some other meaningful value. This is what
>> ‘substring’ does; ‘nil’ as the third argument to ‘substring’ means to
>> use the length of the string supplied.
>> 
>> Common Lisp note: Common Lisp allows the function to specify what
>> default value to use when an optional argument is omitted; Emacs
>> Lisp always uses ‘nil’. Emacs Lisp does not support ‘supplied-p’
>> variables that tell you whether an argument was explicitly passed.
>> 
>> Steve Berman
>
> So not like common lisp (var default)
>
> I have to use UNLESS, perhaps OR. 

Or other such alternatives, yes.

Steve Berman



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

* Re: function arguments optional default values
  2024-07-03 22:04     ` Stephen Berman
@ 2024-07-03 22:24       ` Stephen Berman
  0 siblings, 0 replies; 11+ messages in thread
From: Stephen Berman @ 2024-07-03 22:24 UTC (permalink / raw
  To: Heime; +Cc: Heime via Users list for the GNU Emacs text editor

On Thu, 04 Jul 2024 00:04:58 +0200 Stephen Berman <stephen.berman@gmx.net> wrote:

> On Wed, 03 Jul 2024 21:56:48 +0000 Heime <heimeborgia@protonmail.com> wrote:
>
>> Sent with Proton Mail secure email.
>>
>> On Wednesday, July 3rd, 2024 at 9:51 PM, Stephen Berman
>> <stephen.berman@gmx.net> wrote:
>>
>>> On Wed, 03 Jul 2024 21:21:34 +0000 Heime heimeborgia@protonmail.com wrote:
>>> 
>>> > Does elisp support function arguments optional default values ?
>>> 
>>> 
>>> The answer is in the Elisp manual (info "(elisp) Argument List"):
>>> 
>>> If actual arguments for the optional and rest variables are omitted,
>>> then they always default to ‘nil’. There is no way for the function to
>>> distinguish between an explicit argument of ‘nil’ and an omitted
>>> argument. However, the body of the function is free to consider ‘nil’
>>> an abbreviation for some other meaningful value. This is what
>>> ‘substring’ does; ‘nil’ as the third argument to ‘substring’ means to
>>> use the length of the string supplied.
>>> 
>>> Common Lisp note: Common Lisp allows the function to specify what
>>> default value to use when an optional argument is omitted; Emacs
>>> Lisp always uses ‘nil’. Emacs Lisp does not support ‘supplied-p’
>>> variables that tell you whether an argument was explicitly passed.
>>> 
>>> Steve Berman
>>
>> So not like common lisp (var default)
>>
>> I have to use UNLESS, perhaps OR. 
>
> Or other such alternatives, yes.

But you can also use cl-defun (after requiring 'cl-lib), see the CL
manual (info "(cl) Argument Lists"):

   -- Macro: cl-defun name arglist body...
       This form is identical to the regular ‘defun’ form, except that
       ARGLIST is allowed to be a full Common Lisp argument list.
   [...]
      The full form of a Common Lisp argument list is
  
       (VAR...
        &optional (VAR INITFORM SVAR)...
        &rest VAR
        &key ((KEYWORD VAR) INITFORM SVAR)...
        &aux (VAR INITFORM)...)
  
     Each of the five argument list sections is optional.  The SVAR,
  INITFORM, and KEYWORD parts are optional; if they are omitted, then
  ‘(VAR)’ may be written simply ‘VAR’.
  
     The first section consists of zero or more “required” arguments.
  These arguments must always be specified in a call to the function;
  there is no difference between Emacs Lisp and Common Lisp as far as
  required arguments are concerned.
  
     The second section consists of “optional” arguments.  These arguments
  may be specified in the function call; if they are not, INITFORM
  specifies the default value used for the argument.  (No INITFORM means
  to use ‘nil’ as the default.) [...]

Steve Berman



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

* Re: function arguments optional default values
  2024-07-03 21:21 function arguments optional default values Heime
  2024-07-03 21:51 ` Stephen Berman
@ 2024-07-06 12:43 ` Jean Louis
  2024-07-06 15:03   ` [External] : " Drew Adams
  1 sibling, 1 reply; 11+ messages in thread
From: Jean Louis @ 2024-07-06 12:43 UTC (permalink / raw
  To: Heime; +Cc: Heime via Users list for the GNU Emacs text editor

* Heime <heimeborgia@protonmail.com> [2024-07-04 00:23]:
> 
> Does elisp support function arguments optional default values ?

I solve that problem with following:

(defun my-function (arg &optional other-arg)
  (let* ((other-arg (or other-arg my-default)))
    other-arg))

-- 
Jean

Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns

✡️🛡️ Proudly standing with Israel, a nation rooted in history and culture. Let's condemn hatred and promote understanding.

In support of Richard M. Stallman
https://stallmansupport.org/



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

* RE: [External] : Re: function arguments optional default values
  2024-07-06 12:43 ` Jean Louis
@ 2024-07-06 15:03   ` Drew Adams
  2024-07-06 15:55     ` Stefan Monnier via Users list for the GNU Emacs text editor
  0 siblings, 1 reply; 11+ messages in thread
From: Drew Adams @ 2024-07-06 15:03 UTC (permalink / raw
  To: Jean Louis, Heime; +Cc: Heime via Users list for the GNU Emacs text editor

> > Does elisp support function arguments optional default values ?
> 
> I solve that problem with following:
> 
> (defun my-function (arg &optional other-arg)
>   (let* ((other-arg (or other-arg my-default)))
>     other-arg))

Simpler - no reason for another binding,
just change the value (it's a local var).

(defun my-function (arg &optional other-arg)
  (setq other-arg  (or other-arg my-default))
  ...)

or

(defun my-function (arg &optional other-arg)
  (unless other-arg (setq other-arg  my-default))
  ...)


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

* Re: [External] : Re: function arguments optional default values
  2024-07-06 15:03   ` [External] : " Drew Adams
@ 2024-07-06 15:55     ` Stefan Monnier via Users list for the GNU Emacs text editor
  2024-07-06 16:06       ` Drew Adams
  2024-07-06 21:48       ` Heime
  0 siblings, 2 replies; 11+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2024-07-06 15:55 UTC (permalink / raw
  To: help-gnu-emacs

>> > Does elisp support function arguments optional default values ?
>> I solve that problem with following:
>> (defun my-function (arg &optional other-arg)
>>   (let* ((other-arg (or other-arg my-default)))
>>     other-arg))
> Simpler - no reason for another binding,
> just change the value (it's a local var).
>
> (defun my-function (arg &optional other-arg)
>   (setq other-arg  (or other-arg my-default))
>   ...)

FWIW, assuming you're using `lexical-binding` (which you should), this
tends to result in less efficient byte-code.

The difference is marginal in most cases (and efficiency of ELisp code
is irrelevant in most cases as well), but the point is that bindings
don't "cost" as much as mutation.

Here is how this usually plays out: with (setq x (or x <default>)) the
evaluation pushes the result of (or x <default>) on the stack, does the
`setq` which consumes the value on the stack and modifies the value of
`x`, which itself lives on the stack.

With (let ((x1 (or x <default>))) ...), the beginning is the same,
pushing the result of (or x <default>) on the stack, but then the
execution of the `let` is the "free" act of keeping that value on the
stack (i.e. doing nothing), and instead of referring to the stack
element that holds `x`, we will simply refer to the stack element that
holds `x1`.
[ There is still a cost to `let` in the fact that the stack grows a bit
  more, of course, but it's usually of no consequence.  ]

Compare

    (let ((lexical-binding t))
      (disassemble '(lambda (y &optional x)
                      (setq x (or x 5)) (+ y x))))
=>
    byte code:
      doc:   ...
      args: (arg1 &optional arg2)
    0       dup
    1       goto-if-not-nil-else-pop 1
    4       constant  5
    5:1     stack-set 1
    7       stack-ref 1
    8       stack-ref 1
    9       plus
    10      return

with

    (let ((lexical-binding t))
      (disassemble '(lambda (y &optional x)
                      (let ((x1 (or x 5))) (+ y x1)))))
=>
    byte code:
      doc:   ...
      args: (arg1 &optional arg2)
    0       dup
    1       goto-if-not-nil-else-pop 1
    4       constant  5
    5:1     stack-ref 2
    6       stack-ref 1
    7       plus
    8       return

The difference is more drastic when the variable is captured by
a closure because our closure conversion is too naïve to understand that
the `setq` happens "once and forall" before we capture the variable, so
it presumes that the var may still be mutated after the closure is
constructed, which means that the closure can't just hold a copy of the
var's value but really needs to hold a "reference to the variable",
which we do by storing the variable's value inside a cons-cell:

Compare

    (let ((lexical-binding t))
      (disassemble '(lambda (&optional x)
                      (setq x (or x 5)) (lambda (y) (+ x y))))):
=>
    byte code:
      doc:   ...
      args: (&optional arg1)
    0       dup
    1       list1
    2       dup
    3       stack-ref 1
    4       car-safe
    5       goto-if-not-nil-else-pop 1
    8       constant  5
    9:1     setcar
    10      discard
    11      constant  make-closure
    12      constant  <byte-code-function>
          doc:   ...
          args: (arg1)
        0       constant  V0
        1       car-safe
        2       stack-ref 1
        3       plus
        4       return

    13      stack-ref 2
    14      call      2
    15      return

with

    (let ((lexical-binding t))
      (disassemble '(lambda (&optional x)
                      (let ((x1 (or x 5))) (lambda (y) (+ x1 y))))))
=>
    byte code:
      doc:   ...
      args: (&optional arg1)
    0       dup
    1       goto-if-not-nil-else-pop 1
    4       constant  5
    5:1     constant  make-closure
    6       constant  <byte-code-function>
          doc:   ...
          args: (arg1)
        0       constant  V0
        1       stack-ref 1
        2       plus
        3       return

    7       stack-ref 2
    8       call      2
    9       return


- Stefan




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

* RE: [External] : Re: function arguments optional default values
  2024-07-06 15:55     ` Stefan Monnier via Users list for the GNU Emacs text editor
@ 2024-07-06 16:06       ` Drew Adams
  2024-07-06 19:04         ` Stefan Monnier via Users list for the GNU Emacs text editor
  2024-07-06 21:48       ` Heime
  1 sibling, 1 reply; 11+ messages in thread
From: Drew Adams @ 2024-07-06 16:06 UTC (permalink / raw
  To: Stefan Monnier; +Cc: 'Help-Gnu-Emacs (help-gnu-emacs@gnu.org)'

[-- Attachment #1: Type: text/plain, Size: 2160 bytes --]

> >> > Does elisp support function arguments optional default values ?
> >> I solve that problem with following:
> >> (defun my-function (arg &optional other-arg)
> >>   (let* ((other-arg (or other-arg my-default)))
> >>     other-arg))
> > Simpler - no reason for another binding,
> > just change the value (it's a local var).
> >
> > (defun my-function (arg &optional other-arg)
> >   (setq other-arg  (or other-arg my-default))
> >   ...)
> 
> FWIW, assuming you're using `lexical-binding` (which you should), this
> tends to result in less efficient byte-code.
> 
> The difference is marginal in most cases (and efficiency of ELisp code
> is irrelevant in most cases as well), but the point is that bindings
> don't "cost" as much as mutation.
> 
> Here is how this usually plays out: with (setq x (or x <default>)) the
> evaluation pushes the result of (or x <default>) on the stack, does the
> `setq` which consumes the value on the stack and modifies the value of
> `x`, which itself lives on the stack.
> 
> With (let ((x1 (or x <default>))) ...), the beginning is the same,
> pushing the result of (or x <default>) on the stack, but then the
> execution of the `let` is the "free" act of keeping that value on the
> stack (i.e. doing nothing), and instead of referring to the stack
> element that holds `x`, we will simply refer to the stack element that
> holds `x1`.
> [ There is still a cost to `let` in the fact that the stack grows a bit
>   more, of course, but it's usually of no consequence.  ]
> ... 
>
> The difference is more drastic when the variable is captured by
> a closure because our closure conversion is too naïve to understand that
> the `setq` happens "once and forall" before we capture the variable, so
> it presumes that the var may still be mutated after the closure is
> constructed, which means that the closure can't just hold a copy of the
> var's value but really needs to hold a "reference to the variable",
> which we do by storing the variable's value inside a cons-cell:
> ...

Interesting!  Thanks.

I wonder what the case is with various
Common Lisp implementations.

[-- Attachment #2: winmail.dat --]
[-- Type: application/ms-tnef, Size: 15576 bytes --]

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

* Re: [External] : Re: function arguments optional default values
  2024-07-06 16:06       ` Drew Adams
@ 2024-07-06 19:04         ` Stefan Monnier via Users list for the GNU Emacs text editor
  0 siblings, 0 replies; 11+ messages in thread
From: Stefan Monnier via Users list for the GNU Emacs text editor @ 2024-07-06 19:04 UTC (permalink / raw
  To: help-gnu-emacs

> Interesting!  Thanks.
>
> I wonder what the case is with various
> Common Lisp implementations.

Good implementations probably generate about the same code.  BTW, the
same kind of thing applies in pretty much all languages, which is why
SSA is such a popular intermediate compiler representation (the
conversion to SSA form basically changes your code from the `setq`
version to the `let` version).


        Stefan




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

* Re: [External] : Re: function arguments optional default values
  2024-07-06 15:55     ` Stefan Monnier via Users list for the GNU Emacs text editor
  2024-07-06 16:06       ` Drew Adams
@ 2024-07-06 21:48       ` Heime
  1 sibling, 0 replies; 11+ messages in thread
From: Heime @ 2024-07-06 21:48 UTC (permalink / raw
  To: Stefan Monnier; +Cc: help-gnu-emacs


On Saturday, July 6th, 2024 at 3:55 PM, Stefan Monnier via Users list for the GNU Emacs text editor <help-gnu-emacs@gnu.org> wrote:

> > > > Does elisp support function arguments optional default values ?
> > > > I solve that problem with following:
> > > > (defun my-function (arg &optional other-arg)
> > > > (let* ((other-arg (or other-arg my-default)))
> > > > other-arg))
> > > > Simpler - no reason for another binding,
> > > > just change the value (it's a local var).
> > 
> > (defun my-function (arg &optional other-arg)
> > (setq other-arg (or other-arg my-default))
> > ...)
> 
> 
> FWIW, assuming you're using `lexical-binding` (which you should), this
> tends to result in less efficient byte-code.
> 
> The difference is marginal in most cases (and efficiency of ELisp code
> is irrelevant in most cases as well), but the point is that bindings
> don't "cost" as much as mutation.

Does the mutation occur with 'setq' ?  And the binding is about the use of 
'let' and 'let*' ?  Then using the 'let' version would be preferred, right?





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

end of thread, other threads:[~2024-07-06 21:48 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-03 21:21 function arguments optional default values Heime
2024-07-03 21:51 ` Stephen Berman
2024-07-03 21:56   ` Heime
2024-07-03 22:04     ` Stephen Berman
2024-07-03 22:24       ` Stephen Berman
2024-07-06 12:43 ` Jean Louis
2024-07-06 15:03   ` [External] : " Drew Adams
2024-07-06 15:55     ` Stefan Monnier via Users list for the GNU Emacs text editor
2024-07-06 16:06       ` Drew Adams
2024-07-06 19:04         ` Stefan Monnier via Users list for the GNU Emacs text editor
2024-07-06 21:48       ` Heime

Code repositories for project(s) associated with this external index

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

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.