Suggestion: ephemeron-case
Daphne Preston-Kendal
(04 Feb 2025 10:08 UTC)
|
||
Re: Suggestion: ephemeron-case
John Cowan
(04 Feb 2025 11:35 UTC)
|
||
Re: Suggestion: ephemeron-case
Vincent Manis (he/him)
(04 Feb 2025 19:38 UTC)
|
||
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(05 Feb 2025 15:12 UTC)
|
||
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(05 Feb 2025 15:30 UTC)
|
||
Re: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(05 Feb 2025 18:04 UTC)
|
||
Re: Suggestion: ephemeron-case
Daphne Preston-Kendal
(05 Feb 2025 18:16 UTC)
|
||
(missing)
|
||
Fwd: Suggestion: ephemeron-case
Marc Nieper-Wißkirchen
(16 Mar 2025 13:19 UTC)
|
||
Re: Suggestion: ephemeron-case Marc Nieper-Wißkirchen (12 May 2025 11:51 UTC)
|
Daphne, can you check out the recent posts? We should move forward with SRFI 254. (Arthur asked about its state.) Marc Am So., 16. März 2025 um 14:19 Uhr schrieb Marc Nieper-Wißkirchen <xxxxxx@gmail.com>: > > I just noticed that I missed sending the following post to the mailing list. > > @Daphne: Does it answer your questions about how to use SRFI 254 and why the proposed `ephemeron-case` would be useless? > > Marc > > ---------- Forwarded message --------- > Von: Marc Nieper-Wißkirchen <xxxxxx@gmail.com> > Date: Fr., 7. Feb. 2025 um 15:28 Uhr > Subject: Re: Suggestion: ephemeron-case > To: Daphne Preston-Kendal <xxxxxx@nonceword.org> > > > Am Mi., 5. Feb. 2025 um 19:16 Uhr schrieb Daphne Preston-Kendal <xxxxxx@nonceword.org>: > > > > On 5 Feb 2025, at 19:03, Marc Nieper-Wißkirchen <xxxxxx@gmail.com> wrote: > > > > >> I don’t see how this is the case. The implementation would somehow need to both inline the helper-proc (in order to do the re-ordering optimization you were worried about when you introduced the reference-barrier procedure) but also discard the reference-barriering nature of the mention of ‘key’. This seems very unlikely. > > > > > > It should be possible to prove the correctness of a program formally. > > > For that, "very unlikely" is not enough. > > > > It’s up to the compiler to do this correctly (or not), of course. > > The compiler only has to follow the specification, not the intent of the programmer. > > > > That said, all semantics suggested so far have another problem, which > > > I haven't mentioned yet: A reference barrier on the key in the > > > unbroken case is useless. The GC can break an ephemeron if, under the > > > assumption that it is broken, the key will not be kept alive. > > > > > > I am going to post a "real life" example soon (I am currently ill, and > > > my brain is not fully working) so that we have some concrete code to > > > test potential syntax against. > > > > Okay, please do. I’m a bit confused by this. Get well soon! > > Thank you. I am still not feeling well, but I managed to produce some example code, which will be incorporated into the next draft. > > Here is a simple library for a list-based weak map: > > ** > #!r6rs > > (library (weakmaps) > (export > make-weakmap > weakmap? > weakmap-contains? > weakmap-set! > weakmap-ref > weakmap-delete!) > (import > (rnrs) > (rnrs mutable-pairs) > (srfi :254 ephemerons-and-guardians ephemerons)) > > ;; weakmap-ref and weakmap-contains? keep the KEY argument alive. > ;; The KEY argument to all procedures should denote a location or > ;; sequence of locations. > > ;; Note that no explicit tests for broken ephemerons are necessary > ;; because "the broken key" #f can never be a regular key. > > (define-record-type weakmap > (nongenerative) (sealed #t) > (fields (mutable entries)) > (protocol > (lambda (new) > (lambda () > (new '()))))) > > (define weakmap-contains? > (lambda (wm key) > (assert (weakmap? wm)) > (let f ([entries (weakmap-entries wm)]) > (if (pair? entries) > (if (eq? (ephemeron-key (car entries)) key) > (begin > (reference-barrier key) > #t) > (f (cdr entries))) > (begin > (reference-barrier key) > #f))))) > > (define weakmap-set! > (lambda (wm key val) > (assert (weakmap? wm)) > (let f ([entries (weakmap-entries wm)] > [set-tail! (lambda (tail) (weakmap-entries-set! wm tail))]) > (if (null? entries) > (set-tail! (list (make-ephemeron key val))) > (if (eq? (ephemeron-key (car entries)) key) > (set-tail! (cons (make-ephemeron key val) (cdr entries))) > (f (cdr entries) (lambda (tail) (set-cdr! entries tail)))))))) > > (define weakmap-ref > (lambda (wm key default) > (assert (weakmap? wm)) > (let f ([entries (weakmap-entries wm)]) > (if (pair? entries) > (if (eq? (ephemeron-key (car entries)) key) > (let ([val (ephemeron-value (car entries))]) > (reference-barrier key) > val) > (f (cdr entries))) > (begin > (reference-barrier key) > default))))) > > (define weakmap-delete! > (lambda (wm key) > (assert (weakmap? wm)) > (let f ([entries (weakmap-entries wm)] > [set-tail! (lambda (tail) (weakmap-entries-set! wm tail))]) > (unless (null? entries) > (if (eq? (ephemeron-key (car entries)) key) > (set-tail! (cdr entries)) > (f (cdr entries) (lambda (tail) (set-cdr! entries tail))))))))) > ** > > And here is some code to test it: > > ** > #!r6rs > > (import > (rnrs) > (srfi :254) > (weakmaps)) > > ;;; Weakmaps > > (define wm (make-weakmap)) > (assert (weakmap? wm)) > > (define x (string #\x)) > (define y (string #\y)) > > (assert (not (weakmap-contains? wm x))) > (assert (eq? 'dflt (weakmap-ref wm x 'dflt))) > > (weakmap-delete! wm y) > > (weakmap-set! wm x 1) > (weakmap-set! wm y 2) > > (assert (weakmap-contains? wm x)) > (assert (weakmap-contains? wm y)) > > (assert (eqv? 1 (weakmap-ref wm x #f))) > (assert (eqv? 2 (weakmap-ref wm y #f))) > > (weakmap-set! wm x 3) > (assert (eqv? 3 (weakmap-ref wm x #f))) > (assert (eqv? 2 (weakmap-ref wm y #f))) > > (weakmap-delete! wm x) > > (assert (eqv? 2 (weakmap-ref wm y #f))) > (assert (not (weakmap-contains? wm x))) > > (assert (eqv? 2 > (let ([tmp y]) > (set! y #f) > (weakmap-ref wm tmp #f)))) > ** > > Feel free to ask questions. The reference barrier is needed in the accessor procedures (`weakmap-contains?` and `weakmap-ref`). > > Marc >