unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Why is an empty lambda body not allowed?
@ 2014-07-04 18:20 Tobias Brandt
  2014-07-04 18:44 ` Taylan Ulrich Bayirli/Kammer
  0 siblings, 1 reply; 4+ messages in thread
From: Tobias Brandt @ 2014-07-04 18:20 UTC (permalink / raw)
  To: guile-user@gnu.org

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

Hi,

it seems to be illegal to write
    (lambda ())

I would have expected this to evaluate to a procedure returning unspecified.

On the other hand, the following are all valid
    (begin)
    (define x (begin))
    (lambda () x)

but
    (lambda () (begin))

is not.

Why is that?


Cheers,
Tobias

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

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

* Re: Why is an empty lambda body not allowed?
  2014-07-04 18:20 Why is an empty lambda body not allowed? Tobias Brandt
@ 2014-07-04 18:44 ` Taylan Ulrich Bayirli/Kammer
  2014-07-04 19:14   ` Tobias Brandt
  0 siblings, 1 reply; 4+ messages in thread
From: Taylan Ulrich Bayirli/Kammer @ 2014-07-04 18:44 UTC (permalink / raw)
  To: Tobias Brandt; +Cc: guile-user@gnu.org

Tobias Brandt <tob.brandt@gmail.com> writes:

> Hi,
>
> it seems to be illegal to write
> (lambda ())
>
> I would have expected this to evaluate to a procedure returning
> unspecified.

I don't see that as being more intuitive, or useful.  Even returning
*unspecified* or returning zero values is an action, a procedure with
nothing as its body intuitively does nothing, which doesn't really make
sense (it must at least return something) .. oh well, philosophical
babbling.  In practice it will be just an additional incompatibility
with other implementations, for no gain.

Tangentially related thread from a couple months back:

http://lists.gnu.org/archive/html/guile-devel/2014-02/msg00039.html

> On the other hand, the following are all valid
> (begin)
> (define x (begin))
> (lambda () x)
>
> but
> (lambda () (begin))
>
> is not.
>
> Why is that?

There are (conceptually) two different syntaxes bound to `begin', which
are selected based on the context in which the form appears.

The one `begin' can have a sequence os definitions and expressions as
its subforms, and is evaluated exactly as if the (begin <...>) form were
just <...>.  (The subforms are "spliced" into the surrounding scope.)
This is a hack for macros that want to output several definitions.  This
`begin' form can appear at the start of a lambda body, and similar
places.

The other `begin' can only have expressions (no definitions) as its
subforms, and is itself an expression, thus can appear anywhere an
expression may appear, like in the middle of a lambda body, or as a
procedure-call operand.

In your example, it seems ambiguous which `begin' should be used (it has
no definition subforms, so it could just be the expression-begin), and
apparently Guile interprets it as the former, which is fine.  R5RS could
actually even be interpreted to mean that the splicing-begin *should* be
used in that context (see end of section 5.2.2 "Internal definitions"),
though the same doesn't hold for R7RS-small as far as I see (section
4.2.3 "Sequencing").

I agree that one would at first expect ((lambda () (begin))) to be
equivalent to (begin), but I wouldn't e.g. complicate the compiler for
it.

> Cheers,
> Tobias

Taylan



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

