<rntz>
is there anything vaguely like GADTs for contracts? or, just a way to make a collection of contracts indexed by a collection of values, but also get the "erased" contract that gives the union across all possible values?
<rntz>
e.g. I want val/c such that (val/c 'num) = number?, (val/c 'bool) = boolean?, and some way to extract anyval/c == (or/c number? boolean?)
lavaflow has quit [Ping timeout: 252 seconds]
ubLIX has joined #racket
Fernando-Basso has joined #racket
iyzsong has quit [Read error: Connection reset by peer]
pierpal has quit [Ping timeout: 252 seconds]
stchang has quit [Ping timeout: 252 seconds]
gabot has quit [Ping timeout: 245 seconds]
gabot has joined #racket
dented42 has joined #racket
pierpal has joined #racket
lavaflow has joined #racket
pierpal has quit [Ping timeout: 268 seconds]
_whitelogger has joined #racket
dented42 has quit [Ping timeout: 260 seconds]
iyzsong has joined #racket
dented42 has joined #racket
selimcan has joined #racket
Arcaelyx has quit [Ping timeout: 264 seconds]
Arcaelyx_ has joined #racket
dented42 has quit [Ping timeout: 272 seconds]
iyzsong-x has joined #racket
iyzsong has quit [Ping timeout: 264 seconds]
pierpal has joined #racket
dented42 has joined #racket
iyzsong-x has quit [Ping timeout: 272 seconds]
dented42 has quit [Ping timeout: 246 seconds]
<samth>
rntz: that would be relatively easy to implement, but doesn't exist that I know of
rnmhdn has joined #racket
pera has joined #racket
dented42 has joined #racket
jrslepak has quit [Ping timeout: 245 seconds]
jrslepak has joined #racket
wpcarro has joined #racket
<wpcarro>
I'm new to Racket, but I'm experimenting with it currently to test out a "hello, world"-like example for concurrency. I was hoping to re-create a problematic example where two threads attempt to increment a shared variable 10x each. The goal is to have the end result not always equal 20. I haven't been able to accomplish this, however, because it seems like Racket's runtime prevents this with atomic
<wpcarro>
`set!`. Is that a correct assumption?
pera has quit [Ping timeout: 246 seconds]
pera has joined #racket
<wpcarro>
I was hoping to use Racket to construct a pedantic walkthrough of semaphores and mutexes. But if I can't recreate the problematic scenarios, I might have to switch to another language that will let me shoot myself in my foot. I'd be sad to leave Racket though :/
<soegaard>
No. But you in, say, (set! x (+ x 10)) you have to be extremely lucky/unlucky for the system to switch between threads right after (+ x 1) and before (set! x ...)
<soegaard>
So you can for example introduce a delay to observe what you are after.
<soegaard>
(set! x (let ([y (+ x 1)]) (sleep 1) y)
<soegaard>
And perhaps let the pause be small in one thread and large in the other.
<wpcarro>
soegaard: hm interesting. I'll try this out. I read that "set! assigns to a variable as an atomic action with respect to all threads..." I was wondering if this was then a deal-breaker for me
<wpcarro>
I'm still new to some of these details, so my understanding my be misleading me
<soegaard>
I'll look up set! to see what it says.
<lexi-lambda>
The assignment is atomic, but there’s no guarantee that the evaluation of the RHS and the assignment together is a single atomic operation.
<soegaard>
^ +1
dented42 has quit [Ping timeout: 268 seconds]
<lexi-lambda>
The guarantee is just that you will never have partial reads/partial writes.
<lexi-lambda>
You could make a version of set! that non-deterministically introduces delays to increase the likelihood of pathological scenarios for the purposes of demonstrations, random testing, etc.
<wpcarro>
lexi-lambda: ah okay then. That's the part I'm struggling to understand. Racket's docs mentioned "half-assigned" variables. I tried to read more about this online, but couldn't find anything
<lexi-lambda>
Yes, `set!` guarantees that you will never end up with a “half-assigned” variable. This is, in a language like Racket, a fairly weak guarantee.
<wpcarro>
lexi-lambda: what might a half-assigned variable look like..? I'm having trouble imagining the scenario
<lexi-lambda>
Imagine for a moment some low-level language with a memory model like C’s, where values are just blobs of bits. It would be possible to imagine a non-atomic write operation where assigning to a value might overwrite the bits one-by-one, and theoretically, some other thread could read the data in the middle of the writing.
<lexi-lambda>
So if you had some 32-bit integer, perhaps some of the high bits would have changed when you read, but the low bits haven’t yet, producing a value that is neither the old value nor the new one.
<lexi-lambda>
In Racket this makes less sense, since values are not, conceptually, blobs of bits, and their representation in memory is opaque. So a “half-written” value wouldn’t be a Racket value at all, it’d just be garbage. The runtime prevents this from happening.
<wpcarro>
ah ha! Okay that makes a lot of sense. So if assignment isn't atomic, partial values become a concern
<lexi-lambda>
Right. So Racket doesn’t guarantee that (set! x (add1 x)) will atomically increment x by 1, only that reads from x cannot happen “in the middle of” the assignment, so you’ll only ever get back the new value or the old value.
<wpcarro>
lexi-lambda: okay and the "middle" being that "garbage" state that you alluded to? If so, this makes complete sense. Hence - why you called it a weak guarantee
<wpcarro>
Is that right?
<lexi-lambda>
Yes, that’s right.
<wpcarro>
wow. fascinating
<wpcarro>
Thank you
<lexi-lambda>
Admittedly, as soegaard mentions, it’s probably very unlikely that the Racket thread scheduler would switch threads between evaluating (add1 x) and performing the assignment, and indeed, I’m not sure if it ever would. But if the RHS were some more complicated operation, there might be a switch between reading x and writing x.
<lexi-lambda>
Since Racket threads don’t actually run in parallel, the possibility of two parallel processes interleaving reads/writes is impossible.
<wpcarro>
lexi-lambda: yeah I could see cyclomatic complexity or some other metric being useful to a thread scheduler determining if it might want to switch after evaling the RHS... maybe
<wpcarro>
lexi-lambda: hm is that to say then that the example I'm trying to illustrate is a fool's errand?
<lexi-lambda>
Even if it is possible (it might be, I’m not sure), it seems monumentally unlikely to ever fail in the way you’re looking for. But you could construct slightly different programs (albeit more complicated ones that obscure what you’re trying to demonstrate) that produce the behavior you want.
<wpcarro>
lexi-lambda: hm okay... maybe I'll try writing in something without a runtime like C to give me a more free-fall environment