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)

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
>