Skip to content

Commit

Permalink
Add syntax for string keys in let-hash. (#1121)
Browse files Browse the repository at this point in the history
Some tables contain string keys. Having let-hash properly handle string
keys is thus important. The '.$id' syntax is short and in line with the
other prefixes in let-hash. Weak accessor only.
  • Loading branch information
belmarca authored Feb 15, 2024
1 parent 6329eca commit ffdfe68
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 11 deletions.
13 changes: 7 additions & 6 deletions doc/reference/std/sugar.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,16 +294,17 @@ resolve as hash references.

More specifically, the macro rebinds `%%ref` so that identifiers starting with a `.`
are resolved with the following rules:
- `.x -> (hash-ref hash 'x)` ; strong accessor
- `.?x -> (hash-get hash 'x)` ; weak accessor
- `..x -> (%%ref .x)` ; escape
- `.x -> (hash-ref hash 'x)` ; strong accessor
- `.?x -> (hash-get hash 'x)` ; weak accessor
- `.$x -> (hash-get hash "x")` ; string weak accessor
- `..x -> (%%ref .x)` ; escape

::: tip Examples:
```scheme
> (def .c 4)
> (def h (hash (a 1) (b 2) (c 3)))
> (let-hash h [.a .?b ..c .?d])
(1 2 4 #f)
> (def h (hash (a 1) (b 2) (c 3) ("d" 5)))
> (let-hash h [.a .?b ..c .$d .?e])
(1 2 4 5 #f)
```
:::

Expand Down
4 changes: 2 additions & 2 deletions src/std/sugar-test.ss
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@

(test-case "let-hash"
(def .c 4)
(def h (hash (a 1) (b 2) (c 3)))
(check (let-hash h [.a .?b ..c .?d]) => [1 2 4 #f]))
(def h (hash (a 1) (b 2) (c 3) ("d" 5)))
(check (let-hash h [.a .?b ..c .$d .?e]) => [1 2 4 5 #f]))

(test-case "awhen"
(def (foo c) (awhen (v (char-ascii-digit c)) (* v v)))
Expand Down
12 changes: 9 additions & 3 deletions src/std/sugar.ss
Original file line number Diff line number Diff line change
Expand Up @@ -197,9 +197,10 @@
;; the hash deconstructor macro
;; usage: (let-hash a-hash body ...)
;; rebinds %%ref so that identifiers starting with a dot are looked up in the hash:
;; .x -> (hash-ref a-hash 'x) ; strong accessor
;; .?x -> (hash-get a-hash 'x) ; weak accessor
;; ..x -> (%%ref .x) ; escape
;; .x -> (hash-ref a-hash 'x) ; strong accessor
;; .?x -> (hash-get a-hash 'x) ; weak accessor
;; .$x -> (hash-get a-hash "x") ; string weak accessor
;; ..x -> (%%ref .x) ; escape
(defsyntax (let-hash stx)
(syntax-case stx ()
((macro expr body ...)
Expand All @@ -217,6 +218,8 @@
(let (str (symbol->string (stx-e #'id)))
(def (str->symbol start)
(string->symbol (substring str start (string-length str))))
(def (substr start)
(substring str start (string-length str)))
(if (eq? (string-ref str 0) #\.) ; hash accessor?
(cond
((eq? (string-ref str 1) #\.) ; escape
Expand All @@ -225,6 +228,9 @@
((eq? (string-ref str 1) #\?) ; weak
(with-syntax ((sym (str->symbol 2)))
#'(hash-get ht 'sym)))
((eq? (string-ref str 1) #\$) ; string weak
(with-syntax ((sub (substr 2)))
#'(hash-get ht 'sub)))
(else
(with-syntax ((sym (str->symbol 1)))
#'(hash-ref ht 'sym))))
Expand Down

0 comments on commit ffdfe68

Please sign in to comment.