It depends what you want to do. Boxes are mostly used to simulate passing arguments by reference. They are also significantly slower (last time I checked, some time ago). There are a few cases where the GUI methods use boxes but should return multiple values instead (some historical thing I think)
I used a box once to serialize mutation that could happen from different web server threads. So a box was used for getting the effects of an atomic operation. But I did not use box-cas!, I just used box-set! and I was told that was still atomic. I never quite understood that. Perhaps box-cas! exists merely for using a hardware support that might be available?
set-box!
is atomic in the sense that no other code will be able to operate on the box at the same time. Performing an unbox
to grab a value from a box followed by a set-box!
is not “atomic”, though, because another thread may modify the box in between your thread’s unbox
and set-box!
.
This code shows the problem:
#lang racket/base
(define b (box 0))
(define thds
(for/list ([_ (in-range 100)])
(thread
(lambda ()
(define v (unbox b))
(sync (system-idle-evt))
(set-box! b (add1 v))))))
(for-each sync thds)
(unbox b)
I’m syncing on the idle event in the middle there to force the runtime to de-schedule the threads after the unbox because the code is too simple otherwise and it does end up running serially on my machine (but that doesn’t mean the problem isn’t technically there).
Here’s another example that doesn’t explicitly de-schedule the threads, but lets the runtime do it when each thread runs out of fuel:
#lang racket/base
(define b (box 0))
(define thds
(for/list ([_ (in-range 100)])
(thread
(lambda ()
(define v (unbox b))
(for ([_ (in-range 10000)])
(sqrt v))
(set-box! b (add1 v))))))
(for-each sync thds)
(unbox b)
@popa.bogdanp is correct about boxes, and also set! is atomic in the same sense as set-box!
What is the idiomatic way to select a random element from a set?
Must it truly be uniformly random? Or you just want any one of them?
For the former, I don’t see an efficient way to do it. The only solution I can come up with is converting it to a vector. Draw an index from the uniform distribution, and then pick the corresponding element.
I guess it also depends on how many times do you want to perform this operation, and is there a replacement
If you just want to do it once, reservoir sampling is another possiblity.
I want it to be uniformly random and I was wondering if there was anything better than conversion
I would suggest you to take a look at reservoir sampling