* Re: Why is an empty lambda body not allowed?
  2014-07-04 18:44 ` Taylan Ulrich Bayirli/Kammer
@ 2014-07-04 19:14   ` Tobias Brandt
  2014-07-04 22:01     ` Taylan Ulrich Bayirli/Kammer
  0 siblings, 1 reply; 4+ messages in thread
From: Tobias Brandt @ 2014-07-04 19:14 UTC (permalink / raw)
  To: Taylan Ulrich Bayirli/Kammer; +Cc: guile-user@gnu.org

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

Hi Taylan,

your points are all good and I kind of get the reasoning behind the current
semantics. I'm not trying to start a big discussion here, it's just a
little detail I noticed and that bothered me.

I don't really care what (lambda ()) evaluates to as long as it's
consistent with the rest of the language. But what rubs me the wrong way is
that

    (define x (begin))
    (lambda () x)

is not the same as

    (lambda () (begin))

because one of the strength of functional programming is referential
transparency. Therefore I would expect the definition of x (which has no
side effects) to be substitutable for x itself. This is apparently not the
case as one (begin) has a different meaning than the other because of its
context.

As another data point, this seems to be fine:

    (use-modules (oop goops))
    (define-method (foo))

So, GOOPS doesn't mind empty method bodies. However

    (define-method (foo) (begin))

fails. Not very consistent either, I'm afraid.

Cheers,
Tobias

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

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

* Re: Why is an empty lambda body not allowed?
  2014-07-04 19:14   ` Tobias Brandt
@ 2014-07-04 22:01     ` Taylan Ulrich Bayirli/Kammer
  0 siblings, 0 replies; 4+ messages in thread
From: Taylan Ulrich Bayirli/Kammer @ 2014-07-04 22:01 UTC (permalink / raw)
  To: Tobias Brandt; +Cc: guile-user@gnu.org

Tobias Brandt <tob.brandt@gmail.com> writes:

> I don't really care what (lambda ()) evaluates to as long as it's
> consistent with the rest of the language. But what rubs me the wrong
> way is that
>
> (define x (begin))
> (lambda () x)
>
> is not the same as
>
> (lambda () (begin))
>
> because one of the strength of functional programming is referential
> transparency. Therefore I would expect the definition of x (which has
> no side effects) to be substitutable for x itself. This is apparently
> not the case as one (begin) has a different meaning than the other
> because of its context.

I agree it's annoying.  However it only breaches referential
transparency on a superficial, textual level, or not at all depending on
your definition.  In your example, the right-hand side of the `define'
is (grammatically) an <expression> whereas the other form is in a <body>
position, so it's not so that you're exchanging two <expression>s.  It's
rather so that a valid <expression> (in Guile Scheme at least, see
below) happens to also be a valid <body> (which however leads to an
error later on).

By the way, it comes out the expression-begin is actually specified (in
R5 through 7RS) to take at least one operand, so in your example the
(define x (begin)) is unspecified in first place.

OTOH, a <body> is defined as "<definition>* <sequence>", where
<sequence> is "<command>* <expression>", meaning that in a <body> that
is just "(begin)", the (begin) is an <expression>.  In RnRS, (begin) is
actually an invalid <expression>, but since Guile allows it in general,
one would expect it to work here too.  (Guile's "excuse" here could be
that it uses a wholely different grammar that is compatible with the
RnRS one, instead of one constructed through incremental extensions to
it.)

I now wish Guile simply didn't allow (begin) as a valid expression. :-)

While this is just a nitpick, I'll file a bug report for it.

> As another data point, this seems to be fine:
>
> (use-modules (oop goops))
> (define-method (foo))
>
> So, GOOPS doesn't mind empty method bodies. However
>
> (define-method (foo) (begin))
>
> fails. Not very consistent either, I'm afraid.

I just checked and `define-method' (deferring to the auxilliary macro
`method') special-cases zero-form method bodies, simply giving them a
body of (if #f #f), so it introduces the asymmetry intentionally.  Dunno
why, but changing it could break backwards compatibility.  OTOH it's
nasty that the second failes when the first doesn't, so I'll file an
additional report for that.

> Cheers,
> Tobias

Taylan



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

end of thread, other threads:[~2014-07-04 22:01 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-07-04 18:20 Why is an empty lambda body not allowed? Tobias Brandt
2014-07-04 18:44 ` Taylan Ulrich Bayirli/Kammer
2014-07-04 19:14   ` Tobias Brandt
2014-07-04 22:01     ` Taylan Ulrich Bayirli/Kammer

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