Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread zeRusski
Luke, thanks. You were the first to get there and somehow I missed your 
reply :(

On Friday, 19 April 2019 22:31:41 UTC+1, luke.whittlesey wrote:
>
> `identifier-binding` might be useful if a binding can be defined outside 
> of set/define
>
>
> https://docs.racket-lang.org/reference/stxcmp.html?q=identifier-binding#%28def._%28%28quote._~23~25kernel%29._identifier-binding%29%29
>
>>
>>

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread Matthias Felleisen

Yes, I wanted to recall this trick for you and overshot :) 



> On Apr 19, 2019, at 6:04 PM, zeRusski  wrote:
> 
> Matthias, FWIW your first solution gave me a flashback from last year's 
> Summer School. I remember using this trick. Now I hope I don't forget when I 
> actually need it.
> 
> Thank you Michael and Matthias 
> 
> -- 
> 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 
> .

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread zeRusski
Matthias, FWIW your first solution gave me a flashback from last year's 
Summer School. I remember using this trick. Now I hope I don't forget when 
I actually need it.

Thank you Michael and Matthias 

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread zeRusski

On Friday, 19 April 2019 22:39:10 UTC+1, Michael Murdock MacLeod wrote:
>
> I'm in no ways a macro expert, but will this work? It uses 
> identifier-binding 
> to check if the identifier for the hash table is bound. 
>

Yep, looks like the winner. I should've inferred from the fact that 
"unbound identifier" is a compile time error that there must be a way to 
check said binding at compile time, sigh. Also, I only learnt that its a 
compile time error today and couldn't quite figure how the expander can be 
certain. Now I'm thinking, wait, all those syntax objects have sets of 
scopes attached for a reason.

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread Matthias Felleisen

I should have know better: 


(define-syntax (set/define stx)
  (syntax-case stx ()
[(_ id key val)
 (identifier-binding #'id)
 #`(begin
 (hash-set! h 'key val)
 h)]
[(_ id key val)
 #'(begin
 (define id (make-hash))
 (set/define id key val))]))


This isn’t exactly what you refer to with “is unbound at run-time” in other 
Lisps. 





> On Apr 19, 2019, at 5:33 PM, zeRusski  wrote:
> 
> Not quite what I had in mind. The following examples must all work without 
> errors:
> 
> #lang racket
> 
> ;; set/define defined here
> 
> (set/define h a 1)
> (set/define h a 2)
> (hash-set! h 'b 42)
> 
> (define bar (make-hash))
> (set/define bar a 1)
> 
> (define (foo)
>   (set/define local-h a 1)
>   (set/define local-h a 2)
>   (hash-set! local-h 'b 42)
>   local-h)
> 
> (foo)
> 
> Basically, if the identifier h is unbound at runtime
>   (set/define h key val)
> is the same as
>  (define h (make-hash))
>  (hash-set! h 'key val)
> 
> If h is bound
>  (hash-set! h 'key val)
> 
> -- 
> 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 
> .

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread Michael Murdock MacLeod
I'm in no ways a macro expert, but will this work? It uses identifier-binding 
to check if the identifier for the hash table is bound.

(define-syntax (set/define stx)
  (syntax-case stx ()
[(_ ht key value)
 (cond [(identifier-binding #'ht)
#'(hash-set! ht key value)]
   [else
#'(begin
(define ht (make-hash))
(hash-set! ht key value))])]))

On Friday, April 19, 2019 2:33:54 PM PDT zeRusski wrote:
> Not quite what I had in mind. The following examples must all work without
> errors:
> 
> #lang racket
> 
> ;; set/define defined here
> 
> (set/define h a 1)
> (set/define h a 2)
> (hash-set! h 'b 42)
> 
> (define bar (make-hash))
> (set/define bar a 1)
> 
> (define (foo)
>   (set/define local-h a 1)
>   (set/define local-h a 2)
>   (hash-set! local-h 'b 42)
>   local-h)
> 
> (foo)
> 
> Basically, if the identifier h is unbound at runtime
>   (set/define h key val)
> is the same as
>  (define h (make-hash))
>  (hash-set! h 'key val)
> 
> If h is bound
>  (hash-set! h 'key val)


-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread zeRusski
Not quite what I had in mind. The following examples must all work without 
errors:

#lang racket

;; set/define defined here

(set/define h a 1)
(set/define h a 2)
(hash-set! h 'b 42)

(define bar (make-hash))
(set/define bar a 1)

(define (foo)
  (set/define local-h a 1)
  (set/define local-h a 2)
  (hash-set! local-h 'b 42)
  local-h)

(foo)

Basically, if the identifier h is unbound at runtime
  (set/define h key val)
is the same as
 (define h (make-hash))
 (hash-set! h 'key val)

If h is bound
 (hash-set! h 'key val)

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread Luke Whittlesey
`identifier-binding` might be useful if a binding can be defined outside of
set/define

https://docs.racket-lang.org/reference/stxcmp.html?q=identifier-binding#%28def._%28%28quote._~23~25kernel%29._identifier-binding%29%29

On Fri, Apr 19, 2019 at 4:55 PM Matthias Felleisen 
wrote:

>
> 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  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.
> For more options, visit 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.
>

-- 
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.


Re: [racket-users] catch and bind an unbound id in a macro

2019-04-19 Thread Matthias Felleisen

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  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 
> .
> For more options, visit 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.