* 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
[parent not found: <87wozijhpk.fsf@web.de>]
[parent not found: <jwv8tbyyx4x.fsf-monnier+emacs@gnu.org>]
* 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 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 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 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 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 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 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/ 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
* 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-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
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.