Re: [racket-users] Making sure I understand part of the GC docs

2017-11-17 Thread David Storrs
On Fri, Nov 17, 2017 at 9:05 AM, Matthew Flatt  wrote:
> At Thu, 16 Nov 2017 18:40:14 -0500, David Storrs wrote:
>> From the Guide:
>>
>> ---
>> This code [...] has a subtle bug:
>>
>> #lang racket
>> (let* ([fishes (list (fish 8 'red)
>>  (fish 7 'blue))]
>>[wb (make-weak-box (list-ref fishes 0))])
>>   (collect-garbage)
>>   (printf "still there? ~s\n" (weak-box-value wb)))
>>
>> Specifically, it will show that the weak box is empty, but not because
>> fishes no longer holds onto the value, but because fishes itself is
>> not reachable anymore!
>> ---
>>
>> The reason it's not reachable is because it is not actually referred
>> to in the source code, right?  It is theoretically still reachable in
>> the scope of the 'collect-garbage' call **if you actually put a
>> mention of it in the code** but in this particular case it's not
>> reachable because there is no such reference.
>>
>> In the next section they do exactly that and state that fishes is now
>> reachable again, so I want to confirm that I understand properly what
>> caused the change.
>
> Yes, that's basically correct.
>
> Beware that the requirement is a little stronger than "actually put a
> mention of it in the code". The mention has to be itself something that
> will execute, or that the compiler cannot prove won't execute.
>
> For example, the output will show "#f" for
>
>  (let* ([fishes (list (fish 8 'red)
>   (fish 7 'blue))]
> [wb (make-weak-box (list-ref fishes 0))])
>(collect-garbage)
>(printf "still there? ~s\n" (weak-box-value wb))
>(if #f
>fishes
>'no))
>
> because the compiler can trivially discard the first branch of the
> `if`.
>
> The compiler is also able to discard the first branch in
>
>   (if (not (pair? fishes))
>   fishes
>   'no)
>
> since it can track that `fishes` is a non-empty list. On the other
> hand, the compiler is not currently able to discard the first branch in
>
>   (if (= 0 (length fishes))
>   fishes
>   'no)
>
> since it doesn't track enough to know that `(length fishes)` will
> always produce 2 and never 0.
>
> Having to predict the compiler's behavior is problem; a some level,
> weak references are just not usable that way. For cases where it makes
> sense to drop down to implementation dependencies, the `ffi/unsafe`
> library provides `void/reference-sink` to help create a reference that
> the compiler cannot optimize away.


I see.  Good, thanks for the explanation.

I had been thinking about creating a module that would allow you to
tag property-like information onto any value instead of just structs,
because arbitrary tagging is really useful  My first thought on how to
do that was to do something like this:

(define lst (list 'alice 'bob 'charlie))
(set-property! lst 'committee-name "HR team in charge of staffing the
devops group")
(println (property lst 'committee-name)) ; prints "HR team in charge
of staffing the devops group"

(set-property! 7 'attributes '(prime happy-prime lucky))
(println (property 7 'attributes )) ; prints '(prime happy-prime lucky))

(struct fish (color size number))
(define cod (fish 'white 'medium 8))
(set-property! cod 'number-incrementor (lambda (f) (set-fish-number f
(add1 (fish-number f)
(println (property cod 'number-incrementor)) ; prints #

Behind the scenes this would be a parameter containing a weak hash
where the keys were the values you were tagging and the values were
hashes of property-name => property-value.  This got me concerned
about the impact on GC, and I wanted to understand the system a little
better.


>
> --
> 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] Making sure I understand part of the GC docs

2017-11-17 Thread Matthew Flatt
At Thu, 16 Nov 2017 18:40:14 -0500, David Storrs wrote:
> From the Guide:
> 
> ---
> This code [...] has a subtle bug:
> 
> #lang racket
> (let* ([fishes (list (fish 8 'red)
>  (fish 7 'blue))]
>[wb (make-weak-box (list-ref fishes 0))])
>   (collect-garbage)
>   (printf "still there? ~s\n" (weak-box-value wb)))
> 
> Specifically, it will show that the weak box is empty, but not because
> fishes no longer holds onto the value, but because fishes itself is
> not reachable anymore!
> ---
> 
> The reason it's not reachable is because it is not actually referred
> to in the source code, right?  It is theoretically still reachable in
> the scope of the 'collect-garbage' call **if you actually put a
> mention of it in the code** but in this particular case it's not
> reachable because there is no such reference.
> 
> In the next section they do exactly that and state that fishes is now
> reachable again, so I want to confirm that I understand properly what
> caused the change.

Yes, that's basically correct.

Beware that the requirement is a little stronger than "actually put a
mention of it in the code". The mention has to be itself something that
will execute, or that the compiler cannot prove won't execute.

For example, the output will show "#f" for

 (let* ([fishes (list (fish 8 'red)
  (fish 7 'blue))]
[wb (make-weak-box (list-ref fishes 0))])
   (collect-garbage)
   (printf "still there? ~s\n" (weak-box-value wb))
   (if #f
   fishes
   'no))

because the compiler can trivially discard the first branch of the
`if`.

The compiler is also able to discard the first branch in

  (if (not (pair? fishes))
  fishes
  'no)

since it can track that `fishes` is a non-empty list. On the other
hand, the compiler is not currently able to discard the first branch in

  (if (= 0 (length fishes))
  fishes
  'no)

since it doesn't track enough to know that `(length fishes)` will
always produce 2 and never 0.

Having to predict the compiler's behavior is problem; a some level,
weak references are just not usable that way. For cases where it makes
sense to drop down to implementation dependencies, the `ffi/unsafe`
library provides `void/reference-sink` to help create a reference that
the compiler cannot optimize away.

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


[racket-users] Making sure I understand part of the GC docs

2017-11-16 Thread David Storrs
>From the Guide:

---
This code [...] has a subtle bug:

#lang racket
(let* ([fishes (list (fish 8 'red)
 (fish 7 'blue))]
   [wb (make-weak-box (list-ref fishes 0))])
  (collect-garbage)
  (printf "still there? ~s\n" (weak-box-value wb)))

Specifically, it will show that the weak box is empty, but not because
fishes no longer holds onto the value, but because fishes itself is
not reachable anymore!
---

The reason it's not reachable is because it is not actually referred
to in the source code, right?  It is theoretically still reachable in
the scope of the 'collect-garbage' call **if you actually put a
mention of it in the code** but in this particular case it's not
reachable because there is no such reference.

In the next section they do exactly that and state that fishes is now
reachable again, so I want to confirm that I understand properly what
caused the change.

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