[racket] for/hash: bad syntax in: for/hash

From: Marijn (hkBst at gentoo.org)
Date: Wed Jan 4 10:40:55 EST 2012

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 04-01-12 10:57, Marijn wrote:
> On 03-01-12 20:15, Eli Barzilay wrote:
>> Two hours ago, Marijn wrote:
>>> Hi,
>>> 
>>> for/hash is giving me a syntax-error, but the error is in 
>>> macro-expanded code which is not shown by default and which is 
>>> also seemingly inaccessible via the macro-stepper. The for/hash
>>>  expression works outside my macro, so I guess it's my fault,
>>> but it would help if the syntax-error could be a bit more 
>>> informative. The code: [...]
> 
> Thanks for taking the time to look into this.
> 
>> 4. It's now easy to continue reducing it to the core of the 
>> problem:
> 
>> (define-syntax with-variables (syntax-rules () ((_ (a ...)) 
>> ((with-variables a) ...)) ((_ a) a))) (with-variables (let* ((y
>> 1)) 2))
> 
>> Looks like you're doing a code walk (which is what makes me think
>>  that this is too complex for whatever it is you're trying to
>> do), and treat some names in a special way.  The problem is that
> 
>> ((with-variables a) ...)
> 
>> is creating a function application so the error is the same as 
>> just entering `let*' to get its value -- and the only error that
>> it can throw at this point is a "bad syntax" with the whole 
>> expression, which is just `let*'.
> 
> It took me a while to understand what you're saying here, but if I
> am not mistaken you're saying that the result of the
> macro-expansion is a function-application with `let*' (or
> `for/hash') in the function position. Then when #%app looks that
> name up in the environment it doesn't find anything and thus
> complains about it. What I would then expect is that it complains
> about an undefined variable `let*'.
> 
>> 5. And BTW, the reason it doesn't work is that the first
>> expansion gets to
> 
>> ((with-variables let*) (with-variables ((y 1))) (with-variables 
>> 2))
> 
>> and this form is not a macro -- so it's expanded as a function 
>> call,
> 
>> (#%app ...same...)
> 
>> and the rest is obvious.
> 
> It's not so obvious to me why this should degenerate into a
> function call; I'd say it depends on the result of (with-variables
> let*).

Okay, so I thought about this some more... and while I still think
this is weird behaviour, for my current code it is rather academic, as
it would just fail with unexpanded macro-calls in the arguments of
let*. Which means that I've again fallen into the trap of not thinking
hard enough about how macros are different than functions. Basically,
my idea was to transform:

  (dependent-boxes
   ((a)
    (b (* 2 a))
    (c (+ 2 a b))))

into something which would automatically propagate changes in any
cell/box to any other box which was dependent on it. Pretty much
exactly like a spreadsheet does. As target for that transformation I
had chosen something like:

  (letrec
      ((value-store (mlist (mcons 'a #f) (mcons 'b #f) (mcons 'c #f)))
       (rule-store (make-hash
		    `((a . ,(lambda () ""))
		      (b . ,(lambda () (* 2 (value-store-ref 'a))))
		      (c . ,(lambda () (+ 2 (value-store-ref 'a) (value-store-ref
'b)))) ))))
    ...)

together with surrounding structure such that values could be entered
and read and such that for each value-change, dependent boxes would be
updated automatically. Before today I though this was a pretty sweet
setup. But even if my macro had worked as I had intended, it wouldn't
have respected lexical scope within rules. So I guess it's back to the
drawing board for me. (I don't recall there being any logic to using
an alist for the value-store and a hash-table for the rule-store.
Probably that's just how things grew...)

Marijn

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.18 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk8EcwcACgkQp/VmCx0OL2xEyQCggrb6Fq2hc5EB2ujJGsS/SNpH
RBQAoJf0wk6t6P/zESx8xBwAZnTCsit6
=3zAm
-----END PGP SIGNATURE-----


Posted on the users mailing list.