unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* Add internal definitions to derived forms
@ 2022-11-09 15:32 Linus Björnstam
  2022-11-09 15:46 ` Damien Mattei
                   ` (2 more replies)
  0 siblings, 3 replies; 22+ messages in thread
From: Linus Björnstam @ 2022-11-09 15:32 UTC (permalink / raw)
  To: guile-devel

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

Hi there!

This commit adds internal definitions to derived conditional forms, with-fluids and and-let*. This means the bodies of when, unless and with-fluids, and the clause bodies of case and cond behave like a lambda body. 

There is no performance hit since guile optimizes a (let () ...) without internal definitions to a begin (i.e: no new lexical context is created).

best regards
  Linus Björnstam

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-internal-definitions-to-derived-forms.patch --]
[-- Type: text/x-patch; name="0001-Add-internal-definitions-to-derived-forms.patch", Size: 6347 bytes --]

From 7eeb91b822334b151c5b4a15ce9528a2a655d914 Mon Sep 17 00:00:00 2001
From: Linus <bjornstam.linus@fastmail.se>
Date: Wed, 9 Nov 2022 16:15:18 +0100
Subject: [PATCH] Add internal definitions to derived forms

This commit adds internal definitions to the following derived
forms: when, unless, cond, case, with-fluids, and and-let*.

 * doc/ref/api-control.texi (Conditionals): Update the syntax and docs
   of when, unless, cond, and case.
 * module/ice-9/and-let-star.scm (and-let*): Changed begins to let.
 * module/ice-9/boot-9.scm (cond, case, when, unless, with-fluids):
   Changed begins to let.
---
 doc/ref/api-control.texi      | 25 +++++++++++++------------
 module/ice-9/and-let-star.scm |  6 +++---
 module/ice-9/boot-9.scm       | 12 ++++++------
 3 files changed, 22 insertions(+), 21 deletions(-)

diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index 087e795..ece6a60 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -152,10 +152,10 @@ documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless test stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 @end example
 
 That is to say, @code{when} evaluates its consequent statements in order
@@ -167,11 +167,11 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{expression} @dots{})
+(@var{test} @var{body} @dots{})
 @end lisp
 
-where @var{test} and @var{expression} are arbitrary expressions, or like
-this
+where @var{test} is an arbitrary expression and @var{body} is a
+lambda-like body, or like this
 
 @lisp
 (@var{test} => @var{expression})
@@ -217,7 +217,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
+((@var{datum1} @dots{}) @var{body} @dots{})
 @end lisp
 
 or
@@ -229,7 +229,7 @@ or
 and the last @var{clause} may have the form
 
 @lisp
-(else @var{expr1} @var{expr2} @dots{})
+(else @var{expr1} @var{body} @dots{})
 @end lisp
 
 or
@@ -239,13 +239,14 @@ or
 @end lisp
 
 All @var{datum}s must be distinct.  First, @var{key} is evaluated.  The
-result of this evaluation is compared against all @var{datum} values using
-@code{eqv?}.  When this comparison succeeds, the expression(s) following
-the @var{datum} are evaluated from left to right, returning the value of
-the last expression as the result of the @code{case} expression.
+result of this evaluation is compared against all @var{datum} values
+using @code{eqv?}.  When this comparison succeeds, the @var{body}
+following the @var{datum} is evaluated like the body of a lambda,
+returning the value of the last expression as the result of the
+@code{case} expression.
 
 If the @var{key} matches no @var{datum} and there is an
-@code{else}-clause, the expressions following the @code{else} are
+@code{else}-clause, the @var{body} following the @code{else} is
 evaluated.  If there is no such clause, the result of the expression is
 unspecified.
 
