unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* humble proposal: New special form progn-1
@ 2016-07-27 12:16 Tino Calancha
  2016-07-27 12:22 ` Stefan Monnier
                   ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Tino Calancha @ 2016-07-27 12:16 UTC (permalink / raw)
  To: emacs-devel


Dear all,

i got this idea few days ago (see the patch at the end).

Even though I envision that no one here will like this proposal,
for me it's instructive to learn from your answers why this is
not a good idea.

So, why is this a bad idea?

Thanks in advance for your answer,
Tino


My (weak) motivation for introduce this is:

* Compact (and familiar) syntaxis.
* Same reasons to exists as prog2 has (excluding historical reasons).
* Other way to acomplish one usual task.
* Allow lower indentation level (see below):

(progn-1
  (form1)
  (form2)
  (form3)
  .
  .
  .
  (formN-1)
  (formN))

(prog1
     (progn
       (form1)
       (form2)
       (form3)
       .
       .
       .
       (formN-1))
   (formN))

(prog2
     (progn
       (form1)
       (form2)
       (form3)
       .
       .
       .
       (formN-2))
     (prog1
       (formN-1)
       (formN)))

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
From c9b38c42b253ca004c3aef4dd9dde274aa717d91 Mon Sep 17 00:00:00 2001
From: Tino Calancha <tino.calancha@gmail.com>
Date: Wed, 27 Jul 2016 20:40:25 +0900
Subject: [PATCH] New special form progn-1

* src/eval.c (progn-1): Eval sequentially N forms and
return the value of the form N-1.
---
  src/eval.c | 18 ++++++++++++++++++
  1 file changed, 18 insertions(+)

diff --git a/src/eval.c b/src/eval.c
index 33b82f7..5eb0cfd 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -431,6 +431,23 @@ usage: (progn BODY...)  */)
    return val;
  }

+DEFUN ("progn-1", Fprogn_1, Sprogn_1, 2, UNEVALLED, 0,
+       doc: /* Eval N forms sequentially; return value from form N-1.
+usage: (progn-1 FORM_1 FORM_2...FORM_N-1 FORM_N)  */)
+  (Lisp_Object body)
+{
+  Lisp_Object val = Qnil;
+
+  while (CONSP (XCDR (body)))
+    {
+      val = eval_sub (XCAR (body));
+      body = XCDR (body);
+    }
+  eval_sub (XCAR (body));
+
+  return val;
+}
+
  /* Evaluate BODY sequentially, discarding its value.  Suitable for
     record_unwind_protect.  */

@@ -3906,6 +3923,7 @@ alist of active lexical bindings.  */);
    defsubr (&Sif);
    defsubr (&Scond);
    defsubr (&Sprogn);
+  defsubr (&Sprogn_1);
    defsubr (&Sprog1);
    defsubr (&Sprog2);
    defsubr (&Ssetq);
-- 
2.8.1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

In GNU Emacs 25.1.50.1 (x86_64-pc-linux-gnu, GTK+ Version 3.20.6)
  of 2016-07-27 built
Repository revision: e0d425976e3a83585db9a586687897fe1ac6455f




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

* Re: humble proposal: New special form progn-1
  2016-07-27 12:16 humble proposal: New special form progn-1 Tino Calancha
@ 2016-07-27 12:22 ` Stefan Monnier
  2016-07-27 12:53 ` Andreas Schwab
  2016-07-27 14:08 ` Clément Pit--Claudel
  2 siblings, 0 replies; 12+ messages in thread
From: Stefan Monnier @ 2016-07-27 12:22 UTC (permalink / raw)
  To: emacs-devel

> (progn-1
>   (form1)
>   .
>   .
>   (formN-1)
>   (formN))

Shouldn't that be

> (progn-1
>     (form1)
>     .
>     .
>     (formN-1)
>   (formN))

to follow the usual convention of prog1, prog2, ... ?
If so, we also need a patch for the indentation code.

