unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Why is there no `until' in elisp?
@ 2018-10-16 17:42 Garreau, Alexandre
  2018-10-16 19:16 ` Eric Abrahamsen
  2018-10-16 21:28 ` Stefan Monnier
  0 siblings, 2 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-16 17:42 UTC (permalink / raw)
  To: emacs-devel

Sometimes I have the strong feeling that the symetric of “while”,
“until” [0], unlike in many languages such as C, exists in elisp.  That
happened to me several times, and usually I bug for about an hour before
to realize I do this confusion because it has the symetric of “when”:
“unless”, but not the same for “while”.

However, “until” exists, for instance in bash (which has no “unless”…
maybe because it has no “when” because it has guarded “if”s?), and I
find it pretty handy for making stuff more readable and avoiding making
stuff more complex…

Is there a particular rational or style reason for not using a such
trivial and obvious (both in terms of implementation and
understandement) construct?

If not so, why isn’t it in elisp, aside of `when' and `unless' in
subr.el (if that ought to be the correct file?)?

[0] such as: (defmacro until (test &rest body) (declare (indent 1))
`(while (not ,test) ,@body))



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

* Re: Why is there no `until' in elisp?
  2018-10-16 17:42 Why is there no `until' in elisp? Garreau, Alexandre
@ 2018-10-16 19:16 ` Eric Abrahamsen
  2018-10-16 19:31   ` Garreau, Alexandre
  2018-10-19 15:28   ` Stefan Monnier
  2018-10-16 21:28 ` Stefan Monnier
  1 sibling, 2 replies; 26+ messages in thread
From: Eric Abrahamsen @ 2018-10-16 19:16 UTC (permalink / raw)
  To: emacs-devel

"Garreau, Alexandre" <galex-713@galex-713.eu> writes:

> Sometimes I have the strong feeling that the symetric of “while”,
> “until” [0], unlike in many languages such as C, exists in elisp.  That
> happened to me several times, and usually I bug for about an hour before
> to realize I do this confusion because it has the symetric of “when”:
> “unless”, but not the same for “while”.
>
> However, “until” exists, for instance in bash (which has no “unless”…
> maybe because it has no “when” because it has guarded “if”s?), and I
> find it pretty handy for making stuff more readable and avoiding making
> stuff more complex…
>
> Is there a particular rational or style reason for not using a such
> trivial and obvious (both in terms of implementation and
> understandement) construct?
>
> If not so, why isn’t it in elisp, aside of `when' and `unless' in
> subr.el (if that ought to be the correct file?)?
>
> [0] such as: (defmacro until (test &rest body) (declare (indent 1))
> `(while (not ,test) ,@body))

I have nothing to do with this, but my feeling is that Lisp developers
in general drag their feet about adding trivial/obvious constructs to
the standard library. As your footnote makes clear, it's a two-line code
addition to make `until' work. There are different schools of thought
about this: one that says "why?", and one that says "why not"? The "why
not"s contribute to subr.el and subr-x.el :)




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

* Re: Why is there no `until' in elisp?
  2018-10-16 19:16 ` Eric Abrahamsen
@ 2018-10-16 19:31   ` Garreau, Alexandre
  2018-10-16 20:23     ` Eric Abrahamsen
  2018-10-19 15:28   ` Stefan Monnier
  1 sibling, 1 reply; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-16 19:31 UTC (permalink / raw)
  To: Eric Abrahamsen; +Cc: emacs-devel

On 2018-10-16 at 12:16, Eric Abrahamsen wrote:
> "Garreau, Alexandre" <galex-713@galex-713.eu> writes:
>> [0] such as: (defmacro until (test &rest body) (declare (indent 1))
>> `(while (not ,test) ,@body))
>
> I have nothing to do with this, but my feeling is that Lisp developers
> in general drag their feet about adding trivial/obvious constructs to
> the standard library.

Why?  If this is because of the triviality of reimplementing, wouldn’t
they do, once they want to use it in contributing emacs (I keep seeing
many (while (not …) …))?  or do they restrain themselves for some
rational/useful reason I still ignore?

The “it’s one macro more to learn fully the language” doesn’t stand that
much (especially about elisp) to me as it is easy to read source code,
easy to find definitions, and “unless” is as much an english word as
“while” (maybe even more widespread, outside of programming).



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

* Re: Why is there no `until' in elisp?
  2018-10-16 19:31   ` Garreau, Alexandre
@ 2018-10-16 20:23     ` Eric Abrahamsen
  2018-10-16 23:00       ` Garreau, Alexandre
  0 siblings, 1 reply; 26+ messages in thread
From: Eric Abrahamsen @ 2018-10-16 20:23 UTC (permalink / raw)
  To: emacs-devel

"Garreau, Alexandre" <galex-713@galex-713.eu> writes:

> On 2018-10-16 at 12:16, Eric Abrahamsen wrote:
>> "Garreau, Alexandre" <galex-713@galex-713.eu> writes:
>>> [0] such as: (defmacro until (test &rest body) (declare (indent 1))
>>> `(while (not ,test) ,@body))
>>
>> I have nothing to do with this, but my feeling is that Lisp developers
>> in general drag their feet about adding trivial/obvious constructs to
>> the standard library.
>
> Why?  If this is because of the triviality of reimplementing, wouldn’t
> they do, once they want to use it in contributing emacs (I keep seeing
> many (while (not …) …))?  or do they restrain themselves for some
> rational/useful reason I still ignore?
>
> The “it’s one macro more to learn fully the language” doesn’t stand that
> much (especially about elisp) to me as it is easy to read source code,
> easy to find definitions, and “unless” is as much an english word as
> “while” (maybe even more widespread, outside of programming).

Again, I'm not one of these developers, so I'm putting words in others'
mouths...

I don't think it has anything to do with making the language harder to
learn. It's just the fact that the constructs are so easy to add (this
is the power of lisp, after all), and different developers might want
very slightly different versions of the same thing, so people just put
in their own versions of things.

Obviously there are plenty of people who feel differently about it,
which is why we have all these supplementary packages within Emacs and
the package repositories.

But the core of the language remains conservative about additions.
Personally, I think that's a good thing.

Eric




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

* Re: Why is there no `until' in elisp?
  2018-10-16 17:42 Why is there no `until' in elisp? Garreau, Alexandre
  2018-10-16 19:16 ` Eric Abrahamsen
@ 2018-10-16 21:28 ` Stefan Monnier
  2018-10-17  0:12   ` Garreau, Alexandre
  2018-10-17  8:04   ` Yuri Khan
  1 sibling, 2 replies; 26+ messages in thread
From: Stefan Monnier @ 2018-10-16 21:28 UTC (permalink / raw)
  To: emacs-devel

> [0] such as: (defmacro until (test &rest body) (declare (indent 1))
> `(while (not ,test) ,@body))

I like `until`.  As a matter of fact, I think `until` is more important
than `while` for the following reason: it should not behave like the one
you have above but rather like:

    (defmacro until (test &rest body)
      (let (res)
        (while (not (setq res ,test)) ,@body)
        res))

While `while` doesn't have much else to return than nil, `until` does
have a useful value to return, which is the non-nil value that caused it
to exit.


        Stefan




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

* Re: Why is there no `until' in elisp?
  2018-10-16 20:23     ` Eric Abrahamsen
@ 2018-10-16 23:00       ` Garreau, Alexandre
  0 siblings, 0 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-16 23:00 UTC (permalink / raw)
  To: Eric Abrahamsen; +Cc: emacs-devel

On 2018-10-16 at 13:23, Eric Abrahamsen wrote:
> I don't think it has anything to do with making the language harder to
> learn. It's just the fact that the constructs are so easy to add (this
> is the power of lisp, after all), and different developers might want
> very slightly different versions of the same thing, so people just put
> in their own versions of things.

I was to say that when it’s about simple enough things, there’s a way
people agree, especially if we try keeping it minimal, but then Stefan
Monnier proposed a different version of until I didn’t though about, so
I must admit this is more complex (I keep thinking we need different
words / identifiers for non-minimal cases).

> Obviously there are plenty of people who feel differently about it,
> which is why we have all these supplementary packages within Emacs and
> the package repositories.

If we’re effectively speaking of stuff big enough to justify a package,
then we’re going into DSL libraries that might make themselves alien and
less readable to the uninitiated.

> But the core of the language remains conservative about additions.
> Personally, I think that's a good thing.

I’m unsure, it encourages reinventing the wheel, while there are other
measurment to discriminate between what is known, common and popular and
the more experimental rest.



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

* Re: Why is there no `until' in elisp?
  2018-10-16 21:28 ` Stefan Monnier
@ 2018-10-17  0:12   ` Garreau, Alexandre
  2018-10-17  2:04     ` Stefan Monnier
  2018-10-19 15:34     ` Stefan Monnier
  2018-10-17  8:04   ` Yuri Khan
  1 sibling, 2 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17  0:12 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

I do also believe `until' is actually more important than `while', first of
all, as I said, we can see that because it is more used in human
language, this is also the case because `while', in its condition,
refers to a both initial and transient state, while `until' refers to
its final state, which is what should interest us the most (especially
in functional programming that should be more interested at the result
than the source).

However I believe in minimalism, and I’m surprised you found something
different and incompatible, but still, I find, very very interesting: I
think `until' should refer to the version I gave because this is
probably the one which is going to be implemented naively by most
people, also it can be useful to try to retrieve the last body return
value, just as it is with `while': it is usually something you computed,
not some potential binary boolean that you might have known since the
beginning.  And then, of course, this introduce useless discrepancy
toward symmetry within respect `while'.  So your version should have a
different (maybe longer? I hope the least) name.

A trivial symetric `while' to yours is one that keeps the last true
value: `(let (res) (while (and! res ,test) ,@body) res) (while
introducing the notation fun![0]).

It may sound artificial but it is not, look thereafter.

I recently felt a big need of a form acting both as a `when' and a
`prog1' (a `when' that returns its condition / first argument), and
symetricaly for `unless' (in the end I used a (when-let ((var val))
(prog1 var . body)), but I’m pretty unsatisfied, like always when it’s
about finding an optimum in extreme factorization, maybe sometimes it’s
not possible).  This is no different.

This also recalled me that, but this might be a separate discussion, a
long time ago, when discovering cyclic lists through experimentation, I
thought that `while' could be implemented this way: `(and (prog1 . body)
. #1), and for until: `(or (prog1 . body) . #1).

And your until is precisely that.  Now you also got your interesting
counterpart for `until'.

While my minimal `until' is to yours what `progn' is to `prog1'.  Let’s
call yours `until1', then `until' is (let (res) (until1 test (setq res
(progn . body)))) (I still fill like a relation between both might be
better and more elegantly expressed… though the same stands for
when-prog1).

Another interesting version I dreamt of is the one that returns a list
of the return value of each iteration (in may be useful in both mine and
yours version): (lazy-map (lambda (var) . body) '(cons test (or test
#0))) (or any way of stopping to map/concat when it is returning nil).

[0] so that, for any `fun' where `fun!' (an imperative, side-effects
targeted, version of fun) is undefined: (fun! var . args) stands for
(setq var (fun! var . args)), such as (+! var 1 2) is (setq var (+ var 1
2)), (not! var) is (setq var (not var)) and (and! var bool1 bool2) is
(setq var (and var bool1 bool2) (this is all equivalent to C “+=”, “!=”
and “&=” (or better: C++ “&&=”)).



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

* Re: Why is there no `until' in elisp?
  2018-10-17  0:12   ` Garreau, Alexandre
@ 2018-10-17  2:04     ` Stefan Monnier
  2018-10-17  9:14       ` Garreau, Alexandre
  2018-10-19 15:34     ` Stefan Monnier
  1 sibling, 1 reply; 26+ messages in thread
From: Stefan Monnier @ 2018-10-17  2:04 UTC (permalink / raw)
  To: emacs-devel

> I think `until' should refer to the version I gave because this is
> probably the one which is going to be implemented naively by most people,

I completely reject this kind of argument.

By that argument, we should avoid lexical scoping since dynamic scoping
is "the one which is going to be implemented naively by most people".

> also it can be useful to try to retrieve the last body return
> value, just as it is with `while':

The body of those loops is made of side-effecting operations.
Usually side-effecting operations don't have useful return values.

> And then, of course, this introduce useless discrepancy toward
> symmetry within respect `while'.

No discrepancy: it makes `until` return the value of its last test, just
like `while` already does (with `while` that value is always nil).


        Stefan




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

* Re: Why is there no `until' in elisp?
  2018-10-16 21:28 ` Stefan Monnier
  2018-10-17  0:12   ` Garreau, Alexandre
@ 2018-10-17  8:04   ` Yuri Khan
  2018-10-17  9:23     ` Garreau, Alexandre
                       ` (2 more replies)
  1 sibling, 3 replies; 26+ messages in thread
From: Yuri Khan @ 2018-10-17  8:04 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Emacs developers

On Wed, Oct 17, 2018 at 4:33 AM Stefan Monnier <monnier@iro.umontreal.ca> wrote:

> > [0] such as: (defmacro until (test &rest body) (declare (indent 1))
> > `(while (not ,test) ,@body))
>
> I like `until`.  As a matter of fact, I think `until` is more important
> than `while` for the following reason: it should not behave like the one
> you have above but rather like:
>
>     (defmacro until (test &rest body)
>       (let (res)
>         (while (not (setq res ,test)) ,@body)
>         res))
>
> While `while` doesn't have much else to return than nil, `until` does
> have a useful value to return, which is the non-nil value that caused it
> to exit.

In both these implementations, ‘until’ is still a pre-condition loop
(same as ‘while’, but with the condition negated).

However, in many languages that have an ‘until’ loop as a language
construct, it is a post-condition loop. The body is executed first,
then the condition is evaluated.

Of course, that raises additional questions…

* Should a hypothetical ELisp ‘until’ macro implement a post-condition loop?
* If so, should the condition be passed as the last argument?
  * If so, how should indentation work? (indent the body 4 spaces,
condition 2 spaces?)
  * The macro will then have to take body and condition as a single
&rest list, and split it, right?



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

* Re: Why is there no `until' in elisp?
  2018-10-17  2:04     ` Stefan Monnier
@ 2018-10-17  9:14       ` Garreau, Alexandre
  2018-10-17 15:06         ` Stefan Monnier
  0 siblings, 1 reply; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17  9:14 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On 2018-10-16 at 22:04, Stefan Monnier wrote:
>> I think `until' should refer to the version I gave because this is
>> probably the one which is going to be implemented naively by most people,
>
> I completely reject this kind of argument.
>
> By that argument, we should avoid lexical scoping since dynamic scoping
> is "the one which is going to be implemented naively by most people".

I think you misunderstood me: that’d mean dynamic scoping is something
to implement and keep aside and not remove when implementing lexical
scoping, not that lexical scoping shouldn’t exist.  I said it, I find
your `until' very interesting, so it ought to exist even maybe with a
not-longer name.

It maybe could be an argument against default lexical scoping, while I’m
not against that (afaik it’s only for backward compatibility that emacs
keeps it as default right?), but then I think I should extend my
statement to support what independant experience says, and apply what I
said only to experiences about untested-enough things.

>> also it can be useful to try to retrieve the last body return
>> value, just as it is with `while':
>
> The body of those loops is made of side-effecting operations.
> Usually side-effecting operations don't have useful return values.

They might, but indeed less probably than the cond, so this is a point.
Yet I might notice a cond might usually return a simple t/nil boolean
(for instance when using comparison functions such as (< 1 2), which
keep returning t instead of one of its arguments), which, in case of
`until'/`while', will be known in advance.

>> And then, of course, this introduce useless discrepancy toward
>> symmetry within respect `while'.
>
> No discrepancy: it makes `until` return the value of its last test, just
> like `while` already does (with `while` that value is always nil).

No, `while' currently returns its last body, I just checked:
(let ((x 0)) (while (< x 5) (setq x (+ 1 x))) 8))

Anyway for the non-`while1'/non-`until1' (let’s call them
`whilen'/`untiln' for the sake of speaking) I was talking about a
default `while' (and `until') that would return its cond when there’s no
body, if the working is similar as to `progn' as I stated.



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

* Re: Why is there no `until' in elisp?
  2018-10-17  8:04   ` Yuri Khan
@ 2018-10-17  9:23     ` Garreau, Alexandre
  2018-10-17  9:46       ` Yuri Khan
  2018-10-17 12:41     ` Elias Mårtenson
  2018-10-17 15:03     ` Stefan Monnier
  2 siblings, 1 reply; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17  9:23 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Stefan Monnier, Emacs developers

On 2018-10-17 at 15:04, Yuri Khan wrote:
> In both these implementations, ‘until’ is still a pre-condition loop
> (same as ‘while’, but with the condition negated).

Something such as the C “do” construct might overcomplicate the
language, while I think normal `while' and `until' are not only simpler
but also superior: with those you have the case of 0 loops, in which
basically works as a when.

> However, in many languages that have an ‘until’ loop as a language
> construct, it is a post-condition loop. The body is executed first,
> then the condition is evaluated.

Which languages?  I looked again in bash to be sure, and bash doesn’t do
that.

> Of course, that raises additional questions…
>
> * Should a hypothetical ELisp ‘until’ macro implement a post-condition loop?

I find this a useless discrepancy, coming from inconsistent languages,
that shouldn’t be imported in elisp.  Which is less bad than others in
this respect.

> * If so, should the condition be passed as the last argument?

I guess so, it’d be confusing otherwise.  Yet from a low level
standpoint it’s not trivial (you need last arg of the linked list, but
you might just as well delay the problem by just using `progn'), but
this time I feel this stays elegant enough as the other form present no
real advantages.

>   * If so, how should indentation work? (indent the body 4 spaces,
> condition 2 spaces?)

I guess… can (indent …) declaration constructs allow that?

>   * The macro will then have to take body and condition as a single
> &rest list, and split it, right?

Yes I think.  Since here it’s a lot more crucial and important than a
basic side-effects / not-always-used thing such as `progn' (though if I
wanted to make `progn' look more functional I’d do the same for it, as
an option).

I’ve alway found sad that `defun' &args specs were not powerful enough
for this kind of things (&rest rest &optional last), or even supporting
docstrings (although that requires typing so…).



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

* Re: Why is there no `until' in elisp?
  2018-10-17  9:23     ` Garreau, Alexandre
@ 2018-10-17  9:46       ` Yuri Khan
  2018-10-17 11:06         ` Garreau, Alexandre
  2018-10-17 17:50         ` Paul Eggert
  0 siblings, 2 replies; 26+ messages in thread
From: Yuri Khan @ 2018-10-17  9:46 UTC (permalink / raw)
  To: galex-713; +Cc: Stefan Monnier, Emacs developers

On Wed, Oct 17, 2018 at 4:23 PM Garreau, Alexandre
<galex-713@galex-713.eu> wrote:
>
> Something such as the C “do” construct might overcomplicate the
> language, while I think normal `while' and `until' are not only simpler
> but also superior: with those you have the case of 0 loops, in which
> basically works as a when.

The post-condition loop enables the “at-least-once” case, which is
also occasionally useful, e.g.: Attempt an API call until it succeeds.

> > However, in many languages that have an ‘until’ loop as a language
> > construct, it is a post-condition loop. The body is executed first,
> > then the condition is evaluated.
>
> Which languages?  I looked again in bash to be sure, and bash doesn’t do
> that.

+ Well, you mentioned the C ‘do’/‘while’, for one; it is a
continuation post-condition loop. C++, Java, PHP, Javascript and many
other languages inherited that.
+ Pascal has ‘repeat’/‘until’ (a termination post-condition loop), and
it was my first association for the name ‘until’.
− Bash’s ‘until’/‘do’/‘done’ is a termination pre-condition loop, you’re right.
+ In Perl, both ‘while’ (continuation) and ‘until’ (termination) can
be used as pre-conditions and post-conditions.



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

* Re: Why is there no `until' in elisp?
  2018-10-17  9:46       ` Yuri Khan
@ 2018-10-17 11:06         ` Garreau, Alexandre
  2018-10-17 17:50         ` Paul Eggert
  1 sibling, 0 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17 11:06 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Stefan Monnier, Emacs developers

Le 17/10/2018 à 16h46, Yuri Khan a écrit :
> On Wed, Oct 17, 2018 at 4:23 PM Garreau, Alexandre
> <galex-713@galex-713.eu> wrote:
>>
>> Something such as the C “do” construct might overcomplicate the
>> language, while I think normal `while' and `until' are not only simpler
>> but also superior: with those you have the case of 0 loops, in which
>> basically works as a when.
>
> The post-condition loop enables the “at-least-once” case, which is
> also occasionally useful, e.g.: Attempt an API call until it succeeds.

(…or “until” a non-blocking I/O function blocks)

And no, there’s the no-body form of `while'/`until' which are handy for
that:

(until (call args))
(while (io args))

Or, if you need more instructions because your API is complex:

(until (progn (foo) (call args)))

(while (progn (bar) (io args)))

I’ve saw this form of code idiomatic in basic software such as
coreutils, inetutils, etc.

>> > However, in many languages that have an ‘until’ loop as a language
>> > construct, it is a post-condition loop. The body is executed first,
>> > then the condition is evaluated.
>>
>> Which languages?  I looked again in bash to be sure, and bash doesn’t do
>> that.
>
> + Well, you mentioned the C ‘do’/‘while’, for one; it is a
> continuation post-condition loop. C++, Java, PHP, Javascript and many
> other languages inherited that.
> + Pascal has ‘repeat’/‘until’ (a termination post-condition loop), and
> it was my first association for the name ‘until’.
> + In Perl, both ‘while’ (continuation) and ‘until’ (termination) can
> be used as pre-conditions and post-conditions.

The keyword is “can”.  There’s no “until cond do thing done” where the
until is placed before and by itself makes it a post-cond.  You usually
have a special keyword for trigering post-cond, such as “do” or
“repeat”.  Also “loop” in some language I forgot (basic? sql?)

I’m almost sure cl-loop has it.  So it’s even compatible with the last.

> − Bash’s ‘until’/‘do’/‘done’ is a termination pre-condition loop, you’re right.

Doesn’t one of the languages you mentioned have a “until” using a
pre-cond rather than a post-cond?



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

* Re: Why is there no `until' in elisp?
  2018-10-17  8:04   ` Yuri Khan
  2018-10-17  9:23     ` Garreau, Alexandre
@ 2018-10-17 12:41     ` Elias Mårtenson
  2018-10-17 15:03     ` Stefan Monnier
  2 siblings, 0 replies; 26+ messages in thread
From: Elias Mårtenson @ 2018-10-17 12:41 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Stefan Monnier, emacs-devel

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

On Wed, 17 Oct 2018, 16:06 Yuri Khan, <yurivkhan@gmail.com> wrote:

In both these implementations, ‘until’ is still a pre-condition loop
> (same as ‘while’, but with the condition negated).
>
> However, in many languages that have an ‘until’ loop as a language
> construct, it is a post-condition loop. The body is executed first,
> then the condition is evaluated.
>

Elisp already has the loop macro from CL which implements all of this, and
more. I honestly don't understand what this discussion is all about.

Since the desired functionality is already available, why try to define a
new API that won't do as much?

Regards,
Elias

>

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

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

* Re: Why is there no `until' in elisp?
  2018-10-17  8:04   ` Yuri Khan
  2018-10-17  9:23     ` Garreau, Alexandre
  2018-10-17 12:41     ` Elias Mårtenson
@ 2018-10-17 15:03     ` Stefan Monnier
  2 siblings, 0 replies; 26+ messages in thread
From: Stefan Monnier @ 2018-10-17 15:03 UTC (permalink / raw)
  To: Yuri Khan; +Cc: Emacs developers

> In both these implementations, ‘until’ is still a pre-condition loop
> (same as ‘while’, but with the condition negated).

No, the condition can be anywhere: (while (progn (before) (test)) (after))


        Stefan



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

* Re: Why is there no `until' in elisp?
  2018-10-17  9:14       ` Garreau, Alexandre
@ 2018-10-17 15:06         ` Stefan Monnier
  2018-10-17 16:51           ` Garreau, Alexandre
  0 siblings, 1 reply; 26+ messages in thread
From: Stefan Monnier @ 2018-10-17 15:06 UTC (permalink / raw)
  To: Garreau, Alexandre; +Cc: emacs-devel

> No, `while' currently returns its last body, I just checked:
> (let ((x 0)) (while (< x 5) (setq x (+ 1 x))) 8))

The 8 in your test case is outside of `while`, so it just shows what
`let` returns, not what `while` returns.  Try

    (let ((x 0)) (while (< x 5) (setq x (+ 1 x))))
or
    (let ((x 0)) (while (< x 5) (setq x (+ 1 x)) 8))


-- Stefan



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

* Re: Why is there no `until' in elisp?
  2018-10-17 15:06         ` Stefan Monnier
@ 2018-10-17 16:51           ` Garreau, Alexandre
  0 siblings, 0 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17 16:51 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Le 17/10/2018 à 11h06, Stefan Monnier a écrit :
>> No, `while' currently returns its last body, I just checked:
>> (let ((x 0)) (while (< x 5) (setq x (+ 1 x))) 8))
>
> The 8 in your test case is outside of `while`, so it just shows what
> `let` returns, not what `while` returns.  Try
>
>     (let ((x 0)) (while (< x 5) (setq x (+ 1 x))))
> or
>     (let ((x 0)) (while (< x 5) (setq x (+ 1 x)) 8))

My bad! yours lack a closing paren, but yes indeed you are right!



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

* Re: Why is there no `until' in elisp?
  2018-10-17  9:46       ` Yuri Khan
  2018-10-17 11:06         ` Garreau, Alexandre
@ 2018-10-17 17:50         ` Paul Eggert
  2018-10-17 21:15           ` Garreau, Alexandre
  1 sibling, 1 reply; 26+ messages in thread
From: Paul Eggert @ 2018-10-17 17:50 UTC (permalink / raw)
  To: Yuri Khan, galex-713; +Cc: Stefan Monnier, Emacs developers

On 10/17/18 2:46 AM, Yuri Khan wrote:
> + Pascal has ‘repeat’/‘until’ (a termination post-condition loop), and
> it was my first association for the name ‘until’.

Pascal did it right, for a reason I haven't seen mentioned in this 
thread. The natural tendency when reading a conditional is to assume 
that the condition will be true in the code that immediately follows the 
text of the condition. This works for (if C S) and (while C S), and it 
also works for Pascal's 'repeat S1 until C; S2' where C is true just 
before S2 is executed. It does not work for the confusing C syntax 'do 
S1 while (C); S2' where C is false just before S2 is executed. It also 
does not work for the proposed Elisp syntax (until C S), where C would 
be false just before S is executed. Because of this elementary 
psychological principle, the Elisp syntax for the proposed loop 
construct should *not* be (until C S).




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

* Re: Why is there no `until' in elisp?
  2018-10-17 17:50         ` Paul Eggert
@ 2018-10-17 21:15           ` Garreau, Alexandre
  2018-10-17 21:35             ` Paul Eggert
  0 siblings, 1 reply; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17 21:15 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Yuri Khan, Stefan Monnier, Emacs developers

On 2018-10-17 at 10:50, Paul Eggert wrote:
> On 10/17/18 2:46 AM, Yuri Khan wrote:
>> + Pascal has ‘repeat’/‘until’ (a termination post-condition loop), and
>> it was my first association for the name ‘until’.
>
> Pascal did it right, for a reason I haven't seen mentioned in this
> thread. The natural tendency when reading a conditional is to assume
> that the condition will be true in the code that immediately follows
> the text of the condition.

I disagree: what you say maybe is because we were used to it by
programming languages, or (wrongly) teached to (just as new programmers
nowadays learn to use a tons of useless temporary variables until they
forget what an “expression” is), but linguistically it perfectly makes
sense “until null repeat”:

#+BEGIN_SRC emacs-lisp
(until (zerop n)
  s)
#+END_SRC

Also, “while” we’re talking about programming, note how “while” as used
in natural language does *not* mean the same thing (as it express
contemporarity, not condition), because it is a lot less meaningful,
hence useful.  “While” is one of these artificial differently-meaning
constructs idiosyncratic to programming just as “else” (instead of
“otherwise”).

It is still more natural and meaningful to say “until I’m not hungry
anymore I eat” instead of “while I’m hungry I eat”, just as we’d prefer
to say “until mail finished, write” rather than “while mail not
finished, write”.  If “until” exists in english, it’s for a reason.  If
ever it gets different in anything conveying a meaning, it’s going to be
for a reason too, but as english exist since longer than pascal (though
it depends of what you mean by english and pascal x))…

> It does not work for the confusing C syntax 'do S1 while
> (C); S2' where C is false just before S2 is executed.

Because C implements no until, nor for pre nor post cond.

> It also does not work for the proposed Elisp syntax (until C S), where
> C would be false just before S is executed. 

In my mind this is wrong: we even should have the opposite, have when
based on until instead of the opposite.

> Pascal's 'repeat S1 until C; S2' where C is true just before S2 is
> executed.

> Because of this elementary psychological principle,

I believe post-cond should be at the discretion of the programmer and
not be an arbitrary language decision based on some non-reproducible
psychological subjective observation.

This might as well become a style guideline, but then I feel like it
should be explicitely stated and agreed upon before enforcing it in any
software.

> the Elisp syntax for the proposed loop construct should *not* be
> (until C S).

And what should it be then? (repeat S until C) (begins to feel like
foof-loop, then you could just go for foof-loop)? (until S C) (extremely
counterintuitive, as, in english, “until” *always* serves as a
*preposition* to what it is about)?



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

* Re: Why is there no `until' in elisp?
  2018-10-17 21:15           ` Garreau, Alexandre
@ 2018-10-17 21:35             ` Paul Eggert
  2018-10-17 21:49               ` Garreau, Alexandre
  0 siblings, 1 reply; 26+ messages in thread
From: Paul Eggert @ 2018-10-17 21:35 UTC (permalink / raw)
  To: Garreau, Alexandre; +Cc: Yuri Khan, Stefan Monnier, Emacs developers

On 10/17/18 2:15 PM, Garreau, Alexandre wrote:
> “while” as used in natural language does *not* mean the same thing

Yes, of course. And the same is true for "until". But I'm not objecting 
to the keyword's spelling: I'm objecting to a syntax where a condition C 
is placed immediately before a place where C is false. This is 
confusing! When I read "C" I should be mentally thinking "OK, now C is 
true". This is elementary notation design.


> It is still more natural and meaningful to say “until I’m not hungry
> anymore I eat” instead of “while I’m hungry I eat”,

Not at all. Most English-speakers would say that the latter is far more 
readable.


>> the Elisp syntax for the proposed loop construct should *not* be
>> (until C S).
> And what should it be then?
Why not use cl-loop? Although it's not perfect it's good enough, and 
it's better than introducing a seemingly-simple but deeply confusing syntax.



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

* Re: Why is there no `until' in elisp?
  2018-10-17 21:35             ` Paul Eggert
@ 2018-10-17 21:49               ` Garreau, Alexandre
  2018-10-17 22:33                 ` Paul Eggert
  0 siblings, 1 reply; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17 21:49 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Yuri Khan, Stefan Monnier, Emacs developers

Le 17/10/2018 à 14h35, Paul Eggert a écrit :
> On 10/17/18 2:15 PM, Garreau, Alexandre wrote:
>> “while” as used in natural language does *not* mean the same thing
>
> […] And the same is true for "until".

How’s that?

> But I'm not objecting to the keyword's spelling: I'm objecting to a
> syntax where a condition C is placed immediately before a place where
> C is false. This is confusing! When I read "C" I should be mentally
> thinking "OK, now C is true". This is elementary notation design.

I’m not.  If it works in english such as “until you have money you will
not be able to buy it” I don’t see the problem.

>> It is still more natural and meaningful to say “until I’m not hungry
>> anymore I eat” instead of “while I’m hungry I eat”,
>
> Not at all. Most English-speakers would say that the latter is far
> more readable.

Certainly more readable, because it is simpler.  But how about *more
natural*?  I find “until” be a lot more used in all the languages I
know, including english.

>>> the Elisp syntax for the proposed loop construct should *not* be
>>> (until C S).
>>
>> And what should it be then?
>
> Why not use cl-loop? Although it's not perfect it's good enough, and
> it's better than introducing a seemingly-simple but deeply confusing
> syntax.

The most obvious and only implementation of `unless', I ever seen *until
now* is (while (not cond) body) (see how this sentence breaked your rule
while being the more natural formulation).  It’s only subjectively, thus
seemingly, deeply confusing, thus “not perfect” as well, yet “good
enough” in my mind, so to make programs easier to read and write, while
cl-loop is deeply, not only seemingly, complex, especially about its
syntax: so it’s the other way around I’d say (though cl-loop too accepts
both post- and pre-cond afaik).



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

* Re: Why is there no `until' in elisp?
  2018-10-17 21:49               ` Garreau, Alexandre
@ 2018-10-17 22:33                 ` Paul Eggert
  2018-10-17 22:54                   ` Garreau, Alexandre
  0 siblings, 1 reply; 26+ messages in thread
From: Paul Eggert @ 2018-10-17 22:33 UTC (permalink / raw)
  To: Garreau, Alexandre; +Cc: Yuri Khan, Stefan Monnier, Emacs developers

On 10/17/18 2:49 PM, Garreau, Alexandre wrote:
> Le 17/10/2018 à 14h35, Paul Eggert a écrit :
>> On 10/17/18 2:15 PM, Garreau, Alexandre wrote:
>>> “while” as used in natural language does *not* mean the same thing
>> […] And the same is true for "until".
> How’s that?


In English, "until Y do X" typically means "keep checking Y while you're 
doing X and stop the instant that Y becomes true". This means something 
different from the proposed (until Y X), for the same reason that the 
common meaning of "while Y do X" in English means something different 
from (while Y X).


>
> I find “until” be a lot more used in all the languages I
> know, including english.

Although that might be true in other languages, it's certainly not true 
of English. Google, for example, reports about 8 billion hits for 
"while" but only 2 billion for "until". Admittedly Google hit counts are 
only vaguely approximate, but still....


>
> The most obvious and only implementation of `unless', I ever seen *until
> now* is (while (not cond) body)

"unless" is something different from "until". Anyway, we're not making 
much progress here; feel free to have the last word.




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

* Re: Why is there no `until' in elisp?
  2018-10-17 22:33                 ` Paul Eggert
@ 2018-10-17 22:54                   ` Garreau, Alexandre
  0 siblings, 0 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-17 22:54 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Yuri Khan, Stefan Monnier, Emacs developers

On 2018-10-17 at 15:33, Paul Eggert wrote:
> On 10/17/18 2:49 PM, Garreau, Alexandre wrote:
>> Le 17/10/2018 à 14h35, Paul Eggert a écrit :
>>> On 10/17/18 2:15 PM, Garreau, Alexandre wrote:
>>>> “while” as used in natural language does *not* mean the same thing
>>> […] And the same is true for "until".
>> How’s that?
>
> In English, "until Y do X" typically means "keep checking Y while
> you're doing X and stop the instant that Y becomes true". This means
> something different from the proposed (until Y X), for the same reason
> that the common meaning of "while Y do X" in English means something
> different from (while Y X).

Really?  I thought it meant the same as “do X until Y” or “do X and stop
doing X when Y is true”, which to me seems the same.

While “while” seems to me to have some notion of contemporarity of the
two actions / expressions / etc., so it feels different to me, but
eventually I am to believe you.

>> I find “until” be a lot more used in all the languages I
>> know, including english.
>
> Although that might be true in other languages, it's certainly not
> true of English. Google, for example, reports about 8 billion hits for
> "while" but only 2 billion for "until". Admittedly Google hit counts
> are only vaguely approximate, but still....

Okay, you convinced me now (I get 6M and 2M).

>> The most obvious and only implementation of `unless', I ever seen *until
>> now* is (while (not cond) body)
>
> "unless" is something different from "until".

My bad, I made a mistake: I wanted to say `until' (as could show the
following expression).



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

* Re: Why is there no `until' in elisp?
  2018-10-16 19:16 ` Eric Abrahamsen
  2018-10-16 19:31   ` Garreau, Alexandre
@ 2018-10-19 15:28   ` Stefan Monnier
  1 sibling, 0 replies; 26+ messages in thread
From: Stefan Monnier @ 2018-10-19 15:28 UTC (permalink / raw)
  To: emacs-devel

> I have nothing to do with this, but my feeling is that Lisp developers
> in general drag their feet about adding trivial/obvious constructs to
> the standard library. As your footnote makes clear, it's a two-line code
> addition to make `until' work. There are different schools of thought
> about this: one that says "why?", and one that says "why not"? The "why
> not"s contribute to subr.el and subr-x.el :)

Personally, I grew fond of `until` and wanted to add it (even went to
the trouble of writing the corresponding byte-compiler code), but really
in 99% of the cases, you can just negate the test so the benefit
in minuscule.  But if we could go back in time, then I would definitely
replace `while` with `until`.


        Stefan




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

* Re: Why is there no `until' in elisp?
  2018-10-17  0:12   ` Garreau, Alexandre
  2018-10-17  2:04     ` Stefan Monnier
@ 2018-10-19 15:34     ` Stefan Monnier
  2018-10-19 18:08       ` Garreau, Alexandre
  1 sibling, 1 reply; 26+ messages in thread
From: Stefan Monnier @ 2018-10-19 15:34 UTC (permalink / raw)
  To: emacs-devel

> think `until' should refer to the version I gave because this is
> probably the one which is going to be implemented naively by most
> people,

BTW, this is only true if those people have to implement it on top of
the pre-existing `while`.  Once you go down to implementing it as
a sequence of byte-codes, then the `until` you proposed is no simpler
than the one I proposed.

So reversing your argument, if Elisp had my `until` and you wanted to
define `while` would you define it to return nil or to return t?
IOW would you define it as

    (defmacro while (test &rest body)
      `(until (not ,test) ,@body))
or
    (defmacro while (test &rest body)
      `(progn (until (not ,test) ,@body) nil))

?


        Stefan




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

* Re: Why is there no `until' in elisp?
  2018-10-19 15:34     ` Stefan Monnier
@ 2018-10-19 18:08       ` Garreau, Alexandre
  0 siblings, 0 replies; 26+ messages in thread
From: Garreau, Alexandre @ 2018-10-19 18:08 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

On 2018-10-19 at 11:34, Stefan Monnier wrote:
>> think `until' should refer to the version I gave because this is
>> probably the one which is going to be implemented naively by most
>> people,
>
> BTW, this is only true if those people have to implement it on top of
> the pre-existing `while`.  Once you go down to implementing it as
> a sequence of byte-codes, then the `until` you proposed is no simpler
> than the one I proposed.
>
> So reversing your argument, if Elisp had my `until` and you wanted to
> define `while` would you define it to return nil or to return t?
> IOW would you define it as
>
>     (defmacro while (test &rest body)
>       `(until (not ,test) ,@body))
> or
>     (defmacro while (test &rest body)
>       `(progn (until (not ,test) ,@body) nil))
>
> ?

The former, you’re right.  What I was saying was mainly to keep
consistence, only then I was finding that, for me, returning the body of
a loop looks more logical than returning its condition (as you said,
this only makes sense for until).  But now I saw the working of `while'
match the semantics you gave, I believe your version is better to be
implemented, in elisp.



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

end of thread, other threads:[~2018-10-19 18:08 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-16 17:42 Why is there no `until' in elisp? Garreau, Alexandre
2018-10-16 19:16 ` Eric Abrahamsen
2018-10-16 19:31   ` Garreau, Alexandre
2018-10-16 20:23     ` Eric Abrahamsen
2018-10-16 23:00       ` Garreau, Alexandre
2018-10-19 15:28   ` Stefan Monnier
2018-10-16 21:28 ` Stefan Monnier
2018-10-17  0:12   ` Garreau, Alexandre
2018-10-17  2:04     ` Stefan Monnier
2018-10-17  9:14       ` Garreau, Alexandre
2018-10-17 15:06         ` Stefan Monnier
2018-10-17 16:51           ` Garreau, Alexandre
2018-10-19 15:34     ` Stefan Monnier
2018-10-19 18:08       ` Garreau, Alexandre
2018-10-17  8:04   ` Yuri Khan
2018-10-17  9:23     ` Garreau, Alexandre
2018-10-17  9:46       ` Yuri Khan
2018-10-17 11:06         ` Garreau, Alexandre
2018-10-17 17:50         ` Paul Eggert
2018-10-17 21:15           ` Garreau, Alexandre
2018-10-17 21:35             ` Paul Eggert
2018-10-17 21:49               ` Garreau, Alexandre
2018-10-17 22:33                 ` Paul Eggert
2018-10-17 22:54                   ` Garreau, Alexandre
2018-10-17 12:41     ` Elias Mårtenson
2018-10-17 15:03     ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).