all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
* if-let and when-let: parallel or sequential
@ 2014-08-10  2:44 John Mastro
  2014-08-10 15:22 ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: John Mastro @ 2014-08-10  2:44 UTC (permalink / raw)
  To: emacs-devel

Hi,

I noticed that the new `if-let' and `when-let' in trunk's subr-x create
their bindings sequentially (like `let*' rather than `let'). Would there
be any interest in renaming these to `if-let*' and `when-let*', and
adding parallel-binding versions under the current names?

It's obviously a tiny matter in the scheme of things, but I do think
it's worth sticking to the existing naming convention given the history
and context.

(If this change would be welcome, and nobody beats me to it, I would be
happy to submit a patch and copyright assignment.)

Thanks

--
John Mastro



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

* Re: if-let and when-let: parallel or sequential
  2014-08-10  2:44 if-let and when-let: parallel or sequential John Mastro
@ 2014-08-10 15:22 ` Stefan Monnier
  2014-08-11 12:01   ` Bozhidar Batsov
  0 siblings, 1 reply; 11+ messages in thread
From: Stefan Monnier @ 2014-08-10 15:22 UTC (permalink / raw)
  To: John Mastro; +Cc: emacs-devel

> I noticed that the new `if-let' and `when-let' in trunk's subr-x create
> their bindings sequentially (like `let*' rather than `let'). Would there
> be any interest in renaming these to `if-let*' and `when-let*', and
> adding parallel-binding versions under the current names?

I have a hard time imagining a situation where the "parallel" version
would be useful.


        Stefan



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

* Re: if-let and when-let: parallel or sequential
  2014-08-10 15:22 ` Stefan Monnier
@ 2014-08-11 12:01   ` Bozhidar Batsov
  2014-08-11 14:42     ` Stefan Monnier
  0 siblings, 1 reply; 11+ messages in thread
From: Bozhidar Batsov @ 2014-08-11 12:01 UTC (permalink / raw)
  To: Stefan Monnier, John Mastro; +Cc: emacs-devel

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

On August 10, 2014 at 6:23:25 PM, Stefan Monnier (monnier@iro.umontreal.ca) wrote:
> I noticed that the new `if-let' and `when-let' in trunk's subr-x create  
> their bindings sequentially (like `let*' rather than `let'). Would there  
> be any interest in renaming these to `if-let*' and `when-let*', and  
> adding parallel-binding versions under the current names?  

I have a hard time imagining a situation where the "parallel" version  
would be useful.  


Stefan  


if-let and when-let don’t make much sense with more than one binding form. Other lisps (like Clojure) would raise
an exception if you try to bind more than a single form.

;; good
(if-let ((x (something)))
    …)

;; error
(if-let ((x (something))
           (y (something-else)))
    …)

I’d suggest we do the same. 

[-- Attachment #2: Type: text/html, Size: 1547 bytes --]

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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 12:01   ` Bozhidar Batsov
@ 2014-08-11 14:42     ` Stefan Monnier
  2014-08-11 16:40       ` Harald Hanche-Olsen
                         ` (3 more replies)
  0 siblings, 4 replies; 11+ messages in thread
From: Stefan Monnier @ 2014-08-11 14:42 UTC (permalink / raw)
  To: Bozhidar Batsov; +Cc: John Mastro, emacs-devel

> if-let and when-let don’t make much sense with more than one binding
> form.

Why do you think so?  If they only work for a single binding, the
benefit is really minor.  It's only when you use several bindings that
the benefit becomes more significant (the alternative being either
a very deeply nested code, or separating the var's declarations from
their initialization).


        Stefan



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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 14:42     ` Stefan Monnier
@ 2014-08-11 16:40       ` Harald Hanche-Olsen
  2014-08-11 17:49       ` Bozhidar Batsov
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 11+ messages in thread
From: Harald Hanche-Olsen @ 2014-08-11 16:40 UTC (permalink / raw)
  To: monnier; +Cc: john.b.mastro, bozhidar.batsov, emacs-devel

[Stefan Monnier <monnier@iro.umontreal.ca> (2014-08-11 14:42:19 UTC)]

> > if-let and when-let don’t make much sense with more than one binding
> > form.
> 
> Why do you think so?  If they only work for a single binding, the
> benefit is really minor.  It's only when you use several bindings that
> the benefit becomes more significant (the alternative being either
> a very deeply nested code, or separating the var's declarations from
> their initialization).

Indeed, it looks useful. But may I point out that the docstring seems
deficient? From the source code, I see that the the evaluation
short-circuits, so that evaluating

(defun foo () (insert "called foo\n") nil)
(defun bar () (insert "called bar\n") t)
(if-let ((FOO (foo))
	 (BAR (bar)))
    (insert "aye\n")
  (insert (format "nope: %s\n" BAR)))

produces

called foo
nope: nil

I can see how that is useful, but it needs to be documented better.
I'm afraid the resulting docstring may end up longer than the code,
but then so be it.

– Harald



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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 14:42     ` Stefan Monnier
  2014-08-11 16:40       ` Harald Hanche-Olsen
@ 2014-08-11 17:49       ` Bozhidar Batsov
  2014-08-11 20:55         ` Harald Hanche-Olsen
  2014-08-12  2:43       ` Lars Magne Ingebrigtsen
  2014-08-12  3:15       ` Richard Stallman
  3 siblings, 1 reply; 11+ messages in thread
From: Bozhidar Batsov @ 2014-08-11 17:49 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: John Mastro, emacs-devel

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

On August 11, 2014 at 17:42:20, Stefan Monnier (monnier@iro.umontreal.ca) wrote:
> if-let and when-let don’t make much sense with more than one binding 
> form. 

Why do you think so? If they only work for a single binding, the 
benefit is really minor. It's only when you use several bindings that 
the benefit becomes more significant (the alternative being either 
a very deeply nested code, or separating the var's declarations from 
their initialization). 


Stefan 
Practically speaking, the most common case people run into is checking whether a single object is nil 

and binding it to some local if it’s not. Binding multiple locals in such a form reduces the clarity of the code because the 

semantics are not that clear anymore - should all the forms produce non-nil or should only the first form produce non-nil? Obviously 

people can (and should) read the documentation, but I’m a huge believer in intuitive APIs. That said, I’m fine with whatever 

behavior you decide upon, as I believe those functions are valuable additions regardless.


[-- Attachment #2: Type: text/html, Size: 2429 bytes --]

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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 17:49       ` Bozhidar Batsov
@ 2014-08-11 20:55         ` Harald Hanche-Olsen
  0 siblings, 0 replies; 11+ messages in thread
From: Harald Hanche-Olsen @ 2014-08-11 20:55 UTC (permalink / raw)
  To: bozhidar.batsov; +Cc: john.b.mastro, monnier, emacs-devel

[Bozhidar Batsov <bozhidar.batsov@gmail.com> (2014-08-11 17:49:29 UTC)]

> Binding multiple locals in such a form reduces the clarity of the
> code because the  semantics are not that clear anymore - should all
> the forms produce non-nil or should only the first form produce
> non-nil?

This is a valid point, I think. The macros need better nams.
I suggest if-every-let and when-every-let to make it clearer.

There, that's enough bikeshedding for one day.
I'll go back to lurking now.

– Harald



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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 14:42     ` Stefan Monnier
  2014-08-11 16:40       ` Harald Hanche-Olsen
  2014-08-11 17:49       ` Bozhidar Batsov
@ 2014-08-12  2:43       ` Lars Magne Ingebrigtsen
  2014-08-12  3:15       ` Richard Stallman
  3 siblings, 0 replies; 11+ messages in thread
From: Lars Magne Ingebrigtsen @ 2014-08-12  2:43 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

> Why do you think so?  If they only work for a single binding, the
> benefit is really minor.  It's only when you use several bindings that
> the benefit becomes more significant (the alternative being either
> a very deeply nested code, or separating the var's declarations from
> their initialization).

I use lw:when-let all the time in Common Lisp.  It only takes a single
binding.  I find it very clear and nice -- mostly used as a kinda "early
return" thing, but without the return.

(defun foo (zot)
  (when-let (bar (compute-something zot))
    ...))

I grepped through a random directory in our code base, and out of 146
uses of when-let, 6 had nested when-lets.

There's lw:when-let*, though, which is like Emacs' when-let (i.e.,
several bindings), which is used two times.

Anyway, I think Emacs' when-let is a good addition as it is now.  Even
if the multiple-let-binding version doesn't get used much, it's nice
when you need it.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



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

* Re: if-let and when-let: parallel or sequential
  2014-08-11 14:42     ` Stefan Monnier
                         ` (2 preceding siblings ...)
  2014-08-12  2:43       ` Lars Magne Ingebrigtsen
@ 2014-08-12  3:15       ` Richard Stallman
  2014-08-12  3:30         ` John Mastro
  3 siblings, 1 reply; 11+ messages in thread
From: Richard Stallman @ 2014-08-12  3:15 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: john.b.mastro, bozhidar.batsov, emacs-devel

[[[ To any NSA and FBI agents reading my email: please consider    ]]]
[[[ whether defending the US Constitution against all enemies,     ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]

    > if-let and when-let don t make much sense with more than one binding
    > form.

    Why do you think so?  If they only work for a single binding, the
    benefit is really minor.  It's only when you use several bindings that
    the benefit becomes more significant (the alternative being either
    a very deeply nested code, or separating the var's declarations from
    their initialization).

With several sequential bindings, the alternative is

 (let* ...bindings...
   (if ...))

Thus, if-let saves just one level of nesting
even if there are several bindings.

-- 
Dr Richard Stallman
President, Free Software Foundation
51 Franklin St
Boston MA 02110
USA
www.fsf.org  www.gnu.org
Skype: No way! That's nonfree (freedom-denying) software.
  Use Ekiga or an ordinary phone call.




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

* Re: if-let and when-let: parallel or sequential
  2014-08-12  3:15       ` Richard Stallman
@ 2014-08-12  3:30         ` John Mastro
  2014-08-12 14:32           ` Elias Mårtenson
  0 siblings, 1 reply; 11+ messages in thread
From: John Mastro @ 2014-08-12  3:30 UTC (permalink / raw)
  To: emacs-devel

Richard Stallman <rms@gnu.org> wrote:
> With several sequential bindings, the alternative is
>
>  (let* ...bindings...
>    (if ...))
>
> Thus, if-let saves just one level of nesting
> even if there are several bindings.

The current implementation in trunk is actually short-circuiting. So the
equivalent to:

    (when-let ((a (foo))
               (b (bar)))
        b)

Would be:

    (let ((a (foo)))
      (when a
        (let ((b (bar)))
          b)))

And so on.

The only non-Clojure variant of these that I'm really familiar with is
Alexandria's[1]. It has both `-let' and `-let*' versions, allows
multiple bindings, and is not short circuiting. (I don't say this to
suggest we should mimic them, just to expose "where I'm coming from").

Anyway, I agree with Bozhidar that they'll be nice to have regardless of
the particulars, so I'll gracefully bow out :)

[1] http://common-lisp.net/gitweb?p=projects/alexandria/alexandria.git;a=blob;f=binding.lisp

--
john



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

* Re: if-let and when-let: parallel or sequential
  2014-08-12  3:30         ` John Mastro
@ 2014-08-12 14:32           ` Elias Mårtenson
  0 siblings, 0 replies; 11+ messages in thread
From: Elias Mårtenson @ 2014-08-12 14:32 UTC (permalink / raw)
  To: John Mastro; +Cc: emacs-devel

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

On 12 August 2014 11:30, John Mastro <john.b.mastro@gmail.com> wrote:

The only non-Clojure variant of these that I'm really familiar with is
> Alexandria's[1]. It has both `-let' and `-let*' versions, allows
> multiple bindings, and is not short circuiting. (I don't say this to
> suggest we should mimic them, just to expose "where I'm coming from").
>

Actually, in Alexandria, WHEN-LET is not short-circuiting, while WHEN-LET*
is.

Regards,
Elias

[-- Attachment #2: Type: text/html, Size: 890 bytes --]

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

end of thread, other threads:[~2014-08-12 14:32 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-08-10  2:44 if-let and when-let: parallel or sequential John Mastro
2014-08-10 15:22 ` Stefan Monnier
2014-08-11 12:01   ` Bozhidar Batsov
2014-08-11 14:42     ` Stefan Monnier
2014-08-11 16:40       ` Harald Hanche-Olsen
2014-08-11 17:49       ` Bozhidar Batsov
2014-08-11 20:55         ` Harald Hanche-Olsen
2014-08-12  2:43       ` Lars Magne Ingebrigtsen
2014-08-12  3:15       ` Richard Stallman
2014-08-12  3:30         ` John Mastro
2014-08-12 14:32           ` Elias Mårtenson

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.