> +DEFUN ("progn-1", Fprogn_1, Sprogn_1, 2, UNEVALLED, 0,

All special forms need support in the compiler as well.


        Stefan




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

* Re: humble proposal: New special form progn-1
  2016-07-27 12:16 humble proposal: New special form progn-1 Tino Calancha
  2016-07-27 12:22 ` Stefan Monnier
@ 2016-07-27 12:53 ` Andreas Schwab
  2016-07-27 13:58   ` Tino Calancha
  2016-07-27 14:08 ` Clément Pit--Claudel
  2 siblings, 1 reply; 12+ messages in thread
From: Andreas Schwab @ 2016-07-27 12:53 UTC (permalink / raw)
  To: Tino Calancha; +Cc: emacs-devel

On Mi, Jul 27 2016, Tino Calancha <tino.calancha@gmail.com> wrote:

> * Other way to acomplish one usual task.

How usual is that task?

> * Allow lower indentation level (see below):
>
> (progn-1
>   (form1)
>   (form2)
>   (form3)
>   .
>   .
>   .
>   (formN-1)
>   (formN))

(progn
  (form1)
  ...
  (prog1
      (formN-1)
    (formN)))

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."



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

* Re: humble proposal: New special form progn-1
  2016-07-27 12:53 ` Andreas Schwab
@ 2016-07-27 13:58   ` Tino Calancha
  2016-07-27 16:04     ` Andreas Schwab
  0 siblings, 1 reply; 12+ messages in thread
From: Tino Calancha @ 2016-07-27 13:58 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: emacs-devel, Tino Calancha



On Wed, 27 Jul 2016, Andreas Schwab wrote:

> On Mi, Jul 27 2016, Tino Calancha <tino.calancha@gmail.com> wrote:
>
>> * Other way to acomplish one usual task.
>
> How usual is that task?
I will estimate it:
Running following command on lisp dir:

find lisp -type f -exec grep --color -InH -e regexp \{\} +

1) regexp = '(prog1 '
    matches: 462
2) regexp = '(prog2 '
    matches: 20
3) regexp = '(progn '
    matches: 2262

I would say similar order of magnitude as 1), i.e.,  ~ 20% of 3)



>> * Allow lower indentation level (see below):
>>
>> (progn-1
>>   (form1)
>>   (form2)
>>   (form3)
>>   .
>>   .
>>   .
>>   (formN-1)
>>   (formN))
>
> (progn
>  (form1)
>  ...
>  (prog1
>      (formN-1)
>    (formN)))
>
Its also nice; maybe slightly more readable the first one.
You know, it's matter of taste: 2 forms VS 1 form, like:
(let ((i 1)
       (j 2))
   (form))

compared with:

(let ((i 1))
   (let ((j 2))
     (form)))

Tino



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

* Re: humble proposal: New special form progn-1
  2016-07-27 12:16 humble proposal: New special form progn-1 Tino Calancha
  2016-07-27 12:22 ` Stefan Monnier
  2016-07-27 12:53 ` Andreas Schwab
@ 2016-07-27 14:08 ` Clément Pit--Claudel
  2016-07-27 14:30   ` Phil Sainty
  2016-07-27 14:38   ` Tino Calancha
  2 siblings, 2 replies; 12+ messages in thread
From: Clément Pit--Claudel @ 2016-07-27 14:08 UTC (permalink / raw)
  To: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 2590 bytes --]

On 2016-07-27 08:16, Tino Calancha wrote:
> Dear all,
> 
> i got this idea few days ago (see the patch at the end).
> 
> Even though I envision that no one here will like this proposal,
> for me it's instructive to learn from your answers why this is
> not a good idea.

:) I don't have anything strongly against it myself. Any reason to not make it a lisp macro though?

> My (weak) motivation for introduce this is:
> 
> * Compact (and familiar) syntaxis.
> * Same reasons to exists as prog2 has (excluding historical reasons).
> * Other way to acomplish one usual task.
> * Allow lower indentation level (see below):

Sounds good. One worry that I have with the name is that I read it as (progn)-(1), not prog(n-1).

But in any case, maybe it would be best to make it a lisp macro first?

> ...
> (prog2
>     (progn
>       (form1)
>       (form2)
>       (form3)
>       .
>       .
>       .
>       (formN-2))
>     (prog1
>       (formN-1)
>       (formN)))


Wouldn't 
(progn 
  (form1)
  ...
  (formN-2)
  (prog1
    (formN-1)
    (formN)))
work?

Cheers,
Clément.

> ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
>> From c9b38c42b253ca004c3aef4dd9dde274aa717d91 Mon Sep 17 00:00:00 2001
> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Wed, 27 Jul 2016 20:40:25 +0900
> Subject: [PATCH] New special form progn-1
> 
> * src/eval.c (progn-1): Eval sequentially N forms and
> return the value of the form N-1.
> ---
>  src/eval.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
> 
> diff --git a/src/eval.c b/src/eval.c
> index 33b82f7..5eb0cfd 100644
> --- a/src/eval.c
> +++ b/src/eval.c
> @@ -431,6 +431,23 @@ usage: (progn BODY...)  */)
>    return val;
>  }
> 
> +DEFUN ("progn-1", Fprogn_1, Sprogn_1, 2, UNEVALLED, 0,
> +       doc: /* Eval N forms sequentially; return value from form N-1.
> +usage: (progn-1 FORM_1 FORM_2...FORM_N-1 FORM_N)  */)
> +  (Lisp_Object body)
> +{
> +  Lisp_Object val = Qnil;
> +
> +  while (CONSP (XCDR (body)))
> +    {
> +      val = eval_sub (XCAR (body));
> +      body = XCDR (body);
> +    }
> +  eval_sub (XCAR (body));
> +
> +  return val;
> +}
> +
>  /* Evaluate BODY sequentially, discarding its value.  Suitable for
>     record_unwind_protect.  */
> 
> @@ -3906,6 +3923,7 @@ alist of active lexical bindings.  */);
>    defsubr (&Sif);
>    defsubr (&Scond);
>    defsubr (&Sprogn);
> +  defsubr (&Sprogn_1);
>    defsubr (&Sprog1);
>    defsubr (&Sprog2);
>    defsubr (&Ssetq);


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: humble proposal: New special form progn-1
  2016-07-27 14:08 ` Clément Pit--Claudel
@ 2016-07-27 14:30   ` Phil Sainty
  2016-07-27 15:15     ` Drew Adams
  2016-07-27 14:38   ` Tino Calancha
  1 sibling, 1 reply; 12+ messages in thread
From: Phil Sainty @ 2016-07-27 14:30 UTC (permalink / raw)
  To: emacs-devel

Or the idea could be generalised to:

(progn- offset &rest body)
(prog0+ offset &rest body)

I think code readability potentially suffers with any of
these ideas, mind.




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

* Re: humble proposal: New special form progn-1
  2016-07-27 14:08 ` Clément Pit--Claudel
  2016-07-27 14:30   ` Phil Sainty
@ 2016-07-27 14:38   ` Tino Calancha
  2016-07-27 19:07     ` Clément Pit--Claudel
  1 sibling, 1 reply; 12+ messages in thread
From: Tino Calancha @ 2016-07-27 14:38 UTC (permalink / raw)
  To: Clément Pit--Claudel; +Cc: emacs-devel

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



On Wed, 27 Jul 2016, Clément Pit--Claudel wrote:

> On 2016-07-27 08:16, Tino Calancha wrote:
>> Dear all,
>>
>> i got this idea few days ago (see the patch at the end).
>>
>> Even though I envision that no one here will like this proposal,
>> for me it's instructive to learn from your answers why this is
>> not a good idea.
>
> :) I don't have anything strongly against it myself. Any reason to not make it a lisp macro though?
>
>> My (weak) motivation for introduce this is:
>>
>> * Compact (and familiar) syntaxis.
>> * Same reasons to exists as prog2 has (excluding historical reasons).
>> * Other way to acomplish one usual task.
>> * Allow lower indentation level (see below):
>
> Sounds good. One worry that I have with the name is that I read it as (progn)-(1), not prog(n-1).
You mean that could confuse some people that is like:
(1- (progn (form)))
I still like progn-1 more because naturally fit in the sequence:
prog1, prog2, ..., progn


> Wouldn't
> (progn
>  (form1)
>  ...
>  (formN-2)
>  (prog1
>    (formN-1)
>    (formN)))
> work?
Of course does.  I didn't claim i exhausted the casuistic :-)
Thank you!

Tino

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

* RE: humble proposal: New special form progn-1
  2016-07-27 14:30   ` Phil Sainty
@ 2016-07-27 15:15     ` Drew Adams
  2016-07-28 11:35       ` Tino Calancha
  0 siblings, 1 reply; 12+ messages in thread
From: Drew Adams @ 2016-07-27 15:15 UTC (permalink / raw)
  To: Phil Sainty, emacs-devel

FWIW -

I would have no use for that, and I would find code that uses it
harder to read than what I would normally write.

In fact, I rarely use `prog1', `prog2', or `progn' - less than 0.1%
of code lines for `prog1', .02% for `prog2', and 0.5% for `progn'.

And all of the `prog2' lines, and some of the others, are only for
code that mirrors some code distributed by Emacs (e.g., so that
subsequent updates/diffs are easier).  IOW, it's really someone
else's ugly code. ;-)

I use `prog1' for the swapping idiom (which might be clearer as a
`swap-values' macro, but which is ingrained in me and easy to see):

 (setq start  (prog1 end (setq end  start)))

and sometimes for a return-value computation that is followed by
some side effect such as showing a message.

But for most cases where someone else might use `prog1' I'm already
let-binding a variable that I use for the value that might otherwise
be returned by the `prog1' (or by a `prog2').

 (let (... result) ... (setq result ...) ... result)

And I rarely use `progn' with `if', preferring `when', `unless',
`and', `or', or `cond' for most such use cases.

Just one opinion.



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

* Re: humble proposal: New special form progn-1
  2016-07-27 13:58   ` Tino Calancha