diff --git a/module/ice-9/and-let-star.scm b/module/ice-9/and-let-star.scm
index 2d53ff3..9427c17 100644
--- a/module/ice-9/and-let-star.scm
+++ b/module/ice-9/and-let-star.scm
@@ -53,12 +53,12 @@
       ((_ orig-form ((var expr)) . body)
        (identifier? #'var)
        #'(let ((var expr))
-           (and var (begin . body))))
+           (and var (let () . body))))
       ((_ orig-form ((expr)) . body)
-       #'(and expr (begin . body)))
+       #'(and expr (let () . body)))
       ((_ orig-form (var) . body)
        (identifier? #'var)
-       #'(and var (begin . body)))
+       #'(and var (let () . body)))
 
       ;; Handle bad clauses.
       ((_ orig-form (bad-clause . rest) . body)
diff --git a/module/ice-9/boot-9.scm b/module/ice-9/boot-9.scm
index a46145e..dc35370 100644
--- a/module/ice-9/boot-9.scm
+++ b/module/ice-9/boot-9.scm
@@ -417,10 +417,10 @@ If returning early, return the return value of F."
 (include-from-path "ice-9/quasisyntax")
 
 (define-syntax-rule (when test stmt stmt* ...)
-  (if test (begin stmt stmt* ...)))
+  (if test (let () stmt stmt* ...)))
 
 (define-syntax-rule (unless test stmt stmt* ...)
-  (if (not test) (begin stmt stmt* ...)))
+  (if (not test) (let () stmt stmt* ...)))
 
 (define-syntax else
   (lambda (x)
@@ -461,7 +461,7 @@ If returning early, return the return value of F."
                          ((else e e* ...)
                           (lambda (tail)
                             (if (null? tail)
-                                #'((begin e e* ...))
+                                #'((let () e e* ...))
                                 (bad-clause "else must be the last clause"))))
                          ((else . _) (bad-clause))
                          ((test => receiver)
@@ -488,7 +488,7 @@ If returning early, return the return value of F."
                          ((test e e* ...)
                           (lambda (tail)
                             #`((if test
-                                   (begin e e* ...)
+                                   (let () e e* ...)
                                    #,@tail))))
                          (_ (bad-clause))))
                      #'(clause clauses ...))))))))
@@ -534,7 +534,7 @@ If returning early, return the return value of F."
                                ((=> receiver ...)
                                 (bad-clause
                                  "wrong number of receiver expressions"))
-                               ((e e* ...) #'(begin e e* ...))
+                               ((e e* ...) #'(let () e e* ...))
                                (_ (bad-clause)))))
                          (syntax-case #'test (else)
                            ((datums ...)
@@ -674,7 +674,7 @@ If returning early, return the return value of F."
          #`(let ((fluid-tmp fluid) ...)
              (let ((val-tmp val) ...)
                #,(emit-with-fluids #'((fluid-tmp val-tmp) ...)
-                                   #'(begin exp exp* ...)))))))))
+                                   #'(let () exp exp* ...)))))))))
 
 (define-syntax current-source-location
   (lambda (x)
-- 
2.25.1


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

* Re: Add internal definitions to derived forms
  2022-11-09 15:32 Add internal definitions to derived forms Linus Björnstam
@ 2022-11-09 15:46 ` Damien Mattei
  2022-11-17  7:25 ` lloda
  2023-01-25 15:09 ` Ludovic Courtès
  2 siblings, 0 replies; 22+ messages in thread
From: Damien Mattei @ 2022-11-09 15:46 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: guile-devel

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

thanks,hope it will be in a next stable release of Guile
regards,
damien

On Wed, Nov 9, 2022 at 4:34 PM Linus Björnstam <linus.bjornstam@veryfast.biz>
wrote:

> Hi there!
>
> This commit adds internal definitions to derived conditional forms,
> with-fluids and and-let*. This means the bodies of when, unless and
> with-fluids, and the clause bodies of case and cond behave like a lambda
> body.
>
> There is no performance hit since guile optimizes a (let () ...) without
> internal definitions to a begin (i.e: no new lexical context is created).
>
> best regards
>   Linus Björnstam

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

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

* Re: Add internal definitions to derived forms
  2022-11-09 15:32 Add internal definitions to derived forms Linus Björnstam
  2022-11-09 15:46 ` Damien Mattei
@ 2022-11-17  7:25 ` lloda
  2022-11-18  9:04   ` Linus Björnstam
  2023-01-25 15:09 ` Ludovic Courtès
  2 siblings, 1 reply; 22+ messages in thread
From: lloda @ 2022-11-17  7:25 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: guile-devel


Hi Linus,

I don't understand the following change since at least one expression is required in these clauses.

 @lisp
 (@var{test} => @var{expression})
@@ -217,7 +217,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
+((@var{datum1} @dots{}) @var{body} @dots{})
 @end lisp

Regards

  Daniel


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

* Re: Add internal definitions to derived forms
  2022-11-17  7:25 ` lloda
@ 2022-11-18  9:04   ` Linus Björnstam
  2022-11-18  9:27     ` Lassi Kortela
  0 siblings, 1 reply; 22+ messages in thread
From: Linus Björnstam @ 2022-11-18  9:04 UTC (permalink / raw)
  To: lloda; +Cc: guile-devel

Hi!

Well, the point of the change is to make it so that things other than expressions are allowed. I change it to say @var{body}, and then later clarify that @var{test} is an arbitrary expression and @var{body} is a lambda-like body. 

Which when reading it now sounds... not very good. 

Would "is like the body of a lambda" be a better wording? That would imply that at least one expression is required. English is very much not my first language, and documentation changes are the ones that I fear the most...

best regards
  Linus Björnstam

On Thu, 17 Nov 2022, at 08:25, lloda wrote:
> Hi Linus,
>
> I don't understand the following change since at least one expression 
> is required in these clauses.
>
>  @lisp
>  (@var{test} => @var{expression})
> @@ -217,7 +217,7 @@ result of the @code{cond}-expression.
>  @var{key} may be any expression, and the @var{clause}s must have the form
> 
>  @lisp
> -((@var{datum1} @dots{}) @var{expr1} @var{expr2} @dots{})
> +((@var{datum1} @dots{}) @var{body} @dots{})
>  @end lisp
>
> Regards
>
>   Daniel



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

* Re: Add internal definitions to derived forms
  2022-11-18  9:04   ` Linus Björnstam
@ 2022-11-18  9:27     ` Lassi Kortela
  2022-11-18  9:50       ` Linus Björnstam
  0 siblings, 1 reply; 22+ messages in thread
From: Lassi Kortela @ 2022-11-18  9:27 UTC (permalink / raw)
  To: guile-devel

> Would "is like the body of a lambda" be a better wording?

R7RS section 3.5. says:

(lambda <formals> <definition>* <expression>* <tail expression>)

The <definition>* are the stuff you are adding.



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

* Re: Add internal definitions to derived forms
  2022-11-18  9:27     ` Lassi Kortela
@ 2022-11-18  9:50       ` Linus Björnstam
  2022-11-18 10:22         ` Lassi Kortela
  0 siblings, 1 reply; 22+ messages in thread
From: Linus Björnstam @ 2022-11-18  9:50 UTC (permalink / raw)
  To: Lassi Kortela, guile-devel

On Fri, 18 Nov 2022, at 10:27, Lassi Kortela wrote:
>> Would "is like the body of a lambda" be a better wording?
>
> R7RS section 3.5. says:
>
> (lambda <formals> <definition>* <expression>* <tail expression>)
>
> The <definition>* are the stuff you are adding.

Not quite. Guile extends the lambda body (and by extension let-forms) to allow mixed definitions and expressions:

(lambda () 
  (display "Heippa!")
  (define routsi #t)
  (and (read) routsi))

which expands to, more or less, a letrec*. All in accordance to the paper fixing letrec(reloaded).

Thus saying that the cond clause body is like a lambda body is probably the simplest way to express it. 

best regards
Linus Björnstam



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

* Re: Add internal definitions to derived forms
  2022-11-18  9:50       ` Linus Björnstam
@ 2022-11-18 10:22         ` Lassi Kortela
  2022-11-18 12:53           ` Linus Björnstam
  0 siblings, 1 reply; 22+ messages in thread
From: Lassi Kortela @ 2022-11-18 10:22 UTC (permalink / raw)
  To: guile-devel

> Not quite. Guile extends the lambda body (and by extension let-forms) to allow mixed definitions and expressions:
> 
> (lambda ()
>    (display "Heippa!")
>    (define routsi #t)
>    (and (read) routsi))
> 
> which expands to, more or less, a letrec*. All in accordance to the paper fixing letrec(reloaded).
> 
> Thus saying that the cond clause body is like a lambda body is probably the simplest way to express it.

R7RS defines the syntax of `let` et.al. as follows (section 3.5):

(let (<binding spec>*) <tail body>)

Where:

<tail body> = <definition>* <tail sequence>
<tail sequence> = <expression>* <tail expression>

So their definition of lambda:

(lambda <formals> <definition>* <expression>* <tail expression>)

could be abbreviated:

(lambda <formals> <tail body>)

I haven't read "Fixing letrec" but it looks like Guile intents to 
redefine <tail body> as follows:

<tail body> = <definition-or-expression>* <tail expression>
<definition-or-expression>* = <definition> | <expression>

R6RS appears to use <tail body> in the same sense as R7RS.



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

* Re: Add internal definitions to derived forms
  2022-11-18 10:22         ` Lassi Kortela
@ 2022-11-18 12:53           ` Linus Björnstam
  2022-11-18 13:18             ` Lassi Kortela
  2023-01-19 17:54             ` lloda
  0 siblings, 2 replies; 22+ messages in thread
From: Linus Björnstam @ 2022-11-18 12:53 UTC (permalink / raw)
  To: Lassi Kortela, guile-devel

On Fri, 18 Nov 2022, at 11:22, Lassi Kortela wrote:
> R7RS defines the syntax of `let` et.al. as follows (section 3.5):
>
> (let (<binding spec>*) <tail body>)
>
> Where:
>
> <tail body> = <definition>* <tail sequence>
> <tail sequence> = <expression>* <tail expression>
>
> So their definition of lambda:
>
> (lambda <formals> <definition>* <expression>* <tail expression>)
>
> could be abbreviated:
>
> (lambda <formals> <tail body>)
>
> I haven't read "Fixing letrec" but it looks like Guile intents to 
> redefine <tail body> as follows:
>
> <tail body> = <definition-or-expression>* <tail expression>
> <definition-or-expression>* = <definition> | <expression>
>
> R6RS appears to use <tail body> in the same sense as R7RS.

That is a better way to write it indeed. clause-body being equal to a lambda body. 

Thank you.



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

* Re: Add internal definitions to derived forms
  2022-11-18 12:53           ` Linus Björnstam
@ 2022-11-18 13:18             ` Lassi Kortela
  2023-01-19 17:54             ` lloda
  1 sibling, 0 replies; 22+ messages in thread
From: Lassi Kortela @ 2022-11-18 13:18 UTC (permalink / raw)
  To: Linus Björnstam, guile-devel

> That is a better way to write it indeed. clause-body being equal to a lambda body.
> 
> Thank you.

No problem.

Nb. I made an oversight - the section of R7RS with the grammar I quoted 
says:

"These were derived from rules in the grammar given in chapter 7 by 
replacing some occurrences of <body> with <tail body>, some occurrences 
of <expression> with <tail expression>, and some occurrences of 
<sequence> with <tail sequence>."

So the more general names are <expression>, <sequence>, and <body>.



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

* Re: Add internal definitions to derived forms
  2022-11-18 12:53           ` Linus Björnstam
  2022-11-18 13:18             ` Lassi Kortela
@ 2023-01-19 17:54             ` lloda
  2023-01-20 17:37               ` lloda
  1 sibling, 1 reply; 22+ messages in thread
From: lloda @ 2023-01-19 17:54 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: Lassi Kortela, guile-devel@gnu.org

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


Attached a patch that applies after yours and refers to the explanation of bodies elsewhere in the manual. Wdyt?

Regards

 Daniel



[-- Attachment #2: 0001-Fix-doc-for-conditional-forms-taking-lambda-like-bod.patch --]
[-- Type: application/octet-stream, Size: 2418 bytes --]

From bd68ff5a593b3747b1efed75ca54f2b5eeec8230 Mon Sep 17 00:00:00 2001
From: Daniel Llorens <lloda@sarc.name>
Date: Thu, 19 Jan 2023 16:23:29 +0100
Subject: [PATCH] Fix doc for conditional forms taking lambda-like bodies

* doc/ref/api-control.texi (Simple Conditional Evaluation): Use 'body'
  in the syntax description of when, unless, cond, case.
---
 doc/ref/api-control.texi | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index ece6a6020..7ad52e080 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -142,13 +142,13 @@ an expression that is evaluated for effect, not for value).
 
 In such a case, it is considered more clear to express these intentions
 with these special forms, @code{when} and @code{unless}.  As an added
-bonus, these forms accept multiple statements to evaluate, which are
-implicitly wrapped in a @code{begin}.
+bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
+contain @ref{Internal Definitions,internal definitions} and multiple statements
+to evaluate.
 
-@deffn {Scheme Syntax} when test statement1 statement2 ...
-@deffnx {Scheme Syntax} unless test statement1 statement2 ...
-The actual definitions of these forms are in many ways their most clear
-documentation:
+@deffn {Scheme Syntax} when test body
+@deffnx {Scheme Syntax} unless test body
+The actual definitions of these forms may be their most clear documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
@@ -167,11 +167,10 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{body} @dots{})
+(@var{test} @var{body})
 @end lisp
 
-where @var{test} is an arbitrary expression and @var{body} is a
-lambda-like body, or like this
+where @var{test} is an arbitrary expression, or like this
 
 @lisp
 (@var{test} => @var{expression})
@@ -217,7 +216,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{body} @dots{})
+((@var{datum1} @dots{}) @var{body})
 @end lisp
 
 or
@@ -229,7 +228,7 @@ or
 and the last @var{clause} may have the form
 
 @lisp
-(else @var{expr1} @var{body} @dots{})
+(else @var{body})
 @end lisp
 
 or
-- 
2.30.2


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

* Re: Add internal definitions to derived forms
  2023-01-19 17:54             ` lloda
@ 2023-01-20 17:37               ` lloda
  2023-01-23 22:13                 ` Ludovic Courtès
  0 siblings, 1 reply; 22+ messages in thread
From: lloda @ 2023-01-20 17:37 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: Lassi Kortela, guile-devel@gnu.org

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



> On 19 Jan 2023, at 18:54, lloda <lloda@sarc.name> wrote:
> 
> Attached a patch that applies after yours and refers to the explanation of bodies elsewhere in the manual. Wdyt?

Second version, fixes text for the same type of body for other forms.

Regards

  Daniel


[-- Attachment #2: 0002-Fix-documentation-for-forms-taking-lambda-like-bodie.patch --]
[-- Type: application/octet-stream, Size: 7680 bytes --]

From 7aea299373f7370f31c9701035260ad412763724 Mon Sep 17 00:00:00 2001
From: Daniel Llorens <lloda@sarc.name>
Date: Thu, 19 Jan 2023 16:23:29 +0100
Subject: [PATCH 2/2] Fix documentation for forms taking lambda-like bodies

* doc/ref/api-control.texi (Conditionals): Use 'body' in the syntax
  description of when, unless, cond, case.
* doc/ref/api-binding.texi (Local Bindings): Normalize description of
  body return values.
  (Multiple values): Normalize use of 'body' and description of body
  return values.
---
 doc/ref/api-binding.texi |  6 +++--
 doc/ref/api-control.texi | 51 +++++++++++++++++++---------------------
 2 files changed, 28 insertions(+), 29 deletions(-)

diff --git a/doc/ref/api-binding.texi b/doc/ref/api-binding.texi
index 60f034a0e..2fa1366d2 100644
--- a/doc/ref/api-binding.texi
+++ b/doc/ref/api-binding.texi
@@ -128,6 +128,8 @@ expressions has a few properties which are well worth knowing.
 
 The most basic local binding construct is @code{let}.
 
+@cindex body
+
 @deffn syntax let bindings body
 @var{bindings} has the form
 
@@ -151,8 +153,8 @@ New storage is allocated for the @var{variables}.
 The values of the @var{init} expressions are stored into the variables.
 
 @item
-The expressions in @var{body} are evaluated in order, and the value of
-the last expression is returned as the value of the @code{let}
+The expressions in @var{body} are evaluated in order, and the values of
+the last expression are returned as the result of the @code{let}
 expression.
 @end itemize
 
diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index ece6a6020..d04ec49b6 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -47,8 +47,8 @@ output port, then display a newline.  We use @code{begin} to form a
 compound expression out of this sequence of sub-expressions.
 
 @deffn syntax begin expr @dots{}
-The expression(s) are evaluated in left-to-right order and the value of
-the last expression is returned as the value of the
+The expression(s) are evaluated in left-to-right order and the values of
+the last expression are returned as the result of the
 @code{begin}-expression.  This expression type is used when the
 expressions before the last one are evaluated for their side effects.
 @end deffn
@@ -117,7 +117,7 @@ abuses the @code{begin} form for these two tasks.
 
 Guile provides three syntactic constructs for conditional evaluation.
 @code{if} is the normal if-then-else expression (with an optional else
-branch), @code{cond} is a conditional expression with multiple branches
+branch), @code{cond} is a conditional expression with multiple branches,
 and @code{case} branches if an expression has one of a set of constant
 values.
 
@@ -141,14 +141,14 @@ expression.  (By convention, we use the word @dfn{statement} to refer to
 an expression that is evaluated for effect, not for value).
 
 In such a case, it is considered more clear to express these intentions
-with these special forms, @code{when} and @code{unless}.  As an added
-bonus, these forms accept multiple statements to evaluate, which are
-implicitly wrapped in a @code{begin}.
+with the special forms @code{when} and @code{unless}.  As an added
+bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
+contain @ref{Internal Definitions,internal definitions} and multiple statements
+to evaluate.
 
-@deffn {Scheme Syntax} when test statement1 statement2 ...
-@deffnx {Scheme Syntax} unless test statement1 statement2 ...
-The actual definitions of these forms are in many ways their most clear
-documentation:
+@deffn {Scheme Syntax} when test body
+@deffnx {Scheme Syntax} unless test body
+The actual definitions of these forms may be their most clear documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
@@ -167,11 +167,10 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{body} @dots{})
+(@var{test} @var{body})
 @end lisp
 
-where @var{test} is an arbitrary expression and @var{body} is a
-lambda-like body, or like this
+where @var{test} is an arbitrary expression, or like this
 
 @lisp
 (@var{test} => @var{expression})
@@ -180,9 +179,9 @@ lambda-like body, or like this
 where @var{expression} must evaluate to a procedure.
 
 The @var{test}s of the clauses are evaluated in order and as soon as one
-of them evaluates to a true value, the corresponding @var{expression}s
-are evaluated in order and the last value is returned as the value of
-the @code{cond}-expression.  For the @code{=>} clause type,
+of them evaluates to a true value, the corresponding @var{body} is
+evaluated to produce the result of the @code{cond}-expression.  For the
+@code{=>} clause type,
 @var{expression} is evaluated and the resulting procedure is applied to
 the value of @var{test}.  The result of this procedure application is
 then the result of the @code{cond}-expression.
@@ -209,7 +208,7 @@ procedure to the value(s) of @var{test}, in the same manner as the
 
 The @var{test} of the last @var{clause} may be the symbol @code{else}.
 Then, if none of the preceding @var{test}s is true, the
-@var{expression}s following the @code{else} are evaluated to produce the
+@var{body} following the @code{else} is evaluated to produce the
 result of the @code{cond}-expression.
 @end deffn
 
@@ -217,7 +216,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{body} @dots{})
+((@var{datum1} @dots{}) @var{body})
 @end lisp
 
 or
@@ -229,7 +228,7 @@ or
 and the last @var{clause} may have the form
 
 @lisp
-(else @var{expr1} @var{body} @dots{})
+(else @var{body})
 @end lisp
 
 or
@@ -241,14 +240,13 @@ or
 All @var{datum}s must be distinct.  First, @var{key} is evaluated.  The
 result of this evaluation is compared against all @var{datum} values
 using @code{eqv?}.  When this comparison succeeds, the @var{body}
-following the @var{datum} is evaluated like the body of a lambda,
-returning the value of the last expression as the result of the
+following the @var{datum} is evaluated to produce the result of the
 @code{case} expression.
 
 If the @var{key} matches no @var{datum} and there is an
 @code{else}-clause, the @var{body} following the @code{else} is
-evaluated.  If there is no such clause, the result of the expression is
-unspecified.
+evaluated to produce the result of the @code{case} expression.  If there
+is no such clause, the result of the expression is unspecified.
 
 For the @code{=>} clause types, @var{expression} is evaluated and the
 resulting procedure is applied to the value of @var{key}.  The result of
@@ -970,13 +968,12 @@ same as specified by SRFI-8 (@pxref{SRFI-8}).
 (use-modules (ice-9 receive))
 @end lisp
 
-@deffn {library syntax} receive formals expr body @dots{}
+@deffn {library syntax} receive formals expr body
 Evaluate the expression @var{expr}, and bind the result values (zero
 or more) to the formal arguments in @var{formals}.  @var{formals} is a
 list of symbols, like the argument list in a @code{lambda}
-(@pxref{Lambda}).  After binding the variables, the expressions in
-@var{body} @dots{} are evaluated in order, the return value is the
-result from the last expression.
+(@pxref{Lambda}).  After binding the variables, the @var{body} is
+evaluated to produce the result of the @code{receive} expression.
 
 For example getting results from @code{partition} in SRFI-1
 (@pxref{SRFI-1}),
-- 
2.30.2


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

* Re: Add internal definitions to derived forms
  2023-01-20 17:37               ` lloda
@ 2023-01-23 22:13                 ` Ludovic Courtès
  2023-01-23 23:28                   ` lloda
  0 siblings, 1 reply; 22+ messages in thread
From: Ludovic Courtès @ 2023-01-23 22:13 UTC (permalink / raw)
  To: lloda; +Cc: guile-devel, Linus Björnstam, Lassi Kortela

Hi Daniel,

Chiming in late in the discussion…

lloda <lloda@sarc.name> skribis:

> From 7aea299373f7370f31c9701035260ad412763724 Mon Sep 17 00:00:00 2001
> From: Daniel Llorens <lloda@sarc.name>
> Date: Thu, 19 Jan 2023 16:23:29 +0100
> Subject: [PATCH 2/2] Fix documentation for forms taking lambda-like bodies
>
> * doc/ref/api-control.texi (Conditionals): Use 'body' in the syntax
>   description of when, unless, cond, case.
> * doc/ref/api-binding.texi (Local Bindings): Normalize description of
>   body return values.
>   (Multiple values): Normalize use of 'body' and description of body
>   return values.

What about:
s/Fix documentation…/doc: Document multiple-value returns in let, cond, etc./
?

(That would clarify what’s being fixed.)

> +++ b/doc/ref/api-binding.texi
> @@ -128,6 +128,8 @@ expressions has a few properties which are well worth knowing.
>  
>  The most basic local binding construct is @code{let}.
>  
> +@cindex body

That’s not a great index entry because there’s no context.  Maybe:

  @cindex body, of a @code{let} expression

?

> +with the special forms @code{when} and @code{unless}.  As an added
> +bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
> +contain @ref{Internal Definitions,internal definitions} and multiple statements
> +to evaluate.

“Lambda-like body” is not defined; I guess it’s “lambda-like” in the
wrt. to local ‘define’, but it’s not “lambda-like” for the more crucial
aspect of defining a procedure, so I’d avoid that phrase.  WDYT?

Also, @ref in the middle of sentences may render poorly in Info (info
"(texinfo) @ref").  I’d suggest “(@pxref{Whatever})” at the end of the
sentence or proposition.

>  Each @code{cond}-clause must look like this:
>  
>  @lisp
> -(@var{test} @var{body} @dots{})
> +(@var{test} @var{body})

I think removing dots is incorrect here because it suggests, according
to the typographic conventions used in the document, that there can only
be a single expression.

>  @var{key} may be any expression, and the @var{clause}s must have the form
>  
>  @lisp
> -((@var{datum1} @dots{}) @var{body} @dots{})
> +((@var{datum1} @dots{}) @var{body})

Ditto.

>  and the last @var{clause} may have the form
>  
>  @lisp
> -(else @var{expr1} @var{body} @dots{})
> +(else @var{body})

Ditto.

> -@deffn {library syntax} receive formals expr body @dots{}
> +@deffn {library syntax} receive formals expr body

Likewise.

Otherwise LGTM; it’s certainly an improvement to have multiple-value
returns properly documented!

Thanks,
Ludo’.



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

* Re: Add internal definitions to derived forms
  2023-01-23 22:13                 ` Ludovic Courtès
@ 2023-01-23 23:28                   ` lloda
  2023-01-24  7:33                     ` Linus Björnstam
  2023-01-24  9:02                     ` Ludovic Courtès
  0 siblings, 2 replies; 22+ messages in thread
From: lloda @ 2023-01-23 23:28 UTC (permalink / raw)
  To: Ludovic Courtès
  Cc: guile-devel@gnu.org, Linus Björnstam, Lassi Kortela


Hi Ludovic,

> On 23 Jan 2023, at 23:13, Ludovic Courtès <ludo@gnu.org> wrote:
> 
> Hi Daniel,
> 
> Chiming in late in the discussion…
> 
> lloda <lloda@sarc.name> skribis:
> 
>> From 7aea299373f7370f31c9701035260ad412763724 Mon Sep 17 00:00:00 2001
>> From: Daniel Llorens <lloda@sarc.name>
>> Date: Thu, 19 Jan 2023 16:23:29 +0100
>> Subject: [PATCH 2/2] Fix documentation for forms taking lambda-like bodies
>> 
>> * doc/ref/api-control.texi (Conditionals): Use 'body' in the syntax
>>  description of when, unless, cond, case.
>> * doc/ref/api-binding.texi (Local Bindings): Normalize description of
>>  body return values.
>>  (Multiple values): Normalize use of 'body' and description of body
>>  return values.
> 
> What about:
> s/Fix documentation…/doc: Document multiple-value returns in let, cond, etc./
> ?
> 
> (That would clarify what’s being fixed.)

Ok.

> 
>> +++ b/doc/ref/api-binding.texi
>> @@ -128,6 +128,8 @@ expressions has a few properties which are well worth knowing.
>> 
>> The most basic local binding construct is @code{let}.
>> 
>> +@cindex body
> 
> That’s not a great index entry because there’s no context.  Maybe:
> 
>  @cindex body, of a @code{let} expression
> 
> ?

Ok. I think the word is only used in this sense in the manual, but it might too generic to be used alone.

>> +with the special forms @code{when} and @code{unless}.  As an added
>> +bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
>> +contain @ref{Internal Definitions,internal definitions} and multiple statements
>> +to evaluate.
> 
> “Lambda-like body” is not defined; I guess it’s “lambda-like” in the
> wrt. to local ‘define’, but it’s not “lambda-like” for the more crucial
> aspect of defining a procedure, so I’d avoid that phrase.  WDYT?

Yes, I thought lambda-like was a tad distracting, so I went with 'body' alone...

> Also, @ref in the middle of sentences may render poorly in Info (info
> "(texinfo) @ref").  I’d suggest “(@pxref{Whatever})” at the end of the
> sentence or proposition.

Ok.

>> Each @code{cond}-clause must look like this:
>> 
>> @lisp
>> -(@var{test} @var{body} @dots{})
>> +(@var{test} @var{body})
> 
> I think removing dots is incorrect here because it suggests, according
> to the typographic conventions used in the document, that there can only
> be a single expression.
> 
>> @var{key} may be any expression, and the @var{clause}s must have the form
>> 
>> @lisp
>> -((@var{datum1} @dots{}) @var{body} @dots{})
>> +((@var{datum1} @dots{}) @var{body})
> 
> Ditto.
> 
>> and the last @var{clause} may have the form
>> 
>> @lisp
>> -(else @var{expr1} @var{body} @dots{})
>> +(else @var{body})
> 
> Ditto.
> 
>> -@deffn {library syntax} receive formals expr body @dots{}
>> +@deffn {library syntax} receive formals expr body
> 
> Likewise.

This was actually the main thing I wanted to fix in this patch. Linus' patch had ‘body ...’ but that clearly means ‘zero or more bodies’, which doesn't work because there's exactly one ‘body’. I.e. ‘body’ isn't an expression that is tagged ‘body’, it's, well, a ‘body’.

The Scheme reports use one ‘<body>’ and no dots in all these definitions. See also the definition of let in the linked section ‘Local Bindings’, which again uses ‘body’ and no dots. I hoped that section would count as definition of ‘body’, and the section on ‘Internal Definitions’ explains precisely what can go into ‘body’, so I linked to that as well. I see that isn't clear enough. Maybe ‘body’ should be explicitly defined in one of these sections?

> Otherwise LGTM; it’s certainly an improvement to have multiple-value
> returns properly documented!
> 
> Thanks,
> Ludo’.





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

* Re: Add internal definitions to derived forms
  2023-01-23 23:28                   ` lloda
@ 2023-01-24  7:33                     ` Linus Björnstam
  2023-01-24  9:02                     ` Ludovic Courtès
  1 sibling, 0 replies; 22+ messages in thread
From: Linus Björnstam @ 2023-01-24  7:33 UTC (permalink / raw)
  To: lloda, Ludovic Courtès; +Cc: guile-devel@gnu.org, Lassi Kortela

Hi!

Sorry about the delay, I have an updated patch somewhere, but I started working after 4 months paternity leave and family life's fortunes has it so that I haven't used a computer since the last time I wrote an email in this thread (this is written on a phone).

This is likely how will be in the foreseeable future, despite me having bought an analog keyboard to turn into some kind of music instrument :)

For what it is worth:

The body ... was taken from and-let* and the newer patch was changed to follow the description of let. And "lambda-like body" was changed to "let-expression body".

I will not have the ability to address anything nor actually send my updates patch for what is probably months. If anyone wants to take over I would be happy. For what it is worth, I have already signed a copyright assignment to the FSF. 

Best regards
  Linus Björnstam (manumanumanu)

On Tue, 24 Jan 2023, at 00:28, lloda wrote:
> Hi Ludovic,
>
>> On 23 Jan 2023, at 23:13, Ludovic Courtès <ludo@gnu.org> wrote:
>> 
>> Hi Daniel,
>> 
>> Chiming in late in the discussion…
>> 
>> lloda <lloda@sarc.name> skribis:
>> 
>>> From 7aea299373f7370f31c9701035260ad412763724 Mon Sep 17 00:00:00 2001
>>> From: Daniel Llorens <lloda@sarc.name>
>>> Date: Thu, 19 Jan 2023 16:23:29 +0100
>>> Subject: [PATCH 2/2] Fix documentation for forms taking lambda-like bodies
>>> 
>>> * doc/ref/api-control.texi (Conditionals): Use 'body' in the syntax
>>>  description of when, unless, cond, case.
>>> * doc/ref/api-binding.texi (Local Bindings): Normalize description of
>>>  body return values.
>>>  (Multiple values): Normalize use of 'body' and description of body
>>>  return values.
>> 
>> What about:
>> s/Fix documentation…/doc: Document multiple-value returns in let, cond, etc./
>> ?
>> 
>> (That would clarify what’s being fixed.)
>
> Ok.
>
>> 
>>> +++ b/doc/ref/api-binding.texi
>>> @@ -128,6 +128,8 @@ expressions has a few properties which are well worth knowing.
>>> 
>>> The most basic local binding construct is @code{let}.
>>> 
>>> +@cindex body
>> 
>> That’s not a great index entry because there’s no context.  Maybe:
>> 
>>  @cindex body, of a @code{let} expression
>> 
>> ?
>
> Ok. I think the word is only used in this sense in the manual, but it 
> might too generic to be used alone.
>
>>> +with the special forms @code{when} and @code{unless}.  As an added
>>> +bonus, these forms take a @ref{Local Bindings,lambda-like body}, which can
>>> +contain @ref{Internal Definitions,internal definitions} and multiple statements
>>> +to evaluate.
>> 
>> “Lambda-like body” is not defined; I guess it’s “lambda-like” in the
>> wrt. to local ‘define’, but it’s not “lambda-like” for the more crucial
>> aspect of defining a procedure, so I’d avoid that phrase.  WDYT?
>
> Yes, I thought lambda-like was a tad distracting, so I went with 'body' alone...
>
>> Also, @ref in the middle of sentences may render poorly in Info (info
>> "(texinfo) @ref").  I’d suggest “(@pxref{Whatever})” at the end of the
>> sentence or proposition.
>
> Ok.
>
>>> Each @code{cond}-clause must look like this:
>>> 
>>> @lisp
>>> -(@var{test} @var{body} @dots{})
>>> +(@var{test} @var{body})
>> 
>> I think removing dots is incorrect here because it suggests, according
>> to the typographic conventions used in the document, that there can only
>> be a single expression.
>> 
>>> @var{key} may be any expression, and the @var{clause}s must have the form
>>> 
>>> @lisp
>>> -((@var{datum1} @dots{}) @var{body} @dots{})
>>> +((@var{datum1} @dots{}) @var{body})
>> 
>> Ditto.
>> 
>>> and the last @var{clause} may have the form
>>> 
>>> @lisp
>>> -(else @var{expr1} @var{body} @dots{})
>>> +(else @var{body})
>> 
>> Ditto.
>> 
>>> -@deffn {library syntax} receive formals expr body @dots{}
>>> +@deffn {library syntax} receive formals expr body
>> 
>> Likewise.
>
> This was actually the main thing I wanted to fix in this patch. Linus' 
> patch had ‘body ...’ but that clearly means ‘zero or more bodies’, 
> which doesn't work because there's exactly one ‘body’. I.e. ‘body’ 
> isn't an expression that is tagged ‘body’, it's, well, a ‘body’.
>
> The Scheme reports use one ‘<body>’ and no dots in all these 
> definitions. See also the definition of let in the linked section 
> ‘Local Bindings’, which again uses ‘body’ and no dots. I hoped that 
> section would count as definition of ‘body’, and the section on 
> ‘Internal Definitions’ explains precisely what can go into ‘body’, so I 
> linked to that as well. I see that isn't clear enough. Maybe ‘body’ 
> should be explicitly defined in one of these sections?
>
>> Otherwise LGTM; it’s certainly an improvement to have multiple-value
>> returns properly documented!
>> 
>> Thanks,
>> Ludo’.



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

* Re: Add internal definitions to derived forms
  2023-01-23 23:28                   ` lloda
  2023-01-24  7:33                     ` Linus Björnstam
@ 2023-01-24  9:02                     ` Ludovic Courtès
  2023-01-24 17:59                       ` lloda
  1 sibling, 1 reply; 22+ messages in thread
From: Ludovic Courtès @ 2023-01-24  9:02 UTC (permalink / raw)
  To: lloda; +Cc: guile-devel@gnu.org, Linus Björnstam, Lassi Kortela

Hi!

lloda <lloda@sarc.name> skribis:

>>> @lisp
>>> -(@var{test} @var{body} @dots{})
>>> +(@var{test} @var{body})
>> 
>> I think removing dots is incorrect here because it suggests, according
>> to the typographic conventions used in the document, that there can only
>> be a single expression.

[...]

> This was actually the main thing I wanted to fix in this patch. Linus' patch had ‘body ...’ but that clearly means ‘zero or more bodies’, which doesn't work because there's exactly one ‘body’. I.e. ‘body’ isn't an expression that is tagged ‘body’, it's, well, a ‘body’.

Yeah, ‘body’ is a bit confusing here; in the example above, I’d have
written:

  (@var{test} @var{exp} @dots{})

because that’s what the “body” is: one or more expressions.

> The Scheme reports use one ‘<body>’ and no dots in all these definitions. See also the definition of let in the linked section ‘Local Bindings’, which again uses ‘body’ and no dots. I hoped that section would count as definition of ‘body’, and the section on ‘Internal Definitions’ explains precisely what can go into ‘body’, so I linked to that as well. I see that isn't clear enough. Maybe ‘body’ should be explicitly defined in one of these sections?

Damn it, I hadn’t realized this was a widespread convention, but yeah,
R5RS and parts of the Guile manual follow this convention.  So hmm, the
change you propose makes a lot of sense to me now.

So yeah overall I guess we should always write one of:

  (something @var{body})

or:

  (something @var{exp} @dots{})

Using @var{body} like you do in this patch is consistent with other
parts of the manual, so it LGTM.

Thanks,
Ludo’.



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

* Re: Add internal definitions to derived forms
  2023-01-24  9:02                     ` Ludovic Courtès
@ 2023-01-24 17:59                       ` lloda
  2023-01-25 10:33                         ` Ludovic Courtès
  0 siblings, 1 reply; 22+ messages in thread
From: lloda @ 2023-01-24 17:59 UTC (permalink / raw)
  To: Ludovic Courtès
  Cc: guile-devel@gnu.org, Linus Björnstam, Lassi Kortela

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


> On 24 Jan 2023, at 10:02, Ludovic Courtès <ludo@gnu.org> wrote:
> 
> Hi!
> 
> lloda <lloda@sarc.name> skribis:
> 
>>>> @lisp
>>>> -(@var{test} @var{body} @dots{})
>>>> +(@var{test} @var{body})
>>> 
>>> I think removing dots is incorrect here because it suggests, according
>>> to the typographic conventions used in the document, that there can only
>>> be a single expression.
> 
> [...]
> 
>> This was actually the main thing I wanted to fix in this patch. Linus' patch had ‘body ...’ but that clearly means ‘zero or more bodies’, which doesn't work because there's exactly one ‘body’. I.e. ‘body’ isn't an expression that is tagged ‘body’, it's, well, a ‘body’.
> 
> Yeah, ‘body’ is a bit confusing here; in the example above, I’d have
> written:
> 
>  (@var{test} @var{exp} @dots{})
> 
> because that’s what the “body” is: one or more expressions.

Hmm, it would seem so, but the way the Scheme reports use ‘expression’, it's not.

I've added an explicit definition of what the let-expression body is in the updated patch, I hope that reads better. Also tried to address your other comments.
 
Thanks

  Daniel

>> The Scheme reports use one ‘<body>’ and no dots in all these definitions. See also the definition of let in the linked section ‘Local Bindings’, which again uses ‘body’ and no dots. I hoped that section would count as definition of ‘body’, and the section on ‘Internal Definitions’ explains precisely what can go into ‘body’, so I linked to that as well. I see that isn't clear enough. Maybe ‘body’ should be explicitly defined in one of these sections?
> 
> Damn it, I hadn’t realized this was a widespread convention, but yeah,
> R5RS and parts of the Guile manual follow this convention.  So hmm, the
> change you propose makes a lot of sense to me now.
> 
> So yeah overall I guess we should always write one of:
> 
>  (something @var{body})
> 
> or:
> 
>  (something @var{exp} @dots{})
> 
> Using @var{body} like you do in this patch is consistent with other
> parts of the manual, so it LGTM.
> 
> Thanks,
> Ludo’.


[-- Attachment #2: 0002-Document-multiple-value-returns-in-forms-taking-a-le.patch --]
[-- Type: application/octet-stream, Size: 8146 bytes --]

From 70ce7174a43ba17f2db0c3a6b7eeeb191a332663 Mon Sep 17 00:00:00 2001
From: Daniel Llorens <lloda@sarc.name>
Date: Tue, 24 Jan 2023 11:26:44 +0100
Subject: [PATCH 2/2] Document multiple-value returns in forms taking a
 let-expression body

* doc/ref/api-binding.texi (Local Bindings): Document multiple-value
  returns for let.
* doc/ref/api-control.texi (begin): Document multiple-value returns for
  begin.
  (Conditionals): Document multiple-value returns and use 'body' in the
  syntax description of when, unless, cond, case.
  (Multiple values): Document multiple-value returns and use 'body' in
  the syntax description of SRFI-8 receive.
---
 doc/ref/api-binding.texi | 11 ++++++---
 doc/ref/api-control.texi | 51 +++++++++++++++++++---------------------
 2 files changed, 32 insertions(+), 30 deletions(-)

diff --git a/doc/ref/api-binding.texi b/doc/ref/api-binding.texi
index 60f034a0e..a0cf8f0d8 100644
--- a/doc/ref/api-binding.texi
+++ b/doc/ref/api-binding.texi
@@ -138,6 +138,11 @@ The most basic local binding construct is @code{let}.
 that is zero or more two-element lists of a variable and an arbitrary
 expression each.  All @var{variable} names must be distinct.
 
+@cindex body, of a @code{let} expression
+
+@var{body} is a sequence of expressions and definitions, ending in an
+expression. 
+
 A @code{let} expression is evaluated as follows.
 
 @itemize @bullet
@@ -151,9 +156,9 @@ New storage is allocated for the @var{variables}.
 The values of the @var{init} expressions are stored into the variables.
 
 @item
-The expressions in @var{body} are evaluated in order, and the value of
-the last expression is returned as the value of the @code{let}
-expression.
+The expressions and definitions in @var{body} are evaluated in order
+(@pxref{Internal Definitions}), and the values of the last expression
+are returned as the result of the @code{let} expression.
 @end itemize
 
 The @var{init} expressions are not allowed to refer to any of the
diff --git a/doc/ref/api-control.texi b/doc/ref/api-control.texi
index ece6a6020..24356a273 100644
--- a/doc/ref/api-control.texi
+++ b/doc/ref/api-control.texi
@@ -47,8 +47,8 @@ output port, then display a newline.  We use @code{begin} to form a
 compound expression out of this sequence of sub-expressions.
 
 @deffn syntax begin expr @dots{}
-The expression(s) are evaluated in left-to-right order and the value of
-the last expression is returned as the value of the
+The expression(s) are evaluated in left-to-right order and the values of
+the last expression are returned as the result of the
 @code{begin}-expression.  This expression type is used when the
 expressions before the last one are evaluated for their side effects.
 @end deffn
@@ -117,7 +117,7 @@ abuses the @code{begin} form for these two tasks.
 
 Guile provides three syntactic constructs for conditional evaluation.
 @code{if} is the normal if-then-else expression (with an optional else
-branch), @code{cond} is a conditional expression with multiple branches
+branch), @code{cond} is a conditional expression with multiple branches,
 and @code{case} branches if an expression has one of a set of constant
 values.
 
@@ -141,14 +141,14 @@ expression.  (By convention, we use the word @dfn{statement} to refer to
 an expression that is evaluated for effect, not for value).
 
 In such a case, it is considered more clear to express these intentions
-with these special forms, @code{when} and @code{unless}.  As an added
-bonus, these forms accept multiple statements to evaluate, which are
-implicitly wrapped in a @code{begin}.
+with the special forms @code{when} and @code{unless}.  As an added
+bonus, these forms take a @emph{body} like in a @code{let} expression,
+which can contain internal definitions and multiple statements to
+evaluate (@pxref{Local Bindings}).
 
-@deffn {Scheme Syntax} when test statement1 statement2 ...
-@deffnx {Scheme Syntax} unless test statement1 statement2 ...
-The actual definitions of these forms are in many ways their most clear
-documentation:
+@deffn {Scheme Syntax} when test body
+@deffnx {Scheme Syntax} unless test body
+The actual definitions of these forms may be their most clear documentation:
 
 @example
 (define-syntax-rule (when test stmt stmt* ...)
@@ -167,11 +167,10 @@ statements if @var{test} is false.
 Each @code{cond}-clause must look like this:
 
 @lisp
-(@var{test} @var{body} @dots{})
+(@var{test} @var{body})
 @end lisp
 
-where @var{test} is an arbitrary expression and @var{body} is a
-lambda-like body, or like this
+where @var{test} is an arbitrary expression, or like this
 
 @lisp
 (@var{test} => @var{expression})
@@ -180,9 +179,9 @@ lambda-like body, or like this
 where @var{expression} must evaluate to a procedure.
 
 The @var{test}s of the clauses are evaluated in order and as soon as one
-of them evaluates to a true value, the corresponding @var{expression}s
-are evaluated in order and the last value is returned as the value of
-the @code{cond}-expression.  For the @code{=>} clause type,
+of them evaluates to a true value, the corresponding @var{body} is
+evaluated to produce the result of the @code{cond}-expression.  For the
+@code{=>} clause type,
 @var{expression} is evaluated and the resulting procedure is applied to
 the value of @var{test}.  The result of this procedure application is
 then the result of the @code{cond}-expression.
@@ -209,7 +208,7 @@ procedure to the value(s) of @var{test}, in the same manner as the
 
 The @var{test} of the last @var{clause} may be the symbol @code{else}.
 Then, if none of the preceding @var{test}s is true, the
-@var{expression}s following the @code{else} are evaluated to produce the
+@var{body} following the @code{else} is evaluated to produce the
 result of the @code{cond}-expression.
 @end deffn
 
@@ -217,7 +216,7 @@ result of the @code{cond}-expression.
 @var{key} may be any expression, and the @var{clause}s must have the form
 
 @lisp
-((@var{datum1} @dots{}) @var{body} @dots{})
+((@var{datum1} @dots{}) @var{body})
 @end lisp
 
 or
@@ -229,7 +228,7 @@ or
 and the last @var{clause} may have the form
 
 @lisp
-(else @var{expr1} @var{body} @dots{})
+(else @var{body})
 @end lisp
 
 or
@@ -241,14 +240,13 @@ or
 All @var{datum}s must be distinct.  First, @var{key} is evaluated.  The
 result of this evaluation is compared against all @var{datum} values
 using @code{eqv?}.  When this comparison succeeds, the @var{body}
-following the @var{datum} is evaluated like the body of a lambda,
-returning the value of the last expression as the result of the
+following the @var{datum} is evaluated to produce the result of the
 @code{case} expression.
 
 If the @var{key} matches no @var{datum} and there is an
 @code{else}-clause, the @var{body} following the @code{else} is
-evaluated.  If there is no such clause, the result of the expression is
-unspecified.
+evaluated to produce the result of the @code{case} expression.  If there
+is no such clause, the result of the expression is unspecified.
 
 For the @code{=>} clause types, @var{expression} is evaluated and the
 resulting procedure is applied to the value of @var{key}.  The result of
@@ -970,13 +968,12 @@ same as specified by SRFI-8 (@pxref{SRFI-8}).
 (use-modules (ice-9 receive))
 @end lisp
 
-@deffn {library syntax} receive formals expr body @dots{}
+@deffn {library syntax} receive formals expr body
 Evaluate the expression @var{expr}, and bind the result values (zero
 or more) to the formal arguments in @var{formals}.  @var{formals} is a
 list of symbols, like the argument list in a @code{lambda}
-(@pxref{Lambda}).  After binding the variables, the expressions in
-@var{body} @dots{} are evaluated in order, the return value is the
-result from the last expression.
+(@pxref{Lambda}).  After binding the variables, the @var{body} is
+evaluated to produce the result of the @code{receive} expression.
 
 For example getting results from @code{partition} in SRFI-1
 (@pxref{SRFI-1}),
-- 
2.30.2


[-- Attachment #3: Type: text/plain, Size: 2 bytes --]




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

* Re: Add internal definitions to derived forms
  2023-01-24 17:59                       ` lloda
@ 2023-01-25 10:33                         ` Ludovic Courtès
  0 siblings, 0 replies; 22+ messages in thread
From: Ludovic Courtès @ 2023-01-25 10:33 UTC (permalink / raw)
  To: lloda; +Cc: guile-devel@gnu.org, Linus Björnstam, Lassi Kortela

Hi,

lloda <lloda@sarc.name> skribis:

> From 70ce7174a43ba17f2db0c3a6b7eeeb191a332663 Mon Sep 17 00:00:00 2001
> From: Daniel Llorens <lloda@sarc.name>
> Date: Tue, 24 Jan 2023 11:26:44 +0100
> Subject: [PATCH 2/2] Document multiple-value returns in forms taking a
>  let-expression body
>
> * doc/ref/api-binding.texi (Local Bindings): Document multiple-value
>   returns for let.
> * doc/ref/api-control.texi (begin): Document multiple-value returns for
>   begin.
>   (Conditionals): Document multiple-value returns and use 'body' in the
>   syntax description of when, unless, cond, case.
>   (Multiple values): Document multiple-value returns and use 'body' in
>   the syntax description of SRFI-8 receive.

LGTM, thanks!

Ludo’.



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

* Re: Add internal definitions to derived forms
  2022-11-09 15:32 Add internal definitions to derived forms Linus Björnstam
  2022-11-09 15:46 ` Damien Mattei
  2022-11-17  7:25 ` lloda
@ 2023-01-25 15:09 ` Ludovic Courtès
  2023-01-25 15:38   ` Greg Troxel
                     ` (2 more replies)
  2 siblings, 3 replies; 22+ messages in thread
From: Ludovic Courtès @ 2023-01-25 15:09 UTC (permalink / raw)
  To: Linus Björnstam; +Cc: lloda, guile-devel, Andy Wingo

Hello!

Linus Björnstam <linus.bjornstam@veryfast.biz> skribis:

> This commit adds internal definitions to derived conditional forms,
> with-fluids and and-let*. This means the bodies of when, unless and
> with-fluids, and the clause bodies of case and cond behave like a
> lambda body.
>
> There is no performance hit since guile optimizes a (let () ...)
> without internal definitions to a begin (i.e: no new lexical context
> is created).

Daniel pushed this as 764e3614b8c13de604399572a67d071621e9ca21 in
‘main’.  I had completely overlooked this thread but I wasn’t quite sure
about it, so I did not include it in 3.0.9.

The reason I’m hesitant is that, while I think it’s nice to be able to
have local ‘define’ in these contexts, I’m wary of diverging from R5RS
and R6RS.  Since it’s a one-way change (we won’t be able to revert it
once people rely on it), I thought we’d rather be careful.

What do people think?  Andy?

Thanks,
Ludo’.



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

* Re: Add internal definitions to derived forms
  2023-01-25 15:09 ` Ludovic Courtès
@ 2023-01-25 15:38   ` Greg Troxel
  2023-01-25 21:38     ` Linus Björnstam
  2023-01-25 21:06   ` Linus Björnstam
  2023-02-02 11:17   ` lloda
  2 siblings, 1 reply; 22+ messages in thread
From: Greg Troxel @ 2023-01-25 15:38 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: guile-devel

Ludovic Courtès <ludo@gnu.org> writes:

> The reason I’m hesitant is that, while I think it’s nice to be able to
> have local ‘define’ in these contexts, I’m wary of diverging from R5RS
> and R6RS.  Since it’s a one-way change (we won’t be able to revert it
> once people rely on it), I thought we’d rather be careful.

My reaction, without thinking much, and being fuzzy on a lot of things
is that part of the point of guile is that it is Scheme which to me
means RnRS conformance.   Of course it's not exactly and every other
Scheme impl is not exactly.  But mostly I think that's a bug as it leads
to incompatible programs.

For example, there are many shell scripts out there that use == in test,
because bash decided to have an extension.  This is not useful, except
perhaps to people writing in sh that think they are writing C :-) but it
does mean that these scripts become limited to bash rather than any
"POSIX sh implementation".

Does the new feature advance the goal of guile as an extension language?

Is this heading for inclusino in the next RnRS?



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

* Re: Add internal definitions to derived forms
  2023-01-25 15:09 ` Ludovic Courtès
  2023-01-25 15:38   ` Greg Troxel
@ 2023-01-25 21:06   ` Linus Björnstam
  2023-02-02 11:17   ` lloda
  2 siblings, 0 replies; 22+ messages in thread
From: Linus Björnstam @ 2023-01-25 21:06 UTC (permalink / raw)
  To: Ludovic Courtès; +Cc: lloda, guile-devel, Andy Wingo



On Wed, 25 Jan 2023, at 16:09, Ludovic Courtès wrote:
> Hello!
>
> Linus Björnstam <linus.bjornstam@veryfast.biz> skribis:
>
>
> Daniel pushed this as 764e3614b8c13de604399572a67d071621e9ca21 in
> ‘main’.  I had completely overlooked this thread but I wasn’t quite sure
> about it, so I did not include it in 3.0.9.
>
> The reason I’m hesitant is that, while I think it’s nice to be able to
> have local ‘define’ in these contexts, I’m wary of diverging from R5RS
> and R6RS.  Since it’s a one-way change (we won’t be able to revert it
> once people rely on it), I thought we’d rather be careful.

Andy gave a similar idea thumbs up in IRC some time ago. We could always make r6rs cond, case etc. use (begin ...). For that we could just re-use the example implementations from the r6rs appendix depending on license.

R5RS compatibility is a harder but to crack. Maybe a compat library like r6rs has?

/Linus



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

* Re: Add internal definitions to derived forms
  2023-01-25 15:38   ` Greg Troxel
@ 2023-01-25 21:38     ` Linus Björnstam
  0 siblings, 0 replies; 22+ messages in thread
From: Linus Björnstam @ 2023-01-25 21:38 UTC (permalink / raw)
  To: Greg Troxel, Ludovic Courtès; +Cc: guile-devel


On Wed, 25 Jan 2023, at 16:38, Greg Troxel wrote:

> My reaction, without thinking much, and being fuzzy on a lot of things
> is that part of the point of guile is that it is Scheme which to me
> means RnRS conformance.   Of course it's not exactly and every other
> Scheme impl is not exactly.  But mostly I think that's a bug as it leads
> to incompatible programs.

Guile already has some nonstandard syntax extensions. Definitions in expression context in some places (all bodies, just not begin), cond extensions etc. I had 


> Does the new feature advance the goal of guile as an extension language?

It makes guile more approachable for beginners. We have all written convoluted cond clauses that could have been a lot clearer with internal definitions.

> Is this heading for inclusino in the next RnRS?

No, but...

bodies are now specified using letrec*. Allowing internal definitions is a small step away, but the only one I heard mentioning it was Marc. I suspect they are moving carefully.

The reason r5rs did not include it was that bodies were specified in terms of letrec. That made internal definitions hard to pin down. 

Best regards 
Linus 



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

* Re: Add internal definitions to derived forms
  2023-01-25 15:09 ` Ludovic Courtès
  2023-01-25 15:38   ` Greg Troxel
  2023-01-25 21:06   ` Linus Björnstam
@ 2023-02-02 11:17   ` lloda
  2 siblings, 0 replies; 22+ messages in thread
From: lloda @ 2023-02-02 11:17 UTC (permalink / raw)
  To: guile-devel@gnu.org


Guile already allows mixed definitions and expressions in let bodies (since 2.9.4), which isn't in any of the Scheme reports. It's up to authors to avoid or isolate Guile extensions if they want to remain rnrs compatible, and this patch doesn't change that.

Being able to put definitions in the body of let but not in the bodies of these other forms is an artificial restriction. Some forms still aren't fixed, like match. I believe we should eventually fix those as well.

I think the root of the issue is (begin), but the patch goes in the right direction.

Regards

  Daniel






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

end of thread, other threads:[~2023-02-02 11:17 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-09 15:32 Add internal definitions to derived forms Linus Björnstam
2022-11-09 15:46 ` Damien Mattei
2022-11-17  7:25 ` lloda
2022-11-18  9:04   ` Linus Björnstam
2022-11-18  9:27     ` Lassi Kortela
2022-11-18  9:50       ` Linus Björnstam
2022-11-18 10:22         ` Lassi Kortela
2022-11-18 12:53           ` Linus Björnstam
2022-11-18 13:18             ` Lassi Kortela
2023-01-19 17:54             ` lloda
2023-01-20 17:37               ` lloda
2023-01-23 22:13                 ` Ludovic Courtès
2023-01-23 23:28                   ` lloda
2023-01-24  7:33                     ` Linus Björnstam
2023-01-24  9:02                     ` Ludovic Courtès
2023-01-24 17:59                       ` lloda
2023-01-25 10:33                         ` Ludovic Courtès
2023-01-25 15:09 ` Ludovic Courtès
2023-01-25 15:38   ` Greg Troxel
2023-01-25 21:38     ` Linus Björnstam
2023-01-25 21:06   ` Linus Björnstam
2023-02-02 11:17   ` lloda

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