unofficial mirror of guile-devel@gnu.org 
 help / color / mirror / Atom feed
* definition in expression context, where definitions are not allowed
@ 2015-10-11  7:49 Arne Babenhauserheide
  2015-10-11 10:03 ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 1 reply; 2+ messages in thread
From: Arne Babenhauserheide @ 2015-10-11  7:49 UTC (permalink / raw)
  To: guile-devel

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

Hi,

I’m repeatedly stumbling over the restrictions where to use define. Here’s a minimal example:

    (define (hello who)
      (display "Hello ")
      (define (world who)
        (display who))
      (world who)
      (display "!")
      (newline))

This throws a Syntax error: …definition in expression context, where
definitions are not allowed, in form (define (world who) (display
who))

And though I know that there are reasons for this, it just feels wrong
to be in the language which removes restrictions for writing great
languages and then seeing such a complication.

This works just fine - keeping all the information in the definition -
when I rewrite it to

    (define (hello who)
      (display "Hello ")
      (let ((world (lambda (who) (display who))))
        (world who)
        (display "!")
        (newline)))

So why isn’t that done automatically? Why does Guile not just do this
transformation with an information message that the define was changed
to a let? It already detects the situation, why can’t it make it work?

In other words: Is the optimization allowed by this worth the
additional complexity of the language?

Or am I missing something else which is enabled by this limitation?

Best wishes,
Arne

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 299 bytes --]

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

* Re: definition in expression context, where definitions are not allowed
  2015-10-11  7:49 definition in expression context, where definitions are not allowed Arne Babenhauserheide
@ 2015-10-11 10:03 ` Taylan Ulrich Bayırlı/Kammer
  0 siblings, 0 replies; 2+ messages in thread
From: Taylan Ulrich Bayırlı/Kammer @ 2015-10-11 10:03 UTC (permalink / raw)
  To: Arne Babenhauserheide; +Cc: guile-devel

Arne Babenhauserheide <arne_bab@web.de> writes:

>     (define (hello who)
>       (display "Hello ")
>       (define (world who)
>         (display who))
>       (world who)
>       (display "!")
>       (newline))

Let's look at a different example first, which works with the current
semantics:

  (let ()
    (define (odd? n) (if (zero? n) #f (even? (- n 1))))
    (define (even? n) (if (zero? n) #t (odd? (- n 2))))
    (even? 42))

That works because the internal definitions become 'letrec*' so they may
refer to each other, i.e. 'odd?' can refer to 'even?' in its body,
before 'even?' is really defined.

If your example also worked, than with the combination of the above,
users might ultimately also expect this to work:

  (let ()
    (define (hello)
      (display "Hello ")
      (world)
      (display "!")
      (newline))
    (display "Goodbye Eden, ")
    (define (world)
      (display "World"))
    (hello))

Just like in the top-level.  But that would require making the whole
procedure body a big 'letrec*' expression.  If I'm not mistaken that's
exactly what JavaScript does, called "var hoisting," where all variables
declared anywhere in a function become bound to a special 'undefined'
value at the beginning of the function, and these don't behave exactly
as undefined variables either.  In Guile too, variables "bound but not
defined yet" as created by 'letrec*' aren't checked for invalid access
because it would put overhead on every variable reference.  So that
would end up giving us those weird semantics as known from JS.

(IIRC, "strict mode" JS only allows variable declarations at the
beginning of a function body, just like internal defines in Scheme.)

Or maybe my example was a bit contrived, and/or we can teach users that
they should "group together" definitions that refer to each other, and
have those groups turn into nested 'letrec*' expressions (similar to
your proposal, just using 'letrec*' when there's multiple adjacent
'define' forms).  But that makes things more and more complicated, and
by the time we taught users that we could have probably just taught them
the simpler rule that internal 'define' forms may only appear at the
beginning of a body.

Does that make sense?

Taylan



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

end of thread, other threads:[~2015-10-11 10:03 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-10-11  7:49 definition in expression context, where definitions are not allowed Arne Babenhauserheide
2015-10-11 10:03 ` Taylan Ulrich Bayırlı/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).