@ 2016-07-27 16:04     ` Andreas Schwab
  0 siblings, 0 replies; 12+ messages in thread
From: Andreas Schwab @ 2016-07-27 16:04 UTC (permalink / raw)
  To: Tino Calancha; +Cc: emacs-devel

On Mi, Jul 27 2016, Tino Calancha <tino.calancha@gmail.com> wrote:

> On Wed, 27 Jul 2016, Andreas Schwab wrote:
>
>> On Mi, Jul 27 2016, Tino Calancha <tino.calancha@gmail.com> wrote:
>>
>>> * Other way to acomplish one usual task.
>>
>> How usual is that task?
> I will estimate it:
> Running following command on lisp dir:

I was asking about progn-1.  I don't see much use case for it.

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."



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

* Re: humble proposal: New special form progn-1
  2016-07-27 14:38   ` Tino Calancha
@ 2016-07-27 19:07     ` Clément Pit--Claudel
  2016-07-27 21:51       ` Nicolas Petton
  0 siblings, 1 reply; 12+ messages in thread
From: Clément Pit--Claudel @ 2016-07-27 19:07 UTC (permalink / raw)
  To: Tino Calancha; +Cc: emacs-devel


[-- Attachment #1.1: Type: text/plain, Size: 588 bytes --]

On 2016-07-27 10:38, Tino Calancha wrote:
> You mean that could confuse some people that is like:
> (1- (progn (form)))
> I still like progn-1 more because naturally fit in the sequence:
> prog1, prog2, ..., progn

No, that's not what I meant. I meant that in Lisp when I want to write (n - 1) I actually write (- n 1); thus, when I see progn-1, I don't read it as "prog (n minus 1)", but instead as "progn dash 1". Given the convention that foo-1 usually means "internal function used in the implementation of foo", I read it as "internal function used to implement progn".




[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

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

* Re: humble proposal: New special form progn-1
  2016-07-27 19:07     ` Clément Pit--Claudel
@ 2016-07-27 21:51       ` Nicolas Petton
  0 siblings, 0 replies; 12+ messages in thread
From: Nicolas Petton @ 2016-07-27 21:51 UTC (permalink / raw)
  To: Clément Pit--Claudel, Tino Calancha; +Cc: emacs-devel

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

Clément Pit--Claudel <clement.pit@gmail.com> writes:

Hi Clément,

> Given the convention that foo-1 usually means "internal function used
> in the implementation of foo", I read it as "internal function used to
> implement progn".

I agree with you.

Cheers,
Nico

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 512 bytes --]

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

* RE: humble proposal: New special form progn-1
  2016-07-27 15:15     ` Drew Adams
@ 2016-07-28 11:35       ` Tino Calancha
  0 siblings, 0 replies; 12+ messages in thread
From: Tino Calancha @ 2016-07-28 11:35 UTC (permalink / raw)
  To: emacs-devel

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



On Wed, 27 Jul 2016, Drew Adams wrote:

> and sometimes for a return-value computation that is followed by
> some side effect such as showing a message.
>
> But for most cases where someone else might use `prog1' I'm already
> let-binding a variable that I use for the value that might otherwise
> be returned by the `prog1' (or by a `prog2').
>
> (let (... result) ... (setq result ...) ... result)

Yeah, i also like binding one 'result' variable: this way
all defun's in the code sistematically return
the last evaluated form.  Its easier to read.

On Wed, 27 Jul 2016, Clément Pit--Claudel wrote:
>No, that's not what I meant. I meant that in Lisp when I want to write
>(n - 1) I actually write (- n 1); thus, when I see progn-1,
>I don't read it as "prog (n minus 1)", but instead as "progn dash 1".
>Given the convention that foo-1 usually means
>"internal function used in the implementation of foo",
>I read it as "internal function used to implement progn".

This is another point against my proposal: the notation could be 
misleading.

So, i give up with my proposal.
Thank you very much.

Tino

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

end of thread, other threads:[~2016-07-28 11:35 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-27 12:16 humble proposal: New special form progn-1 Tino Calancha
2016-07-27 12:22 ` Stefan Monnier
2016-07-27 12:53 ` Andreas Schwab
2016-07-27 13:58   ` Tino Calancha
2016-07-27 16:04     ` Andreas Schwab
2016-07-27 14:08 ` Clément Pit--Claudel
2016-07-27 14:30   ` Phil Sainty
2016-07-27 15:15     ` Drew Adams
2016-07-28 11:35       ` Tino Calancha
2016-07-27 14:38   ` Tino Calancha
2016-07-27 19:07     ` Clément Pit--Claudel
2016-07-27 21:51       ` Nicolas Petton

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).