Difference in define behaviour between kawa.jar and embedded Scheme example

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

Difference in define behaviour between kawa.jar and embedded Scheme example

Mark Raynsford
I have the following trivial example:

https://raw.githubusercontent.com/io7m/kawa-experiments/develop/src/main/resources/com/io7m/kawa_exp/demo0.scm

If I evaluate it on the command line:

$ java -jar kawa-3.0/lib/kawa.jar
#|kawa:1|# (define (six0 x) (+ 3 3))
#|kawa:2|# (define (+ x y) (* x y))
#|kawa:3|# (define (six1 x) (+ 3 3))
#|kawa:4|# (six0 0)
6
#|kawa:5|# (six1 0)
9

This is the behaviour I'd expect. If I then try (what appears to be)
the same thing from Java:

https://raw.githubusercontent.com/io7m/kawa-experiments/develop/src/main/java/com/io7m/kawa_exp/SchemeExp0.java

The program prints:

22:30:02.499 [main] DEBUG com.io7m.kawa_exp.SchemeExp0 - result: 9, 9

In other words, the redefinition of + on the second line is affecting
the existing definition of six0 so that the applications of six0 and
six1 are both returning 9. What's going on here?

This is an unmodified kawa jar from the 3.0 binary distribution.

--
Mark Raynsford | http://www.io7m.com


attachment0 (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Difference in define behaviour between kawa.jar and embedded Scheme example

Per Bothner
On 11/22/2017 11:33 PM, Mark Raynsford wrote:
> In other words, the redefinition of + on the second line is affecting
> the existing definition of six0 so that the applications of six0 and
> six1 are both returning 9. What's going on here?

The behavior of demo0.scm depends on whether it is evaluated line-by-line
(as in REPL) or as a "module" (or "library" in R7RS-speak).  The latter
is the default, but you can force teh former using the -f options.
Compare:
   $ kawa demo0.scm
vs:
   $ kawa -d demo0.scm

Either implicitly imports (kawa base).  In general it is invalid to
explicitly define bindings that conflict with imported bindings.
We are somewhat more lenient with (kawa base), for compatibility
with tradition, but it is still a bad idea.

Instead you can do something like:

(import (except (kawa base) +))
(import (only (kawa base) (+ orig-+)))
(define (six0 x) (orig-+ 3 3))
(define (+ x y) (* x y))
(define (six1 x) (+ 3 3))
(format #t "[~w ~w]~%~!" (six0 0) (six1 0))
--
        --Per Bothner
[hidden email]   http://per.bothner.com/
Reply | Threaded
Open this post in threaded view
|

Re: Difference in define behaviour between kawa.jar and embedded Scheme example

Mark Raynsford
Hello!

On 2017-11-23T03:26:20 +0100
Per Bothner <[hidden email]> wrote:

>
> On 11/22/2017 11:33 PM, Mark Raynsford wrote:
> > In other words, the redefinition of + on the second line is affecting
> > the existing definition of six0 so that the applications of six0 and
> > six1 are both returning 9. What's going on here?  
>
> The behavior of demo0.scm depends on whether it is evaluated line-by-line
> (as in REPL) or as a "module" (or "library" in R7RS-speak).  The latter
> is the default, but you can force teh former using the -f options.
> Compare:
>    $ kawa demo0.scm
> vs:
>    $ kawa -d demo0.scm
>
> Either implicitly imports (kawa base).  In general it is invalid to
> explicitly define bindings that conflict with imported bindings.
> We are somewhat more lenient with (kawa base), for compatibility
> with tradition, but it is still a bad idea.
OK, thanks. This is something I'm going to be looking into at the
source. As you know, I'm putting together a gratuitously incompatible
subset of the language, so I have no need for compatibility with
tradition. I'd rather get hard errors up front. To be honest, I'd
rather all redefines at the top-level be errors, but I assume this is
something I'm going to have to implement myself.

I actually ran into this behaviour because I was informally testing my
subclasses of Scheme/SchemeCompilation and was surprised that I could
override existing bindings like this (because being able to affect the
internals of existing definitions wasn't the behaviour I was used to
from other Schemes). I assumed that I'd broken something with my
subclasses, but then it turned out that the original Scheme class also
did this.

> Instead you can do something like:
>
> (import (except (kawa base) +))
> (import (only (kawa base) (+ orig-+)))
> (define (six0 x) (orig-+ 3 3))
> (define (+ x y) (* x y))
> (define (six1 x) (+ 3 3))
> (format #t "[~w ~w]~%~!" (six0 0) (six1 0))

Got it.

--
Mark Raynsford | http://www.io7m.com


attachment0 (849 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Difference in define behaviour between kawa.jar and embedded Scheme example

Per Bothner
On 11/23/2017 11:52 AM, Mark Raynsford wrote:
>
> OK, thanks. This is something I'm going to be looking into at the
> source. As you know, I'm putting together a gratuitously incompatible
> subset of the language, so I have no need for compatibility with
> tradition. I'd rather get hard errors up front. To be honest, I'd
> rather all redefines at the top-level be errors, but I assume this is
> something I'm going to have to implement myself.

Re-definitions are not allowed in files (modules), but they are allowed
in line-by-line mode (a REPL or a file processed with -f).

> I actually ran into this behaviour because I was informally testing my
> subclasses of Scheme/SchemeCompilation and was surprised that I could
> override existing bindings like this (because being able to affect the
> internals of existing definitions wasn't the behaviour I was used to
> from other Schemes).

Surely in most Schemes if f is implemented using gm and g is redefined,
then f will use the new definition (at least in a REPL)?
--
        --Per Bothner
[hidden email]   http://per.bothner.com/