* if-let/if-let*/and-let/..
@ 2018-02-11 23:51 Stefan Monnier
[not found] ` <87wozijhpk.fsf@web.de>
0 siblings, 1 reply; 47+ messages in thread
From: Stefan Monnier @ 2018-02-11 23:51 UTC (permalink / raw)
To: emacs-devel
This if/when/and-let/let* business looks pretty messy to me:
- why do we have and-let* ? According to its docstring the only case
when it differs from when-let* is when body is nil, but in that case
you're better off moving the last binding to the body (and use
when-let*).
- why do we have foo-let vs foo-let* ? The fact that each stp is depend
on the previous means that a "parallel let" semantics doesn't make
much sense, so only the "let*" semantics makes sense and we don't want
to have both of them.
Currently, almost all packages outside of Emacs which use those things
suffer from annoying obsolescence warnings which don't seem to be worth
the trouble.
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
[not found] ` <jwv8tbyyx4x.fsf-monnier+emacs@gnu.org>
@ 2018-02-12 17:32 ` Stefan Monnier
2018-02-13 18:23 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Stefan Monnier @ 2018-02-12 17:32 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mark Oteiza, npostavs, emacs-devel
Resending with correct Cc. Sorry 'bout that and thanks Mark for the
heads up,
Stefan
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>>> This if/when/and-let/let* business looks pretty messy to me:
>>>
>>> - why do we have and-let* ? According to its docstring the only case
>>> when it differs from when-let* is when body is nil, but in that case
>>> you're better off moving the last binding to the body (and use
>>> when-let*).
>>
>> The discussion about this was in bug#28254. The original and-let*
>> version was much more different from `when-let*', but AFAIR Noam vetoed
>> against this version, so they got more similar in the end.
>
> Is it worth keeping this "more similar" result at all?
>
>> The original reason was that we decided that the names without "*" are
>> quite confusing and we wanted to get rid of them in the future.
>
> Is the benefit of slightly reducing confusion (I really find it hard to
> believe the confusion is serious, since the dependencies between the
> different steps would make it rather inconvenient to provide a real
> "parallel-let" semantics) worth the burden of those
> compatibility/obsolescence issues (I'd also mention the confusing
> aspect of having an extra * for a construct that doesn't exist without
> a *, even though traditionally the * is used to mark an "alternative"
> definition, as in list*, mapcar*, ...).
>
> Another question is why aren't when-let and when-let* aliases of
> each other? Currently we have 5 variants (2 of which are deprecated)
> each with very slightly different semantics.
>
>
> Stefan
>
>
> PS: I'm also biased against when-let* because I find this * ugly.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-12 17:32 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-13 18:23 ` Michael Heerdegen
2018-02-13 19:24 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-13 19:31 ` if-let/if-let*/and-let/ Mark Oteiza
0 siblings, 2 replies; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-13 18:23 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, emacs-devel, npostavs
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
> >>> - why do we have and-let* ? According to its docstring the only
> >>> case when it differs from when-let* is when body is nil, but in
> >>> that case you're better off moving the last binding to the body
> >>> (and use when-let*).
> >>
> >> The discussion about this was in bug#28254. The original and-let*
> >> version was much more different from `when-let*', but AFAIR Noam
> >> vetoed against this version, so they got more similar in the end.
> >
> > Is it worth keeping this "more similar" result at all?
I think it is worth it, for the same reason we keep having `when' though
we have `if' or `and': to make code better readable and its intention
better understandable.
> >> The original reason was that we decided that the names without "*" are
> >> quite confusing and we wanted to get rid of them in the future.
> >
> > Is the benefit of slightly reducing confusion (I really find it hard to
> > believe the confusion is serious, since the dependencies between the
> > different steps would make it rather inconvenient to provide a real
> > "parallel-let" semantics)
In my case, my brain always told me that the * name is the canonical
one, so I always got errors. I think nobody thinks through what you
said when writing code.
> > worth the burden of those compatibility/obsolescence issues (I'd
> > also mention the confusing aspect of having an extra * for a
> > construct that doesn't exist without a *, even though traditionally
> > the * is used to mark an "alternative" definition, as in list*,
> > mapcar*, ...).
I think when using `when-let' etc. more people have the analogy to `let'
in mind than mapcar* vs. mapcar, but I see your point: the obsolescence
issue is very unpleasant.
> > Another question is why aren't when-let and when-let* aliases of
> > each other? Currently we have 5 variants (2 of which are
> > deprecated) each with very slightly different semantics.
That makes no sense, indeed. Would keeping both names as aliases be ok
to you?
> PS: I'm also biased against when-let* because I find this * ugly.
So, what are your suggestions?
And @Mark: What do you think about Stefan's points?
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 18:23 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-13 19:24 ` Stefan Monnier
2018-02-13 20:52 ` if-let/if-let*/and-let/ John Wiegley
2018-02-13 19:31 ` if-let/if-let*/and-let/ Mark Oteiza
1 sibling, 1 reply; 47+ messages in thread
From: Stefan Monnier @ 2018-02-13 19:24 UTC (permalink / raw)
To: emacs-devel
> I think it is worth it, for the same reason we keep having `when' though
> we have `if' or `and': to make code better readable and its intention
> better understandable.
I was OK with having if-let and when-let, yes.
I think more than 2 alternative semantics is hard to justify, tho:
I don't even see a single use of and-let (other than in tests).
>> > Another question is why aren't when-let and when-let* aliases of
>> > each other? Currently we have 5 variants (2 of which are
>> > deprecated) each with very slightly different semantics.
> That makes no sense, indeed. Would keeping both names as aliases be ok
> to you?
Yes.
> So, what are your suggestions?
I think we should drop `and-let` and make if/when-let aliases of if/when-let*
(or the reverse). I think it could still be done on emacs-26.
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 18:23 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-13 19:24 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-13 19:31 ` Mark Oteiza
2018-02-13 20:49 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-13 20:54 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 2 replies; 47+ messages in thread
From: Mark Oteiza @ 2018-02-13 19:31 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: emacs-devel, Stefan Monnier, npostavs
On 13/02/18 at 07:23pm, Michael Heerdegen wrote:
> Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>
> > >>> - why do we have and-let* ? According to its docstring the only
> > >>> case when it differs from when-let* is when body is nil, but in
> > >>> that case you're better off moving the last binding to the body
> > >>> (and use when-let*).
> > >>
> > >> The discussion about this was in bug#28254. The original and-let*
> > >> version was much more different from `when-let*', but AFAIR Noam
> > >> vetoed against this version, so they got more similar in the end.
> > >
> > > Is it worth keeping this "more similar" result at all?
>
> I think it is worth it, for the same reason we keep having `when' though
> we have `if' or `and': to make code better readable and its intention
> better understandable.
They ended up being so similar because we bestowed all the goodies from
and-let* onto the other two macros. I proposed code adding and-let* so
naturally I'm all about keeping it.
> > >> The original reason was that we decided that the names without "*" are
> > >> quite confusing and we wanted to get rid of them in the future.
> > >
> > > Is the benefit of slightly reducing confusion (I really find it hard to
> > > believe the confusion is serious, since the dependencies between the
> > > different steps would make it rather inconvenient to provide a real
> > > "parallel-let" semantics)
>
> In my case, my brain always told me that the * name is the canonical
> one, so I always got errors. I think nobody thinks through what you
> said when writing code.
The macros are based on let*, so why wouldn't their names reflect it? (I
see the below reasoning about original vs alternate)
I forget from the discussion of when these were introduced, but I think
the other language's when-let from which the single binding special case
was assimilated ONLY allowed a single binding, and so wouldn't have
needed let* anyways.
> > > worth the burden of those compatibility/obsolescence issues (I'd
> > > also mention the confusing aspect of having an extra * for a
> > > construct that doesn't exist without a *, even though traditionally
> > > the * is used to mark an "alternative" definition, as in list*,
> > > mapcar*, ...).
>
> I think when using `when-let' etc. more people have the analogy to `let'
> in mind than mapcar* vs. mapcar, but I see your point: the obsolescence
> issue is very unpleasant.
>
> > > Another question is why aren't when-let and when-let* aliases of
> > > each other? Currently we have 5 variants (2 of which are
> > > deprecated) each with very slightly different semantics.
>
> That makes no sense, indeed. Would keeping both names as aliases be ok
> to you?
If we are ok with breaking code that depends on the special case (SYMBOL
VALUEFORM) semantics that the original if-let and when-let had, that is:
(when-let (a 1) a)
then we could just make them aliases--they are separate from the
{if,when}-let* simply to avoid breaking code.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 19:31 ` if-let/if-let*/and-let/ Mark Oteiza
@ 2018-02-13 20:49 ` Stefan Monnier
2018-02-14 0:07 ` if-let/if-let*/and-let/ Mark Oteiza
2018-02-13 20:54 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 1 reply; 47+ messages in thread
From: Stefan Monnier @ 2018-02-13 20:49 UTC (permalink / raw)
To: Mark Oteiza; +Cc: Michael Heerdegen, emacs-devel, npostavs
> If we are ok with breaking code that depends on the special case (SYMBOL
> VALUEFORM) semantics that the original if-let and when-let had, that is:
>
> (when-let (a 1) a)
That's a part I didn't understand: why did we drop support for this in
when-let*?
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 19:24 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-13 20:52 ` John Wiegley
0 siblings, 0 replies; 47+ messages in thread
From: John Wiegley @ 2018-02-13 20:52 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
>>>>> "SM" == Stefan Monnier <monnier@iro.umontreal.ca> writes:
SM> I think we should drop `and-let` and make if/when-let aliases of
SM> if/when-let* (or the reverse). I think it could still be done on emacs-26.
Sounds reasonable to me.
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 19:31 ` if-let/if-let*/and-let/ Mark Oteiza
2018-02-13 20:49 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-13 20:54 ` Michael Heerdegen
2018-02-13 21:57 ` if-let/if-let*/and-let/ Eric Abrahamsen
1 sibling, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-13 20:54 UTC (permalink / raw)
To: Mark Oteiza; +Cc: npostavs, Stefan Monnier, emacs-devel
Mark Oteiza <mvoteiza@udel.edu> writes:
> If we are ok with breaking code that depends on the special case (SYMBOL
> VALUEFORM) semantics that the original if-let and when-let had, that is:
>
> (when-let (a 1) a)
>
> then we could just make them aliases--they are separate from the
> {if,when}-let* simply to avoid breaking code.
Ah, that was the reason. I'm not sure whether breaking this would be
less bad than what we have currently.
BTW, these forms don't seem to be used inside Emacs, but two files in
Gnu Elpa use them:
#+begin_src emacs-lisp
;;; *** /home/micha/software/elpa/packages/ebdb/ebdb.el (1 match)
;;;; Line 5461
(cl-defmethod ebdb-record-search ((record ebdb-record)
(_type (subclass ebdb-field-notes))
(regexp string))
(if-let (notes (slot-value record 'notes))
(ebdb-field-search notes regexp)))
;;; *** /home/micha/software/elpa/packages/yasnippet/yasnippet-debug.el (8 matches)
;;;; Line 76
(when-let (color-ov (gethash location yas-debug-live-indicators)) ..4..)
;;;; Line 173
(when-let (overlay (yas--snippet-control-overlay snippet)) ..4..)
;;;; Line 177
(when-let (active-field (yas--snippet-active-field snippet)) ..7..)
;;;; Line 184
(when-let (exit (yas--snippet-exit snippet)) ..4..)
;;;; Line 298
(when-let (mode (cl-member "-M:" options :test #'string-prefix-p)) ..2..)
;;;; Line 300
(when-let (mode (cl-member "-M." options :test #'string-prefix-p)) ..4..)
;;;; Line 306
(when-let (snippet-file (cl-member "-S:" options :test #'string-prefix-p)) ..13..)
;;;; Line 321
(when-let (verbosity (car (or (member "-v" options) (member "-vv" options)))) ..4..)
#+end_src
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 20:54 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-13 21:57 ` Eric Abrahamsen
2018-02-13 22:39 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Eric Abrahamsen @ 2018-02-13 21:57 UTC (permalink / raw)
To: emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Mark Oteiza <mvoteiza@udel.edu> writes:
>
>> If we are ok with breaking code that depends on the special case (SYMBOL
>> VALUEFORM) semantics that the original if-let and when-let had, that is:
>>
>> (when-let (a 1) a)
>>
>> then we could just make them aliases--they are separate from the
>> {if,when}-let* simply to avoid breaking code.
>
> Ah, that was the reason. I'm not sure whether breaking this would be
> less bad than what we have currently.
>
> BTW, these forms don't seem to be used inside Emacs, but two files in
> Gnu Elpa use them:
>
> #+begin_src emacs-lisp
> ;;; *** /home/micha/software/elpa/packages/ebdb/ebdb.el (1 match)
>
> ;;;; Line 5461
> (cl-defmethod ebdb-record-search ((record ebdb-record)
> (_type (subclass ebdb-field-notes))
> (regexp string))
> (if-let (notes (slot-value record 'notes))
> (ebdb-field-search notes regexp)))
Are you sure about this? In both my github repo and in the installed
version of EBDB, I've gone back to a pokey old when-inside-a-let,
precisely because of all the funkiness surrounding these macros. IIRC, I
treated the above use of `if-let' as a bug when I noticed it. I thought
I got rid of it quite a while ago...?
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 21:57 ` if-let/if-let*/and-let/ Eric Abrahamsen
@ 2018-02-13 22:39 ` Michael Heerdegen
2018-02-13 22:51 ` if-let/if-let*/and-let/ Eric Abrahamsen
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-13 22:39 UTC (permalink / raw)
To: Eric Abrahamsen; +Cc: emacs-devel
Eric Abrahamsen <eric@ericabrahamsen.net> writes:
> Are you sure about this? In both my github repo and in the installed
> version of EBDB, I've gone back to a pokey old when-inside-a-let,
> precisely because of all the funkiness surrounding these macros. IIRC, I
> treated the above use of `if-let' as a bug when I noticed it. I thought
> I got rid of it quite a while ago...?
EDBD is in an external branch, right? Then I apparently searched in an
very old version of that branch. I thought my workflow with Magit would
fetch also external branches, but that doesn't seem to be right.
Sorry about the confusion,
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 22:39 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-13 22:51 ` Eric Abrahamsen
0 siblings, 0 replies; 47+ messages in thread
From: Eric Abrahamsen @ 2018-02-13 22:51 UTC (permalink / raw)
To: emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Eric Abrahamsen <eric@ericabrahamsen.net> writes:
>
>> Are you sure about this? In both my github repo and in the installed
>> version of EBDB, I've gone back to a pokey old when-inside-a-let,
>> precisely because of all the funkiness surrounding these macros. IIRC, I
>> treated the above use of `if-let' as a bug when I noticed it. I thought
>> I got rid of it quite a while ago...?
>
> EDBD is in an external branch, right? Then I apparently searched in an
> very old version of that branch. I thought my workflow with Magit would
> fetch also external branches, but that doesn't seem to be right.
>
> Sorry about the confusion,
That's a relief, you had me nervous for a second there :)
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-13 20:49 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-14 0:07 ` Mark Oteiza
2018-02-14 23:07 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Mark Oteiza @ 2018-02-14 0:07 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Michael Heerdegen, npostavs, emacs-devel
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>> If we are ok with breaking code that depends on the special case
>> (SYMBOL
>> VALUEFORM) semantics that the original if-let and when-let had, that
>> is:
>>
>> (when-let (a 1) a)
>
> That's a part I didn't understand: why did we drop support for this in
> when-let*?
Discussed in #28254:
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28254#38
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-14 0:07 ` if-let/if-let*/and-let/ Mark Oteiza
@ 2018-02-14 23:07 ` Michael Heerdegen
2018-02-15 3:37 ` if-let/if-let*/and-let/ Stefan Monnier
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-14 23:07 UTC (permalink / raw)
To: Mark Oteiza; +Cc: emacs-devel, Stefan Monnier, npostavs
Mark Oteiza <mvoteiza@udel.edu> writes:
> Discussed in #28254:
> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28254#38
Which means, I think, it had been buggy or inconsistent. See this
example in the report's discussion, Stefan:
#+begin_src emacs-lisp
(if-let* (x) "dogs" "cats") => "cats"
(if-let* (x (y 2)) "dogs" "cats") => (void-function y)
(if-let* (x (y 1) (z 2)) "dogs" "cats") => "cats"
#+end_src
Do you remember any details, Mark?
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-14 23:07 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-15 3:37 ` Stefan Monnier
2018-02-21 4:26 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-22 1:08 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 2 replies; 47+ messages in thread
From: Stefan Monnier @ 2018-02-15 3:37 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mark Oteiza, emacs-devel, npostavs
> (if-let* (x) "dogs" "cats") => "cats"
We could detect this case and signal an error during macro-expansion for
it (the special (VAR EXP) form should be (VAR EXP) and not just
`(VAR)`).
> (if-let* (x (y 2)) "dogs" "cats") => (void-function y)
This is right. If you presume that `if-let` only takes the same syntax
as `let`, then the above would be equivalent to
(if-let* ((x nil) (y 2)) "dogs" "cats")
which is just a complicated way to write
"cats"
so it's rather unlikely that a user would write that on purpose.
It's much more likely that he meant
(if-let* (x (y 2)) "dogs" "cats")
to be treated as
(if-let* ((x (y 2))) "dogs" "cats")
which will indeed correctly give you the (void-function y).
> (if-let* (x (y 1) (z 2)) "dogs" "cats") => "cats"
Same as the first case above, we could/should detect this case during
macro-expansion since this is not of the form (VAR EXP) but (VAR EXP EXP).
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-15 3:37 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-21 4:26 ` Michael Heerdegen
2018-02-22 1:08 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 0 replies; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-21 4:26 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, npostavs, emacs-devel
Hi Stefan,
I agreed to everything. I'll prepare a patch for emacs-26.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-15 3:37 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-21 4:26 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-22 1:08 ` Michael Heerdegen
2018-02-22 5:10 ` if-let/if-let*/and-let/ Stefan Monnier
1 sibling, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-22 1:08 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, npostavs, emacs-devel
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
> > (if-let* (x (y 1) (z 2)) "dogs" "cats") => "cats"
>
> Same as the first case above, we could/should detect this case during
> macro-expansion since this is not of the form (VAR EXP) but (VAR EXP
> EXP).
I understand now what the problem is.
Mark had implemented and-let* as in srfi-2:
https://srfi.schemers.org/srfi-2/srfi-2.html
(scroll to "Specification")
which interprets a (bound) symbol in the binding spec as a boolean.
Noam then had asked for making if-let's binding SPEC compatible with
that of the new and-let* - but the single-binding case of those was
incompatible with that, so foo-let* were born breaking with the single
binding case, and at that time we wanted to introduce these names
anyway. foo-let were then reimplemented based on foo-let* but made
still supporting the single-binding case for backward compatibility as
special case, and also marked obsolete to not have two versions of the
very same thing.
That treatment of a single SYMBOL in the SPEC is redundant AFAIK (in the
SRFI2 and in master) since it can also be written as (SYMBOL). If we
sacrifice the absolute rigid compatibility with SRFI2, we can treat the
binding SPEC, as Stefan suggested, like
#+begin_src emacs-lisp
(pcase spec
(`(,(pred symbolp) . ,rest)
(pcase rest
(`(,_) (cl-callf list spec)) ;the single binding syntax
(_ (signal 'error (list "if-let: Bad binding spec" spec))))))
#+end_src
being slightly backward incompatible since
| 4612b2a2b37026bef5a9b8e92878a15dabb9b261
| Parent: c87331a1c0 Merge branch 'master' of git.savannah.gnu.org:/srv/git/emacs
| Merged: emacs-25
| Containing: emacs-26 master
| Follows: emacs-25.1 (130022)
|
| Implement and-let*
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-22 1:08 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-02-22 5:10 ` Stefan Monnier
2018-02-22 7:55 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Stefan Monnier @ 2018-02-22 5:10 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Mark Oteiza, npostavs, emacs-devel
> Mark had implemented and-let* as in srfi-2:
> https://srfi.schemers.org/srfi-2/srfi-2.html
> (scroll to "Specification")
> which interprets a (bound) symbol in the binding spec as a boolean.
OK, that makes sense.
> That treatment of a single SYMBOL in the SPEC is redundant AFAIK (in the
> SRFI2 and in master) since it can also be written as (SYMBOL).
The (SYMBOL) syntax is not very attractive, tho (to me, it really gives
me the impression that I'm binding SYMBOL to nil). As a programmer, I'd
much rather write SYMBOL for that and if that's not an option, then
I'd use (_ SYMBOL) to make it clear that SYMBOL is just evaluated and
not bound.
> (pcase spec
> (`(,(pred symbolp) . ,rest)
> (pcase rest
> (`(,_) (cl-callf list spec)) ;the single binding syntax
> (_ (signal 'error (list "if-let: Bad binding spec" spec))))))
So you'd then support the SYMBOL syntax as a shorthand for (_ SYMBOL)
*except* as the first element of the spec?
That would be OK for me (tho the above error message might like to
suggest the use of (_ SYMBOL) to circumvent this restriction).
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-22 5:10 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-02-22 7:55 ` Michael Heerdegen
2018-03-03 14:12 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-02-22 7:55 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, emacs-devel, npostavs
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
> > (pcase spec
> > (`(,(pred symbolp) . ,rest)
> > (pcase rest
> > (`(,_) (cl-callf list spec)) ;the single binding syntax
> > (_ (signal 'error (list "if-let: Bad binding spec" spec))))))
>
> So you'd then support the SYMBOL syntax as a shorthand for (_ SYMBOL)
> *except* as the first element of the spec?
Hmm - maybe it would be even better to make `foo-let*' just do what
`foo-let' does currently - only handle a SPEC (SYMBOL EXPR) specially,
and don't signal any errors.
I also had the idea of moving `foo-let' back and limit it to the single
binding case, which would IMHO be more consistent - but that would break
stuff in Gnu Elpa, so I guess it's not an option.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-02-22 7:55 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-03 14:12 ` Michael Heerdegen
2018-03-06 15:03 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-03 14:12 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, emacs-devel, npostavs
[-- Attachment #1: Type: text/plain, Size: 530 bytes --]
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Hmm - maybe it would be even better to make `foo-let*' just do what
> `foo-let' does currently - only handle a SPEC (SYMBOL EXPR) specially,
> and don't signal any errors.
Sorry for the delay. I've done that now - the new patch is attached.
In a subsequent commit we need to add to the documentation that an
element of the VARLIST can also be a symbol - that case is currently
undocumented. This is independent from this issue here, so I'll do it
in a separate commit.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Define-if-let-and-derivatives-as-aliases-of-if-let.patch --]
[-- Type: text/x-diff, Size: 24989 bytes --]
From 69d1375dd100f46100c0bbf2cff42846a8cdd139 Mon Sep 17 00:00:00 2001
From: Michael Heerdegen <michael_heerdegen@web.de>
Date: Wed, 21 Feb 2018 11:15:37 +0100
Subject: [PATCH] Define if-let* and derivatives as aliases of if-let
This commit reverts declaring `if-let' and `when-let' obsolete in
favor of the new `if-let* and `when-let*' versions because of the
compiler warning mess (Bug#30039). Instead we make foo-let and
foo-let* aliases. The old single-tuple variable spec case is still
supported for backward compatibility.
* lisp/emacs-lisp/subr-x.el (if-let, when-let): Don't declare
obsolete. Tweak edebug specs.
(and-let): Renamed from `and-let*' for compatibility with the names
`if-let' and `when-let'.
(if-let*, when-let*, and-let*): Define as aliases of `if-let',
`when-let' and `and-let'.
* test/lisp/emacs-lisp/subr-x-tests.el (if-let-single-tuple-case-test)
(when-let-single-tuple-case-test): New tests for the single-binding
tuple case.
In the whole file, prefer the names without "*".
---
etc/NEWS | 10 +-
lisp/emacs-lisp/subr-x.el | 55 ++++-----
test/lisp/emacs-lisp/subr-x-tests.el | 232 ++++++++++++++++++-----------------
3 files changed, 148 insertions(+), 149 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index eded00e655..c88bec5a56 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1301,12 +1301,10 @@ current buffer or the self-insertion takes place within a comment.
** The alist 'ucs-names' is now a hash table.
---
-** 'if-let' and 'when-let' are subsumed by 'if-let*' and 'when-let*'.
-The incumbent 'if-let' and 'when-let' are now marked obsolete.
-'if-let*' and 'when-let*' do not accept the single tuple special case.
-New macro 'and-let*' is an implementation of the Scheme SRFI-2 syntax
-of the same name. 'if-let*' and 'when-let*' now accept the same
-binding syntax as 'and-let*'.
+** The new macro 'and-let' is an implementation of the Scheme SRFI-2
+syntax. 'if-let' and 'when-let' now also accept the same binding
+syntax as 'and-let'. 'if-let*', 'when-let*' and 'and-let*' are new
+aliases for 'if-let', 'when-let' and 'and-let'.
---
** 'C-up', 'C-down', 'C-left' and 'C-right' are now defined in term
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 21dba377bf..b2d7f0dec4 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -121,7 +121,7 @@ internal--build-bindings
binding))
bindings)))
-(defmacro if-let* (varlist then &rest else)
+(defmacro if-let (varlist then &rest else)
"Bind variables according to VARLIST and eval THEN or ELSE.
Each binding is evaluated in turn, and evaluation stops if a
binding value is nil. If all are non-nil, the value of THEN is
@@ -131,10 +131,18 @@ if-let*
SYMBOL to the value of VALUEFORM. An element can additionally
be of the form (VALUEFORM), which is evaluated and checked for
nil; i.e. SYMBOL can be omitted if only the test result is of
-interest."
+interest.
+
+As a special case, a VARLIST of the form (SYMBOL SOMETHING) is
+treated like ((SYMBOL SOMETHING))."
(declare (indent 2)
- (debug ((&rest [&or symbolp (symbolp form) (form)])
+ (debug ([&or (symbolp form)
+ (&rest [&or symbolp (symbolp form) (form)])]
form body)))
+ (pcase varlist
+ (`(,(pred symbolp) ,_)
+ ;; the single-tuple syntax case, for backward compatibility
+ (cl-callf list varlist)))
(if varlist
`(let* ,(setq varlist (internal--build-bindings varlist))
(if ,(caar (last varlist))
@@ -142,23 +150,23 @@ if-let*
,@else))
`(let* () ,then)))
-(defmacro when-let* (varlist &rest body)
+(defmacro when-let (varlist &rest body)
"Bind variables according to VARLIST and conditionally eval BODY.
Each binding is evaluated in turn, and evaluation stops if a
binding value is nil. If all are non-nil, the value of the last
form in BODY is returned.
-VARLIST is the same as in `if-let*'."
- (declare (indent 1) (debug if-let*))
- (list 'if-let* varlist (macroexp-progn body)))
+VARLIST is the same as in `if-let'."
+ (declare (indent 1) (debug ([&or (symbolp form)
+ (&rest [&or symbolp (symbolp form) (form)])]
+ body)))
+ (list 'if-let varlist (macroexp-progn body)))
-(defmacro and-let* (varlist &rest body)
+(defmacro and-let (varlist &rest body)
"Bind variables according to VARLIST and conditionally eval BODY.
-Like `when-let*', except if BODY is empty and all the bindings
+Like `when-let', except if BODY is empty and all the bindings
are non-nil, then the result is non-nil."
- (declare (indent 1)
- (debug ((&rest [&or symbolp (symbolp form) (form)])
- body)))
+ (declare (indent 1) (debug when-let))
(let (res)
(if varlist
`(let* ,(setq varlist (internal--build-bindings varlist))
@@ -166,26 +174,9 @@ and-let*
,@(or body `(,res))))
`(let* () ,@(or body '(t))))))
-(defmacro if-let (spec then &rest else)
- "Bind variables according to SPEC and eval THEN or ELSE.
-Like `if-let*' except SPEC can have the form (SYMBOL VALUEFORM)."
- (declare (indent 2)
- (debug ([&or (&rest [&or symbolp (symbolp form) (form)])
- (symbolp form)]
- form body))
- (obsolete "use `if-let*' instead." "26.1"))
- (when (and (<= (length spec) 2)
- (not (listp (car spec))))
- ;; Adjust the single binding case
- (setq spec (list spec)))
- (list 'if-let* spec then (macroexp-progn else)))
-
-(defmacro when-let (spec &rest body)
- "Bind variables according to SPEC and conditionally eval BODY.
-Like `when-let*' except SPEC can have the form (SYMBOL VALUEFORM)."
- (declare (indent 1) (debug if-let)
- (obsolete "use `when-let*' instead." "26.1"))
- (list 'if-let spec (macroexp-progn body)))
+(defalias 'if-let* #'if-let)
+(defalias 'when-let* #'when-let)
+(defalias 'and-let* #'and-let)
(defsubst hash-table-empty-p (hash-table)
"Check whether HASH-TABLE is empty (has 0 elements)."
diff --git a/test/lisp/emacs-lisp/subr-x-tests.el b/test/lisp/emacs-lisp/subr-x-tests.el
index c9618f3c37..a361718c9e 100644
--- a/test/lisp/emacs-lisp/subr-x-tests.el
+++ b/test/lisp/emacs-lisp/subr-x-tests.el
@@ -28,13 +28,13 @@
(require 'subr-x)
\f
-;; `if-let*' tests
+;; `if-let' tests
-(ert-deftest subr-x-test-if-let*-single-binding-expansion ()
+(ert-deftest subr-x-test-if-let-single-binding-expansion ()
"Test single bindings are expanded properly."
(should (equal
(macroexpand
- '(if-let* ((a 1))
+ '(if-let ((a 1))
(- a)
"no"))
'(let* ((a (and t 1)))
@@ -43,7 +43,7 @@
"no"))))
(should (equal
(macroexpand
- '(if-let* (a)
+ '(if-let (a)
(- a)
"no"))
'(let* ((a (and t a)))
@@ -51,11 +51,11 @@
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let*-single-symbol-expansion ()
+(ert-deftest subr-x-test-if-let-single-symbol-expansion ()
"Test single symbol bindings are expanded properly."
(should (equal
(macroexpand
- '(if-let* (a)
+ '(if-let (a)
(- a)
"no"))
'(let* ((a (and t a)))
@@ -64,7 +64,7 @@
"no"))))
(should (equal
(macroexpand
- '(if-let* (a b c)
+ '(if-let (a b c)
(- a)
"no"))
'(let* ((a (and t a))
@@ -75,7 +75,7 @@
"no"))))
(should (equal
(macroexpand
- '(if-let* (a (b 2) c)
+ '(if-let (a (b 2) c)
(- a)
"no"))
'(let* ((a (and t a))
@@ -85,11 +85,11 @@
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let*-nil-related-expansion ()
+(ert-deftest subr-x-test-if-let-nil-related-expansion ()
"Test nil is processed properly."
(should (equal
(macroexpand
- '(if-let* (nil)
+ '(if-let (nil)
(- a)
"no"))
'(let* ((nil (and t nil)))
@@ -98,7 +98,7 @@
"no"))))
(should (equal
(macroexpand
- '(if-let* ((a 1) nil (b 2))
+ '(if-let ((a 1) nil (b 2))
(- a)
"no"))
'(let* ((a (and t 1))
@@ -108,106 +108,106 @@
(- a)
"no")))))
-(ert-deftest subr-x-test-if-let*-malformed-binding ()
+(ert-deftest subr-x-test-if-let-malformed-binding ()
"Test malformed bindings trigger errors."
(should-error (macroexpand
- '(if-let* (_ (a 1 1) (b 2) (c 3) d)
+ '(if-let (_ (a 1 1) (b 2) (c 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let* (_ (a 1) (b 2 2) (c 3) d)
+ '(if-let (_ (a 1) (b 2 2) (c 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let* (_ (a 1) (b 2) (c 3 3) d)
+ '(if-let (_ (a 1) (b 2) (c 3 3) d)
(- a)
"no"))
:type 'error)
(should-error (macroexpand
- '(if-let* ((a 1 1))
+ '(if-let ((a 1 1))
(- a)
"no"))
:type 'error))
-(ert-deftest subr-x-test-if-let*-true ()
+(ert-deftest subr-x-test-if-let-true ()
"Test `if-let' with truthy bindings."
(should (equal
- (if-let* ((a 1))
+ (if-let ((a 1))
a
"no")
1))
(should (equal
- (if-let* ((a 1) (b 2) (c 3))
+ (if-let ((a 1) (b 2) (c 3))
(list a b c)
"no")
(list 1 2 3))))
-(ert-deftest subr-x-test-if-let*-false ()
+(ert-deftest subr-x-test-if-let-false ()
"Test `if-let' with falsie bindings."
(should (equal
- (if-let* ((a nil))
+ (if-let ((a nil))
(list a b c)
"no")
"no"))
(should (equal
- (if-let* ((a nil) (b 2) (c 3))
+ (if-let ((a nil) (b 2) (c 3))
(list a b c)
"no")
"no"))
(should (equal
- (if-let* ((a 1) (b nil) (c 3))
+ (if-let ((a 1) (b nil) (c 3))
(list a b c)
"no")
"no"))
(should (equal
- (if-let* ((a 1) (b 2) (c nil))
+ (if-let ((a 1) (b 2) (c nil))
(list a b c)
"no")
"no"))
(should (equal
(let (z)
- (if-let* (z (a 1) (b 2) (c 3))
+ (if-let (z (a 1) (b 2) (c 3))
(list a b c)
"no"))
"no"))
(should (equal
(let (d)
- (if-let* ((a 1) (b 2) (c 3) d)
+ (if-let ((a 1) (b 2) (c 3) d)
(list a b c)
"no"))
"no")))
-(ert-deftest subr-x-test-if-let*-bound-references ()
+(ert-deftest subr-x-test-if-let-bound-references ()
"Test `if-let' bindings can refer to already bound symbols."
(should (equal
- (if-let* ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
+ (if-let ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
(list a b c)
"no")
(list 1 2 3))))
-(ert-deftest subr-x-test-if-let*-and-laziness-is-preserved ()
+(ert-deftest subr-x-test-if-let-and-laziness-is-preserved ()
"Test `if-let' respects `and' laziness."
(let (a-called b-called c-called)
(should (equal
- (if-let* ((a nil)
- (b (setq b-called t))
- (c (setq c-called t)))
+ (if-let ((a nil)
+ (b (setq b-called t))
+ (c (setq c-called t)))
"yes"
(list a-called b-called c-called))
(list nil nil nil))))
(let (a-called b-called c-called)
(should (equal
- (if-let* ((a (setq a-called t))
- (b nil)
- (c (setq c-called t)))
+ (if-let ((a (setq a-called t))
+ (b nil)
+ (c (setq c-called t)))
"yes"
(list a-called b-called c-called))
(list t nil nil))))
(let (a-called b-called c-called)
(should (equal
- (if-let* ((a (setq a-called t))
+ (if-let ((a (setq a-called t))
(b (setq b-called t))
(c nil)
(d (setq c-called t)))
@@ -215,14 +215,19 @@
(list a-called b-called c-called))
(list t t nil)))))
+(defun if-let-single-tuple-case-test ()
+ "Test the BINDING-SPEC == (SYMBOL SOMETHING) case."
+ (should (equal (if-let (a 1) (1+ a)) 2))
+ (should (equal (let ((b 2)) (if-let (a b) a)) 2)))
+
\f
-;; `when-let*' tests
+;; `when-let' tests
-(ert-deftest subr-x-test-when-let*-body-expansion ()
+(ert-deftest subr-x-test-when-let-body-expansion ()
"Test body allows for multiple sexps wrapping with progn."
(should (equal
(macroexpand
- '(when-let* ((a 1))
+ '(when-let ((a 1))
(message "opposite")
(- a)))
'(let* ((a (and t 1)))
@@ -231,18 +236,18 @@
(message "opposite")
(- a)))))))
-(ert-deftest subr-x-test-when-let*-single-symbol-expansion ()
+(ert-deftest subr-x-test-when-let-single-symbol-expansion ()
"Test single symbol bindings are expanded properly."
(should (equal
(macroexpand
- '(when-let* (a)
+ '(when-let (a)
(- a)))
'(let* ((a (and t a)))
(if a
(- a)))))
(should (equal
(macroexpand
- '(when-let* (a b c)
+ '(when-let (a b c)
(- a)))
'(let* ((a (and t a))
(b (and a b))
@@ -251,7 +256,7 @@
(- a)))))
(should (equal
(macroexpand
- '(when-let* (a (b 2) c)
+ '(when-let (a (b 2) c)
(- a)))
'(let* ((a (and t a))
(b (and a 2))
@@ -259,18 +264,18 @@
(if c
(- a))))))
-(ert-deftest subr-x-test-when-let*-nil-related-expansion ()
+(ert-deftest subr-x-test-when-let-nil-related-expansion ()
"Test nil is processed properly."
(should (equal
(macroexpand
- '(when-let* (nil)
+ '(when-let (nil)
(- a)))
'(let* ((nil (and t nil)))
(if nil
(- a)))))
(should (equal
(macroexpand
- '(when-let* ((a 1) nil (b 2))
+ '(when-let ((a 1) nil (b 2))
(- a)))
'(let* ((a (and t 1))
(nil (and a nil))
@@ -278,173 +283,178 @@
(if b
(- a))))))
-(ert-deftest subr-x-test-when-let*-malformed-binding ()
+(ert-deftest subr-x-test-when-let-malformed-binding ()
"Test malformed bindings trigger errors."
(should-error (macroexpand
- '(when-let* (_ (a 1 1) (b 2) (c 3) d)
+ '(when-let (_ (a 1 1) (b 2) (c 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let* (_ (a 1) (b 2 2) (c 3) d)
+ '(when-let (_ (a 1) (b 2 2) (c 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let* (_ (a 1) (b 2) (c 3 3) d)
+ '(when-let (_ (a 1) (b 2) (c 3 3) d)
(- a)))
:type 'error)
(should-error (macroexpand
- '(when-let* ((a 1 1))
+ '(when-let ((a 1 1))
(- a)))
:type 'error))
-(ert-deftest subr-x-test-when-let*-true ()
+(ert-deftest subr-x-test-when-let-true ()
"Test `when-let' with truthy bindings."
(should (equal
- (when-let* ((a 1))
+ (when-let ((a 1))
a)
1))
(should (equal
- (when-let* ((a 1) (b 2) (c 3))
+ (when-let ((a 1) (b 2) (c 3))
(list a b c))
(list 1 2 3))))
-(ert-deftest subr-x-test-when-let*-false ()
+(ert-deftest subr-x-test-when-let-false ()
"Test `when-let' with falsie bindings."
(should (equal
- (when-let* ((a nil))
+ (when-let ((a nil))
(list a b c)
"no")
nil))
(should (equal
- (when-let* ((a nil) (b 2) (c 3))
+ (when-let ((a nil) (b 2) (c 3))
(list a b c)
"no")
nil))
(should (equal
- (when-let* ((a 1) (b nil) (c 3))
+ (when-let ((a 1) (b nil) (c 3))
(list a b c)
"no")
nil))
(should (equal
- (when-let* ((a 1) (b 2) (c nil))
+ (when-let ((a 1) (b 2) (c nil))
(list a b c)
"no")
nil))
(should (equal
(let (z)
- (when-let* (z (a 1) (b 2) (c 3))
+ (when-let (z (a 1) (b 2) (c 3))
(list a b c)
"no"))
nil))
(should (equal
(let (d)
- (when-let* ((a 1) (b 2) (c 3) d)
+ (when-let ((a 1) (b 2) (c 3) d)
(list a b c)
"no"))
nil)))
-(ert-deftest subr-x-test-when-let*-bound-references ()
+(ert-deftest subr-x-test-when-let-bound-references ()
"Test `when-let' bindings can refer to already bound symbols."
(should (equal
- (when-let* ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
+ (when-let ((a (1+ 0)) (b (1+ a)) (c (1+ b)))
(list a b c))
(list 1 2 3))))
-(ert-deftest subr-x-test-when-let*-and-laziness-is-preserved ()
+(ert-deftest subr-x-test-when-let-and-laziness-is-preserved ()
"Test `when-let' respects `and' laziness."
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let* ((a nil)
- (b (setq b-called t))
- (c (setq c-called t)))
+ (when-let ((a nil)
+ (b (setq b-called t))
+ (c (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list nil nil nil))))
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let* ((a (setq a-called t))
- (b nil)
- (c (setq c-called t)))
+ (when-let ((a (setq a-called t))
+ (b nil)
+ (c (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list t nil nil))))
(let (a-called b-called c-called)
(should (equal
(progn
- (when-let* ((a (setq a-called t))
- (b (setq b-called t))
- (c nil)
- (d (setq c-called t)))
+ (when-let ((a (setq a-called t))
+ (b (setq b-called t))
+ (c nil)
+ (d (setq c-called t)))
"yes")
(list a-called b-called c-called))
(list t t nil)))))
+(defun when-let-single-tuple-case-test ()
+ "Test the BINDING-SPEC == (SYMBOL SOMETHING) case."
+ (should (equal (when-let (a 1) (1+ a)) 2))
+ (should (equal (let ((b 2)) (when-let (a b) a)) 2)))
+
\f
-;; `and-let*' tests
+;; `and-let' tests
;; Adapted from the Guile tests
;; https://git.savannah.gnu.org/cgit/guile.git/tree/test-suite/tests/srfi-2.test
-(ert-deftest subr-x-and-let*-test-empty-varlist ()
- (should (equal 1 (and-let* () 1)))
- (should (equal 2 (and-let* () 1 2)))
- (should (equal t (and-let* ()))))
+(ert-deftest subr-x-and-let-test-empty-varlist ()
+ (should (equal 1 (and-let () 1)))
+ (should (equal 2 (and-let () 1 2)))
+ (should (equal t (and-let ()))))
-(ert-deftest subr-x-and-let*-test-group-1 ()
- (should (equal nil (let ((x nil)) (and-let* (x)))))
- (should (equal 1 (let ((x 1)) (and-let* (x)))))
- (should (equal nil (and-let* ((x nil)))))
- (should (equal 1 (and-let* ((x 1)))))
+(ert-deftest subr-x-and-let-test-group-1 ()
+ (should (equal nil (let ((x nil)) (and-let (x)))))
+ (should (equal 1 (let ((x 1)) (and-let (x)))))
+ (should (equal nil (and-let ((x nil)))))
+ (should (equal 1 (and-let ((x 1)))))
;; The error doesn't trigger when compiled: the compiler will give
;; a warning and then drop the erroneous code. Therefore, use
;; `eval' to avoid compilation.
- (should-error (eval '(and-let* (nil (x 1))) lexical-binding)
+ (should-error (eval '(and-let (nil (x 1))) lexical-binding)
:type 'setting-constant)
- (should (equal nil (and-let* ((nil) (x 1)))))
- (should-error (eval '(and-let* (2 (x 1))) lexical-binding)
+ (should (equal nil (and-let ((nil) (x 1)))))
+ (should-error (eval '(and-let (2 (x 1))) lexical-binding)
:type 'wrong-type-argument)
- (should (equal 1 (and-let* ((2) (x 1)))))
- (should (equal 2 (and-let* ((x 1) (2)))))
- (should (equal nil (let ((x nil)) (and-let* (x) x))))
- (should (equal "" (let ((x "")) (and-let* (x) x))))
- (should (equal "" (let ((x "")) (and-let* (x)))))
- (should (equal 2 (let ((x 1)) (and-let* (x) (+ x 1)))))
- (should (equal nil (let ((x nil)) (and-let* (x) (+ x 1)))))
- (should (equal 2 (let ((x 1)) (and-let* (((> x 0))) (+ x 1)))))
- (should (equal t (let ((x 1)) (and-let* (((> x 0)))))))
- (should (equal nil (let ((x 0)) (and-let* (((> x 0))) (+ x 1)))))
+ (should (equal 1 (and-let ((2) (x 1)))))
+ (should (equal 2 (and-let ((x 1) (2)))))
+ (should (equal nil (let ((x nil)) (and-let (x) x))))
+ (should (equal "" (let ((x "")) (and-let (x) x))))
+ (should (equal "" (let ((x "")) (and-let (x)))))
+ (should (equal 2 (let ((x 1)) (and-let (x) (+ x 1)))))
+ (should (equal nil (let ((x nil)) (and-let (x) (+ x 1)))))
+ (should (equal 2 (let ((x 1)) (and-let (((> x 0))) (+ x 1)))))
+ (should (equal t (let ((x 1)) (and-let (((> x 0)))))))
+ (should (equal nil (let ((x 0)) (and-let (((> x 0))) (+ x 1)))))
(should (equal 3
- (let ((x 1)) (and-let* (((> x 0)) (x (+ x 1))) (+ x 1))))))
+ (let ((x 1)) (and-let (((> x 0)) (x (+ x 1))) (+ x 1))))))
-(ert-deftest subr-x-and-let*-test-rebind ()
+(ert-deftest subr-x-and-let-test-rebind ()
(should
(equal 4
(let ((x 1))
- (and-let* (((> x 0)) (x (+ x 1)) (x (+ x 1))) (+ x 1))))))
+ (and-let (((> x 0)) (x (+ x 1)) (x (+ x 1))) (+ x 1))))))
-(ert-deftest subr-x-and-let*-test-group-2 ()
+(ert-deftest subr-x-and-let-test-group-2 ()
(should
- (equal 2 (let ((x 1)) (and-let* (x ((> x 0))) (+ x 1)))))
+ (equal 2 (let ((x 1)) (and-let (x ((> x 0))) (+ x 1)))))
(should
- (equal 2 (let ((x 1)) (and-let* (((progn x)) ((> x 0))) (+ x 1)))))
- (should (equal nil (let ((x 0)) (and-let* (x ((> x 0))) (+ x 1)))))
- (should (equal nil (let ((x nil)) (and-let* (x ((> x 0))) (+ x 1)))))
+ (equal 2 (let ((x 1)) (and-let (((progn x)) ((> x 0))) (+ x 1)))))
+ (should (equal nil (let ((x 0)) (and-let (x ((> x 0))) (+ x 1)))))
+ (should (equal nil (let ((x nil)) (and-let (x ((> x 0))) (+ x 1)))))
(should
- (equal nil (let ((x nil)) (and-let* (((progn x)) ((> x 0))) (+ x 1))))))
+ (equal nil (let ((x nil)) (and-let (((progn x)) ((> x 0))) (+ x 1))))))
-(ert-deftest subr-x-and-let*-test-group-3 ()
+(ert-deftest subr-x-and-let-test-group-3 ()
(should
- (equal nil (let ((x 1)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (equal nil (let ((x 1)) (and-let (x (y (- x 1)) ((> y 0))) (/ x y)))))
(should
- (equal nil (let ((x 0)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (equal nil (let ((x 0)) (and-let (x (y (- x 1)) ((> y 0))) (/ x y)))))
(should
(equal nil
- (let ((x nil)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y)))))
+ (let ((x nil)) (and-let (x (y (- x 1)) ((> y 0))) (/ x y)))))
(should
(equal (/ 3.0 2)
- (let ((x 3.0)) (and-let* (x (y (- x 1)) ((> y 0))) (/ x y))))))
+ (let ((x 3.0)) (and-let (x (y (- x 1)) ((> y 0))) (/ x y))))))
\f
--
2.16.1
[-- Attachment #3: Type: text/plain, Size: 21 bytes --]
Regards,
Michael.
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-03 14:12 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-06 15:03 ` Michael Heerdegen
2018-03-06 15:31 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-06 15:03 UTC (permalink / raw)
To: Stefan Monnier; +Cc: Mark Oteiza, npostavs, emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Sorry for the delay. I've done that now - the new patch is attached.
Installed.
> In a subsequent commit we need to add to the documentation that an
> element of the VARLIST can also be a symbol - that case is currently
> undocumented. This is independent from this issue here, so I'll do it
> in a separate commit.
@Mark: do you remember why we don't document this case? Just an
oversight?
Thanks,
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 15:03 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-06 15:31 ` Michael Heerdegen
2018-03-06 15:34 ` if-let/if-let*/and-let/ John Wiegley
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-06 15:31 UTC (permalink / raw)
To: emacs-devel
Michael Heerdegen <michael_heerdegen@web.de> writes:
> Installed.
Hmm, I hope it is ok that I installed it into emacs-26...I think it is
important to include it in the release.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 15:31 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-06 15:34 ` John Wiegley
2018-03-06 16:03 ` if-let/if-let*/and-let/ Stefan Monnier
2018-03-06 16:04 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 2 replies; 47+ messages in thread
From: John Wiegley @ 2018-03-06 15:34 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: emacs-devel
>>>>> "MH" == Michael Heerdegen <michael_heerdegen@web.de> writes:
MH> Hmm, I hope it is ok that I installed it into emacs-26...I think it is
MH> important to include it in the release.
Unless Eli is OK with it, I'm not. We're into RC1 territory now (or in a few
days), which means absolutely no non-critical changes.
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 15:34 ` if-let/if-let*/and-let/ John Wiegley
@ 2018-03-06 16:03 ` Stefan Monnier
2018-03-06 17:40 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-06 17:40 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-06 16:04 ` if-let/if-let*/and-let/ Eli Zaretskii
1 sibling, 2 replies; 47+ messages in thread
From: Stefan Monnier @ 2018-03-06 16:03 UTC (permalink / raw)
To: emacs-devel
> MH> Hmm, I hope it is ok that I installed it into emacs-26...I think it is
> MH> important to include it in the release.
> Unless Eli is OK with it, I'm not. We're into RC1 territory now (or in a few
> days), which means absolutely no non-critical changes.
FWIW, I think delaying the change to after Emacs-26.1 would make the
change pointless, since the whole purpose is to avoid the abrupt change
in Emacs-26.1.
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 15:34 ` if-let/if-let*/and-let/ John Wiegley
2018-03-06 16:03 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-03-06 16:04 ` Eli Zaretskii
2018-03-06 17:35 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-06 16:04 UTC (permalink / raw)
To: John Wiegley; +Cc: michael_heerdegen, emacs-devel
> From: "John Wiegley" <johnw@gnu.org>
> Date: Tue, 06 Mar 2018 07:34:07 -0800
> Cc: emacs-devel@gnu.org
>
> >>>>> "MH" == Michael Heerdegen <michael_heerdegen@web.de> writes:
>
> MH> Hmm, I hope it is ok that I installed it into emacs-26...I think it is
> MH> important to include it in the release.
>
> Unless Eli is OK with it, I'm not. We're into RC1 territory now (or in a few
> days), which means absolutely no non-critical changes.
Indeed, I don't understand why this was pushed to the release branch.
It's too late for such changes. Please revert.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 16:04 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-06 17:35 ` Michael Heerdegen
0 siblings, 0 replies; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-06 17:35 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: John Wiegley, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> Indeed, I don't understand why this was pushed to the release branch.
If someone had commented on the commit, we could have discussed it.
Sure, I also didn't ask. My bad.
> It's too late for such changes. Please revert.
Done for now.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 16:03 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-03-06 17:40 ` Michael Heerdegen
2018-03-06 19:12 ` if-let/if-let*/and-let/ Radon Rosborough
2018-03-06 17:40 ` if-let/if-let*/and-let/ Eli Zaretskii
1 sibling, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-06 17:40 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
Stefan Monnier <monnier@iro.umontreal.ca> writes:
> FWIW, I think delaying the change to after Emacs-26.1 would make the
> change pointless, since the whole purpose is to avoid the abrupt
> change in Emacs-26.1.
Yes, we should at least deobsolete foo-let in 26.1. It makes no sense
to declare these obsolete now, causing everyone work and trouble, and
then deobsolete these in the next release.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 16:03 ` if-let/if-let*/and-let/ Stefan Monnier
2018-03-06 17:40 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-06 17:40 ` Eli Zaretskii
2018-03-07 14:15 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-06 17:40 UTC (permalink / raw)
To: Stefan Monnier; +Cc: emacs-devel
> From: Stefan Monnier <monnier@iro.umontreal.ca>
> Date: Tue, 06 Mar 2018 11:03:41 -0500
>
> > MH> Hmm, I hope it is ok that I installed it into emacs-26...I think it is
> > MH> important to include it in the release.
> > Unless Eli is OK with it, I'm not. We're into RC1 territory now (or in a few
> > days), which means absolutely no non-critical changes.
>
> FWIW, I think delaying the change to after Emacs-26.1 would make the
> change pointless, since the whole purpose is to avoid the abrupt change
> in Emacs-26.1.
Then please convince me by telling more about this. The log message
vaguely mentions some warning problems, but doesn't tell any details,
and the discussion was on emacs-devel, not the bug tracker. Help in
understanding why this is important to have now (or at all) will be
appreciated.
TIA
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 17:40 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-06 19:12 ` Radon Rosborough
2018-03-07 2:13 ` if-let/if-let*/and-let/ James Nguyen
0 siblings, 1 reply; 47+ messages in thread
From: Radon Rosborough @ 2018-03-06 19:12 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Stefan Monnier, emacs-devel
> It makes no sense
> to declare these obsolete now, causing everyone work and trouble
I have personally experienced this work and trouble multiple times,
and would be very happy if I didn't have to keep dealing with it for
every package that I happen to want to use if-let and when-let in. Any
plan that does not result in those functions being made obsolete gets
my vote.
-- Radon
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 19:12 ` if-let/if-let*/and-let/ Radon Rosborough
@ 2018-03-07 2:13 ` James Nguyen
2018-03-07 3:42 ` if-let/if-let*/and-let/ Kaushal Modi
0 siblings, 1 reply; 47+ messages in thread
From: James Nguyen @ 2018-03-07 2:13 UTC (permalink / raw)
To: Radon Rosborough; +Cc: Michael Heerdegen, Stefan Monnier, emacs-devel
Strong +, Maintain a couple packages and have to add boilerplate defalias code in every single package for this.
> On Mar 6, 2018, at 11:12 AM, Radon Rosborough <radon.neon@gmail.com> wrote:
>
>> It makes no sense
>> to declare these obsolete now, causing everyone work and trouble
>
> I have personally experienced this work and trouble multiple times,
> and would be very happy if I didn't have to keep dealing with it for
> every package that I happen to want to use if-let and when-let in. Any
> plan that does not result in those functions being made obsolete gets
> my vote.
>
> -- Radon
>
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-07 2:13 ` if-let/if-let*/and-let/ James Nguyen
@ 2018-03-07 3:42 ` Kaushal Modi
0 siblings, 0 replies; 47+ messages in thread
From: Kaushal Modi @ 2018-03-07 3:42 UTC (permalink / raw)
To: James Nguyen
Cc: Michael Heerdegen, Radon Rosborough, Stefan Monnier, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 582 bytes --]
On Tue, Mar 6, 2018, 9:14 PM James Nguyen <jamesn@fastmail.com> wrote:
> Strong +, Maintain a couple packages and have to add boilerplate defalias
> code in every single package for this.
>
I have my +1 to prevent this obsolete-then-deobsolete plan across Emacs
versions.
When foo-let were obsoleted, I was like, fine.. not a big deal. But now if
they are going to be deobsoleted in the next release, then why not just do
it now?
I would rather have the obsolete-then-deobsolete phase happen in a single
major version dev cycle, rather than across releases.
--
Kaushal Modi
[-- Attachment #2: Type: text/html, Size: 1146 bytes --]
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-06 17:40 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-07 14:15 ` Michael Heerdegen
2018-03-07 15:13 ` if-let/if-let*/and-let/ Nicolas Petton
` (2 more replies)
0 siblings, 3 replies; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-07 14:15 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> Then please convince me by telling more about this. The log message
> vaguely mentions some warning problems, but doesn't tell any details,
> and the discussion was on emacs-devel, not the bug tracker. Help in
> understanding why this is important to have now (or at all) will be
> appreciated.
Ok.
In the beginning, we had if-let and when-let in subr-x (that's the state
of the last release). Then we added and-let and decided to port the
extended syntax of and-let to if-let and when-let. In a single special
case ("single binding tuple"), the new syntax was incompatible with that
of when-let and if-let, so we decided to introduce new names if-let* and
when-let* (which some of us preferred over the old names anyway) and
declared if-let and when-let obsolete. That's the state of the emacs-26
branch without my suggested patch.
We then have seen that this was a mistake, there were lots of
complaints. The problem is that whenever a file uses foo-let (and those
are much more than we had estimated), you get a lot of compiler warnings
about using an obsolete thing. But people can't just use the new forms
because that would not be backward compatible with older (25.x) Emacs
versions.
With the current state of the emacs-26 branch, we would still declare
foo-let obsolete, although we already know that we will revert this in
the subsequent release. If we leave things as they are now, we would
cause a lot of confusion and trouble for nothing: to get rid of the
numerous warnings, people have began to remove occurrences of foo-let
from their files or turn off compiler warnings in their packages
completely. Very bad, and needless. Lot's of packages would have to be
changed for no gain.
My commit is a tiny change that deobsoletes foo-let and readjusts things
so that foo-let* are aliases for foo-let.
But yes, the commit touches the foo-let. As a compromise, we could also
just deobsolete foo-let to avoid the confusion, and install the
suggested change to master. Though, that would still not be optimal,
because we would install a version of foo-let* that we will not keep in
the subsequent releases, so it would still cause a lot of trouble and
confusion.
FWIW, the change is well tested, and I had a look at each affected
occurrence of foo-let in the Emacs code base (which are not very many),
if that matters.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-07 14:15 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-07 15:13 ` Nicolas Petton
2018-03-07 20:43 ` if-let/if-let*/and-let/ John Wiegley
2018-03-08 13:53 ` if-let/if-let*/and-let/ Eli Zaretskii
2 siblings, 0 replies; 47+ messages in thread
From: Nicolas Petton @ 2018-03-07 15:13 UTC (permalink / raw)
To: Michael Heerdegen, Eli Zaretskii; +Cc: Stefan Monnier, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 671 bytes --]
Michael Heerdegen <michael_heerdegen@web.de> writes:
Hi Michael,
> But yes, the commit touches the foo-let. As a compromise, we could also
> just deobsolete foo-let to avoid the confusion, and install the
> suggested change to master. Though, that would still not be optimal,
> because we would install a version of foo-let* that we will not keep in
> the subsequent releases, so it would still cause a lot of trouble and
> confusion.
FWIW, I also think it's important to at least de-obsolete these macros,
for the reasons you mentioned.
I am myself waiting for a final decision regarding this before getting
rid of all foo-let usages in my packages.
Cheers,
Nico
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 487 bytes --]
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-07 14:15 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-07 15:13 ` if-let/if-let*/and-let/ Nicolas Petton
@ 2018-03-07 20:43 ` John Wiegley
2018-03-08 13:53 ` if-let/if-let*/and-let/ Eli Zaretskii
2 siblings, 0 replies; 47+ messages in thread
From: John Wiegley @ 2018-03-07 20:43 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: Eli Zaretskii, Stefan Monnier, emacs-devel
>>>>> "MH" == Michael Heerdegen <michael_heerdegen@web.de> writes:
MH> My commit is a tiny change that deobsoletes foo-let and readjusts things
MH> so that foo-let* are aliases for foo-let.
This does sound safe enough to allow in for the release, as well as avoiding
some unnecessary annoyance. What say you, Eli?
--
John Wiegley GPG fingerprint = 4710 CF98 AF9B 327B B80F
http://newartisans.com 60E1 46C4 BD1A 7AC1 4BA2
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-07 14:15 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-07 15:13 ` if-let/if-let*/and-let/ Nicolas Petton
2018-03-07 20:43 ` if-let/if-let*/and-let/ John Wiegley
@ 2018-03-08 13:53 ` Eli Zaretskii
2018-03-09 15:16 ` if-let/if-let*/and-let/ Michael Heerdegen
2 siblings, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-08 13:53 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: Stefan Monnier <monnier@iro.umontreal.ca>, emacs-devel@gnu.org
> Date: Wed, 07 Mar 2018 15:15:33 +0100
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> > Then please convince me by telling more about this. The log message
> > vaguely mentions some warning problems, but doesn't tell any details,
> > and the discussion was on emacs-devel, not the bug tracker. Help in
> > understanding why this is important to have now (or at all) will be
> > appreciated.
>
> Ok.
>
> In the beginning [...]
Thanks for the explanations.
Maybe I'm missing something, but it sounds like if we just
un-obsolete foo-let, we'd have solved the urgent problem, is that
right? If not, what unsolved problems will this leave us with?
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-08 13:53 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-09 15:16 ` Michael Heerdegen
2018-03-09 15:32 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-09 15:16 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> Maybe I'm missing something, but it sounds like if we just
> un-obsolete foo-let, we'd have solved the urgent problem, is that
> right? If not, what unsolved problems will this leave us with?
It would solve the most urgent problem (the warnings), yes, package
maintainers would be happy.
The downside of only de-obsoleting now is that in the subsequent
release, we would have to change the newly introduced foo-let* in a
backward-incompatible way for the single-binding-tuple special case.
This backward-incompatible change is necessary to make foo-let* aliases
of foo-let, which is our goal - foo-let has to support the
single-binding-tuple syntax because it supported it all the time.
We have to weigh what is worse: make the whole change now and make 26.1
introduce the new foo-let* as we want them to be, or release foo-let* as
is, with the need of a backward-incompatible change of foo-let* in 26.2
for the special case, which could then potentially break working code.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 15:16 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-09 15:32 ` Eli Zaretskii
2018-03-09 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-09 15:32 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Fri, 09 Mar 2018 16:16:14 +0100
>
> The downside of only de-obsoleting now is that in the subsequent
> release, we would have to change the newly introduced foo-let* in a
> backward-incompatible way for the single-binding-tuple special case.
>
> This backward-incompatible change is necessary to make foo-let* aliases
> of foo-let, which is our goal - foo-let has to support the
> single-binding-tuple syntax because it supported it all the time.
That foo-let did support that case doesn't necessarily mean it has to
support that in the future, nor that we must make that
backward-incompatible immediately. We could simply let foo-let be as
it is today on the release branch and collect more experience before
we make our decision. Does that make sense?
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 15:32 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-09 16:07 ` Michael Heerdegen
2018-03-09 16:24 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-09 16:07 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> That foo-let did support that case doesn't necessarily mean it has to
> support that in the future, nor that we must make that
> backward-incompatible immediately. We could simply let foo-let be as
> it is today on the release branch and collect more experience before
> we make our decision. Does that make sense?
This isn't about experience: the old single binding syntax is simply
obsolete:
(1) (if-let (a (calculate-a)) use-a ...)
is the same as
(2) (if-let ((a (calculate-a))) use-a ...)
The problem is that people still use the syntax (1) in code a lot (since
it was once the only valid syntax AFAICT), and `if-let*' interprets a
varlist as in (1) in a _different way_. That's why we decided to
obsolete if-let. That gave us the compiler warning problem which
annoyed many people.
We are now going in circles in the discussions for a while. There
simply is no optimal solution to that problem. We have to decide what
we want, more time won't help. Keeping both names foo-let and foo-let*
with very small, illogical semantic differences as we have now would be
the worst solution, as Stefan pointed out.
My suggested solution (the solution of the commit I had installed and
then reverted) was to change `if-let*' for the special case so that it
also supports the old interpretation of a varlist as in (1). Then we
can make `foo-let' and `foo-let*' synonyms, which is what we want, and
also a quite harmless change, since the names `foo-let*' are new in 26.1
and I have checked every individual occurrence of a foo-let* varlist of
kind (1) in the Emacs sources and in Gnu Elpa.
There are other solutions, of course. I would rather get rid of the old
semantic, but that's not possible without creating a large amount of
annoyance for a longer time.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-09 16:24 ` Eli Zaretskii
2018-03-09 16:33 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-09 16:24 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Fri, 09 Mar 2018 17:07:44 +0100
>
> We are now going in circles in the discussions for a while.
I'm sorry to cause the circling, but I must understand the issue to
decide whether and how to apply these changes to the release branch.
> Keeping both names foo-let and foo-let* with very small, illogical
> semantic differences as we have now would be the worst solution, as
> Stefan pointed out.
Why is it the worst solution? It sounds to me like the best one,
given the mess that already exists for several months.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 16:24 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-09 16:33 ` Michael Heerdegen
2018-03-09 18:22 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-09 16:33 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> I'm sorry to cause the circling, but I must understand the issue to
> decide whether and how to apply these changes to the release branch.
Sure - welcome.
> Why is it the worst solution? It sounds to me like the best one,
> given the mess that already exists for several months.
It's a different kind of mess. With Emacs 26.1 we would have new macro
names foo-let* which would be doing exactly the same as foo-let apart
from a corner case. That would make no sense and cause a lot of
confusion.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 16:33 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-09 18:22 ` Eli Zaretskii
2018-03-09 22:24 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-09 18:22 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Fri, 09 Mar 2018 17:33:04 +0100
>
> > Why is it the worst solution? It sounds to me like the best one,
> > given the mess that already exists for several months.
>
> It's a different kind of mess. With Emacs 26.1 we would have new macro
> names foo-let* which would be doing exactly the same as foo-let apart
> from a corner case. That would make no sense and cause a lot of
> confusion.
I don't see why would that be a mess. Two APIs that produce the same
effect in some cases, but not in others, are nothing new.
So I think this is what we should do on the release branch.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 18:22 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-09 22:24 ` Michael Heerdegen
2018-03-10 8:02 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-09 22:24 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> I don't see why would that be a mess. Two APIs that produce the same
> effect in some cases, but not in others, are nothing new.
What is new, however, is that having two different APIs doesn't make any
sense here.
> So I think this is what we should do on the release branch.
If you don't object to unite the two APIs in master, I'm ok with that
decision. However, I then would like to change the NEWS entry in the
release branch so that it doesn't mention the new foo-let* names,
because these will be only synonyms for foo-let in subsequent releases,
and letting NEWS introduce them now as something different would only
cause confusion.
Thanks,
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-09 22:24 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-10 8:02 ` Eli Zaretskii
2018-03-10 15:54 ` if-let/if-let*/and-let/ Stefan Monnier
2018-03-10 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 2 replies; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-10 8:02 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Fri, 09 Mar 2018 23:24:28 +0100
>
> Eli Zaretskii <eliz@gnu.org> writes:
>
> > I don't see why would that be a mess. Two APIs that produce the same
> > effect in some cases, but not in others, are nothing new.
>
> What is new, however, is that having two different APIs doesn't make any
> sense here.
I don't think it's new ;-)
And it probably did make sense when the foo-let* were introduced.
It's just in retrospect that it doesn't.
> > So I think this is what we should do on the release branch.
>
> If you don't object to unite the two APIs in master, I'm ok with that
> decision. However, I then would like to change the NEWS entry in the
> release branch so that it doesn't mention the new foo-let* names,
> because these will be only synonyms for foo-let in subsequent releases,
> and letting NEWS introduce them now as something different would only
> cause confusion.
Fine with me, thanks.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-10 8:02 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-10 15:54 ` Stefan Monnier
2018-03-10 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
1 sibling, 0 replies; 47+ messages in thread
From: Stefan Monnier @ 2018-03-10 15:54 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Michael Heerdegen, emacs-devel
> And it probably did make sense when the foo-let* were introduced.
No, when foo-let* was introduced the idea is that it would supersede foo-let.
Stefan
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-10 8:02 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-10 15:54 ` if-let/if-let*/and-let/ Stefan Monnier
@ 2018-03-10 16:07 ` Michael Heerdegen
2018-03-10 16:29 ` if-let/if-let*/and-let/ Eli Zaretskii
1 sibling, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-10 16:07 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
Eli Zaretskii <eliz@gnu.org> writes:
> And it probably did make sense when the foo-let* were introduced.
> It's just in retrospect that it doesn't.
No, AFAIR it never made sense. The switch to new names, and declaring
the old names obsolete, was done to avoid making a backward incompatible
change.
> > If you don't object to unite the two APIs in master, I'm ok with that
> > decision. However, I then would like to change the NEWS entry in the
> > release branch so that it doesn't mention the new foo-let* names,
> > because these will be only synonyms for foo-let in subsequent releases,
> > and letting NEWS introduce them now as something different would only
> > cause confusion.
>
> Fine with me, thanks.
Oh, I see that we still have a little problem with that: In emacs-26, we
currently only have `and-let*', no `and-let' is defined - so what we
present in NEWS would still be inconsistent/confusing - unless we also
keep `and-let*' secret for now and only tell users that `if-let' and
`when-let' have gotten extended semantics. That would not be
problematic however, since and-let/and-let* is only a special case of
when-let, the main improvement was the extension of the semantics of the
variable binding list.
Michael.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-10 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-10 16:29 ` Eli Zaretskii
2018-03-10 17:16 ` if-let/if-let*/and-let/ Michael Heerdegen
0 siblings, 1 reply; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-10 16:29 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Sat, 10 Mar 2018 17:07:58 +0100
>
> The switch to new names, and declaring the old names obsolete, was
> done to avoid making a backward incompatible change.
Which is what I call "made sense".
> > > If you don't object to unite the two APIs in master, I'm ok with that
> > > decision. However, I then would like to change the NEWS entry in the
> > > release branch so that it doesn't mention the new foo-let* names,
> > > because these will be only synonyms for foo-let in subsequent releases,
> > > and letting NEWS introduce them now as something different would only
> > > cause confusion.
> >
> > Fine with me, thanks.
>
> Oh, I see that we still have a little problem with that: In emacs-26, we
> currently only have `and-let*', no `and-let' is defined - so what we
> present in NEWS would still be inconsistent/confusing - unless we also
> keep `and-let*' secret for now and only tell users that `if-let' and
> `when-let' have gotten extended semantics.
If you really meant and-let*, then it's covered by the "foo-let*"
catch-all, and I assumed it, too, won't be mentioned.
^ permalink raw reply [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-10 16:29 ` if-let/if-let*/and-let/ Eli Zaretskii
@ 2018-03-10 17:16 ` Michael Heerdegen
2018-03-10 17:29 ` if-let/if-let*/and-let/ Eli Zaretskii
0 siblings, 1 reply; 47+ messages in thread
From: Michael Heerdegen @ 2018-03-10 17:16 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: monnier, emacs-devel
[-- Attachment #1: Type: text/plain, Size: 217 bytes --]
Eli Zaretskii <eliz@gnu.org> writes:
> If you really meant and-let*, then it's covered by the "foo-let*"
> catch-all, and I assumed it, too, won't be mentioned.
Yes, I meant that.
Then this is what I have so far:
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-De-obsolete-if-let-and-when-let.patch --]
[-- Type: text/x-diff, Size: 2177 bytes --]
From 065374524104eaa471d199528cff180754975def Mon Sep 17 00:00:00 2001
From: Michael Heerdegen <michael_heerdegen@web.de>
Date: Sat, 10 Mar 2018 16:39:41 +0100
Subject: [PATCH] De-obsolete `if-let' and `when-let'
Revert declaring `if-let' and `when-let' obsolete....
---
etc/NEWS | 8 ++------
lisp/emacs-lisp/subr-x.el | 6 ++----
2 files changed, 4 insertions(+), 10 deletions(-)
diff --git a/etc/NEWS b/etc/NEWS
index eded00e655..b87715ddbc 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1301,12 +1301,8 @@ current buffer or the self-insertion takes place within a comment.
** The alist 'ucs-names' is now a hash table.
---
-** 'if-let' and 'when-let' are subsumed by 'if-let*' and 'when-let*'.
-The incumbent 'if-let' and 'when-let' are now marked obsolete.
-'if-let*' and 'when-let*' do not accept the single tuple special case.
-New macro 'and-let*' is an implementation of the Scheme SRFI-2 syntax
-of the same name. 'if-let*' and 'when-let*' now accept the same
-binding syntax as 'and-let*'.
+** 'if-let' and 'when-let' now support binding lists as defined by the
+SRFI-2.
---
** 'C-up', 'C-down', 'C-left' and 'C-right' are now defined in term
diff --git a/lisp/emacs-lisp/subr-x.el b/lisp/emacs-lisp/subr-x.el
index 21dba377bf..e620e2062f 100644
--- a/lisp/emacs-lisp/subr-x.el
+++ b/lisp/emacs-lisp/subr-x.el
@@ -172,8 +172,7 @@ if-let
(declare (indent 2)
(debug ([&or (&rest [&or symbolp (symbolp form) (form)])
(symbolp form)]
- form body))
- (obsolete "use `if-let*' instead." "26.1"))
+ form body)))
(when (and (<= (length spec) 2)
(not (listp (car spec))))
;; Adjust the single binding case
@@ -183,8 +182,7 @@ if-let
(defmacro when-let (spec &rest body)
"Bind variables according to SPEC and conditionally eval BODY.
Like `when-let*' except SPEC can have the form (SYMBOL VALUEFORM)."
- (declare (indent 1) (debug if-let)
- (obsolete "use `when-let*' instead." "26.1"))
+ (declare (indent 1) (debug if-let))
(list 'if-let spec (macroexp-progn body)))
(defsubst hash-table-empty-p (hash-table)
--
2.16.1
[-- Attachment #3: Type: text/plain, Size: 719 bytes --]
But we still can't use this, because the documentation of if-let and
when-let in emacs-26 refers to the documentation of if-let* and
when-let*. I would at least also have to rewrite the docstrings of
if-let and when-let. I'm beginning to wonder if what we are
constructing here is really simpler than my initial approach.
BTW, the srfi-2 allows a SYMBOL as element of the binding spec. AFAIK
all of the macros (foo-let and foo-let*) support that case, but it's not
documented. I dunno why, the original author, Mark Oteiza
<mvoteiza@udel.edu>, didn't respond to my questions in emacs-dev. My
guess is that it hasn't been documented because the foo-let
single-binding case intersects with this syntax.
Michael.
^ permalink raw reply related [flat|nested] 47+ messages in thread
* Re: if-let/if-let*/and-let/..
2018-03-10 17:16 ` if-let/if-let*/and-let/ Michael Heerdegen
@ 2018-03-10 17:29 ` Eli Zaretskii
0 siblings, 0 replies; 47+ messages in thread
From: Eli Zaretskii @ 2018-03-10 17:29 UTC (permalink / raw)
To: Michael Heerdegen; +Cc: monnier, emacs-devel
> From: Michael Heerdegen <michael_heerdegen@web.de>
> Cc: monnier@iro.umontreal.ca, emacs-devel@gnu.org
> Date: Sat, 10 Mar 2018 18:16:37 +0100
>
> Then this is what I have so far:
LGTM, thanks.
> But we still can't use this, because the documentation of if-let and
> when-let in emacs-26 refers to the documentation of if-let* and
> when-let*. I would at least also have to rewrite the docstrings of
> if-let and when-let. I'm beginning to wonder if what we are
> constructing here is really simpler than my initial approach.
It might not be a lot simpler, but it's certainly safer, since changes
in doc string can never cause any breakage.
> BTW, the srfi-2 allows a SYMBOL as element of the binding spec. AFAIK
> all of the macros (foo-let and foo-let*) support that case, but it's not
> documented. I dunno why, the original author, Mark Oteiza
> <mvoteiza@udel.edu>, didn't respond to my questions in emacs-dev. My
> guess is that it hasn't been documented because the foo-let
> single-binding case intersects with this syntax.
If you decide to add this to the documentation, it's fine by me.
^ permalink raw reply [flat|nested] 47+ messages in thread
end of thread, other threads:[~2018-03-10 17:29 UTC | newest]
Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-11 23:51 if-let/if-let*/and-let/ Stefan Monnier
[not found] ` <87wozijhpk.fsf@web.de>
[not found] ` <jwv8tbyyx4x.fsf-monnier+emacs@gnu.org>
2018-02-12 17:32 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-13 18:23 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-13 19:24 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-13 20:52 ` if-let/if-let*/and-let/ John Wiegley
2018-02-13 19:31 ` if-let/if-let*/and-let/ Mark Oteiza
2018-02-13 20:49 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-14 0:07 ` if-let/if-let*/and-let/ Mark Oteiza
2018-02-14 23:07 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-15 3:37 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-21 4:26 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-22 1:08 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-22 5:10 ` if-let/if-let*/and-let/ Stefan Monnier
2018-02-22 7:55 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-03 14:12 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-06 15:03 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-06 15:31 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-06 15:34 ` if-let/if-let*/and-let/ John Wiegley
2018-03-06 16:03 ` if-let/if-let*/and-let/ Stefan Monnier
2018-03-06 17:40 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-06 19:12 ` if-let/if-let*/and-let/ Radon Rosborough
2018-03-07 2:13 ` if-let/if-let*/and-let/ James Nguyen
2018-03-07 3:42 ` if-let/if-let*/and-let/ Kaushal Modi
2018-03-06 17:40 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-07 14:15 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-07 15:13 ` if-let/if-let*/and-let/ Nicolas Petton
2018-03-07 20:43 ` if-let/if-let*/and-let/ John Wiegley
2018-03-08 13:53 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-09 15:16 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-09 15:32 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-09 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-09 16:24 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-09 16:33 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-09 18:22 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-09 22:24 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-10 8:02 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-10 15:54 ` if-let/if-let*/and-let/ Stefan Monnier
2018-03-10 16:07 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-10 16:29 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-10 17:16 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-03-10 17:29 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-06 16:04 ` if-let/if-let*/and-let/ Eli Zaretskii
2018-03-06 17:35 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-13 20:54 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-13 21:57 ` if-let/if-let*/and-let/ Eric Abrahamsen
2018-02-13 22:39 ` if-let/if-let*/and-let/ Michael Heerdegen
2018-02-13 22:51 ` if-let/if-let*/and-let/ Eric Abrahamsen
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.