Re: [sawfish] Re: The dark corners of rep
- From: Eli Barzilay <eli barzilay org>
- To: General discussion about sawfish wm <sawfish-list gnome org>
- Subject: Re: [sawfish] Re: The dark corners of rep
- Date: Wed, 13 May 2009 18:42:42 -0400
On May 14, Timo Korvola wrote:
> Eli Barzilay <eli barzilay org> writes:
> > * Even worse, `defvar' does its magic in a way that shadows possible
> > later definitions:
> >
> > user> (defvar x 123)
> > x
> > user> (define x 1234)
> > user> x
> > 123
>
> That looks like a bug:
> user> (let ((x 1234)) x)
> 1234
> user> (let () (define x 1234) x)
> 123
> Those two should be equivalent.
My guess is that
(let () (define x 1234) x)
gets flattened somehow to just (define x 1234), which doesn't work in
the same way I showed. (And my guess is that this flattening is
intended to mimic lisp code, but it's not needed.)
> It seems to work if you don't use defvar:
> user> (define y 123)
> user> (let () (define y 1234) y)
> 1234
Righ -- but after you do the above you get the toplevel `y' set to
1234.
> It also works inside defines:
> user> (define (foo) (let () (define x 1234) x))
> user> (foo)
> 1234
That's why I said that it's similar to JavaScript -- `define' seems to
be done at the nearest function scope. It's very confusing to deal
with in JavaScript, and even more in rep because you'd expect scheme
or lisp-like behavior.
> > which is of course not needed, because you can do the usual
> > thing in scheme:
>
> Scheme also allows creating local bindings with define in the
> beginning of the body of a lambda or let.
Yes, two equivalent ways to define the counter example would be:
(define count!
(let ((counter 0))
(lambda () ...)))
(define count!
(let ()
(define counter 0)
(lambda () ...)))
> > which happens because `define' is actually more like Lisp's
> > `defvar' and `defun' in that it has a global effect
>
> Looks like another bug that only affects toplevel. Inside defines
> define seems to create local definitions as expected.
Hmm, that *does* seem to be a correct analysis -- nested scopes inside
functions do behave as expected:
user> (define (foo)
(define x 1)
(let () (define x 2) x)
x)
user> (foo)
1
So this makes `rep' be like JavaScript for toplevel definitions
only...
Here are some more gems:
* These wouldn't work in Scheme:
user> (define (foo)
(define x 1)
(define x 2)
x)
user> (foo)
2
user> (define (foo)
(define x 1)
(define x (+ x 1))
x)
user> (foo)
2
user> (define (foo)
(define x (cons 1 x))
x)
user> (foo)
(1)
user> (letrec ((x x) (x 2)) x)
2
user> (letrec ((x (cons 1 x))) x)
(1)
* I'm sure that some people will want to wave that away as doing
something reasonable, but:
user> (define (foo)
(define x 1)
x
(define x 2)
x)
user> (foo)
1
;; Why didn't that return 2? Because the second define turned to
;; a global one:
user> x
2
And of course the expression that gets assigned to the global is
evaluated in the local context:
user> (define (foo)
(define x 1)
x
(define x (+ x 1))
x)
user> (foo)
1
user> x
2
* rep does have `symbol-value', as used in lisps to access the global
value of a symbol -- but in rep it returns the lexical value instead
(which misses the whole point of this function):
user> (define (foo)
(define x 1)
x
(define x (+ x 1))
(symbol-value 'x))
user> (foo)
1
user> (symbol-value 'x)
2
This goes in line with the fact that `set' can actually be used to
change locals.
--
((lambda (x) (x x)) (lambda (x) (x x))) Eli Barzilay:
http://www.barzilay.org/ Maze is Life!
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]