I had the impression that you want to create the hashtable when it’s not there and use it when it is:
#lang racket (define-syntax (set/define stx) (syntax-case stx () [(_ id key val) (syntax-local-value #'id (lambda () #f)) (with-syntax ([h (car (syntax-local-value #'id (lambda () #f)))]) #`(begin (hash-set! h 'key val) h))] [(_ id key val) #'(begin (define-syntax id (cons #'h 0)) (define h (make-hash)) (set/define id key val))])) (set/define h a 1) (set/define h a 2) To make sure you can see the hashtable, I also return it after every set/define. > On Apr 19, 2019, at 4:17 PM, zeRusski <vladilen.ko...@gmail.com> wrote: > > Here's what I've been trying and failing to do in Racket. The smallest > example I > could think of is a macro that sets a key in a hash-table, so basically this > transformation: > > (set/define ht 'key 42) > ;; => > (hash-set! ht 'key 42) > > > but if ht there is an unbound identifier it must bind it to a fresh hash > table. So > basically introduce a (define ht (make-hash)) before setting the key. Assume > we > run in a context where define is allowed. > > Please, don't ask why I want something like this, I just do. So far tricks I > could > use in other lisps failed in Racket. Here's one silly idea: catch unbound > identifier exn. You can do it as per below or in the handler itself but it > doesn't > matter cause that define is local (I think) and doesn't happen in the macro > use > context. > > (require (only-in syntax/macro-testing convert-compile-time-error)) > > (define (unbound-id-error? err) > (and (exn:fail:syntax? err) > (regexp-match #rx"unbound identifier" (exn-message err)))) > > (define-syntax-rule (set/define id key val) > (unless (let/ec k > (with-handlers ((unbound-id-error? (λ (_) (k #f)))) > (convert-compile-time-error > (hash-set! id key val)))) > (displayln "escaped") > (define id (make-hash)) > (hash-set! id key val))) > > (set/define ht 'key 42) > ;; => > ;; runs but appears that the (define ht ..) doesn't happen at top-level > > This is already all sorts of ugly and it doesn't even work. > > Another idea is to replace #%top for the extent of that transformer, perform > local-expand (or some equivalent) so that #%top expansion does the job. I've > no > idea how to do that, but I'm sure Racket could be persuaded. Incidentally, I'm > curious how to create such local transformers e.g. something like > (let-transformer((#%top ...)) body). > > Even if I knew how to do the above (local-expand #'(set/define ht 'key 42) > '()) > run at compile time doesn't seem to wrap unbound ht in #%top. I thought it > should? > > So then, two questions: > > 1. What's the Racket way of getting what I want? > > 2. Is there a way to torture the above code into submission? Put differently > is > there a way to ensure (define id (make-hash)) runs in appropriate context? > > -- > You received this message because you are subscribed to the Google Groups > "Racket Users" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to racket-users+unsubscr...@googlegroups.com > <mailto:racket-users+unsubscr...@googlegroups.com>. > For more options, visit https://groups.google.com/d/optout > <https://groups.google.com/d/optout>. -- You received this message because you are subscribed to the Google Groups "Racket Users" group. To unsubscribe from this group and stop receiving emails from it, send an email to racket-users+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.