
My Go Resolutions for 2017 - mitchellh
https://research.swtch.com/go2017
======
munificent

        > Part of the intended contract for error reporting in Go
        > is that functions include relevant available context,
        > including the operation being attempted (such as the
        > function name and its arguments).
    

I know the Go folks don't like exceptions, but this is an example of them
learning the hard way that about one useful thing they lost by deciding to not
do exceptions.

Exceptions give you stack traces automatically. All of that context (and more)
is there without library authors having to manually weave it in at every level
of calls.

    
    
        > Today, there are newer attempts to learn from as well,
        > including Dart, Midori, Rust, and Swift.
    

For what it's worth, we are making significant changes to Dart's generics
story and type system in general [1]. We added generic methods, which probably
should have been there the entire time.

Generics are still always covariant, which has some plusses but also some real
minuses. It's not clear if the current behavior is sufficient.

Our ahead-of-time compilation story for generics is still not fully proven
either. We don't do any specialization, so we may be sacrificing more
performance than we'd like, though we don't have a lot of benchmark numbers
yet to measure it. This also interacts with a lot of other language features
in deep ways, like nullability, whether primitive types are objects, how lists
are implemented, etc.

[1]: [https://github.com/dart-
lang/dev_compiler/blob/master/STRONG...](https://github.com/dart-
lang/dev_compiler/blob/master/STRONG_MODE.md)

~~~
stickfigure
Having just spent the last two months writing Go code, exceptions are the
thing I miss most (well, besides the ternary operator and map/reduce
operations). Not only are errors painful to debug without stacktraces, but
every single method call is followed by three lines of "if err != null {". I
am amazed that folks tolerate the sheer amount of repetitive typing required
by the language.

~~~
divan
Changing the language is like changing the country residence. Some things take
long time to get used to, unless you're highly mobile traveller :)

I couldn't imagine myself returning to languages with exceptions and ternary
operators, for example.

~~~
stymaar
> I couldn't imagine myself returning to languages with exceptions and ternary
> operators, for example.

Why ? Is it because no language with those feature is good (let say you
wouldn't like to return to Java for instance), or is it because you genuinely
prefer this over ternary operator :

    
    
        if expr {
            n = trueVal
        } else {
            n = falseVal
        }

~~~
divan
Well, from my 15 years experience for each nice example of ternary operator
being useful there are 10 more examples where it's being used improperly and
makes code hardly readable.

I know that the typical answer is "it's just bad programmer", but that's where
Go chooses different view. Many design decisions in Go were taken with
awareness of the social context of programming.

If the feature incentivizes using it in a wrong way - it's not a bad
programmer, it's a bad feature. Programming language is a language between
humans in a first place and it should be readable as much as possible, it
should deincentivize using obscure and easy-to-use-improperly things.

It so much better when you go to practically any Go repository and find that
code is readable and clear. I've never had this experience with any other
language before.

PS. Found one of the real examples of abusing ternary operators. That was one
of the coolest I've seen. And I guess it's easy to understand that the same
programmer wouldn't write the same with "if .. else .." blocks in Go. He would
realize that it's too verbose and hard, hence probably wrong design, so he
need to find better solution within the space of language features.
[http://imgur.com/a/hjKOe](http://imgur.com/a/hjKOe)

~~~
pif
> If the feature incentivizes using it in a wrong way - it's not a bad
> programmer, it's a bad feature.

So there's nothing good about alcohol (it may cause liver damage), cars (they
may cause accidents), prescribed drugs (they may have unpleasant collateral
effects), ...

Hey, it's also true that programming incentivizes bugs, so programming is bad.
Let's stop programming!

~~~
nulltype
It's weird how people miss the conditional operator but not switch case
fallthrough.

------
bsaul
Along with generics, they should probably also reconsider algebraic data
types, such a enums with values. This is _the_ best feature swift adds to the
table hands on, and it seems to me as it's pretty orthogonal to the rest of
the language ( although it carries a lot of other features with it, such as
pattern matching).

They wrote that they considered it to be redundant with interface programming,
but really i don't understand why. Interface is about behavior, not data. An
int doesn't "behave" like one, it _is_ one. And something that's either an int
or an array of string, doesn't "behave" like anything you'd want to describe
with an interface...

As an example, one should see how protobuf "one of" messages are dealt with in
go : switch on arbitrary types followed by manual typecasting. That's just
gross...

~~~
xyzzy_plugh
I see where you are coming from, but that isn't the go way.

Switch on arbitrary types, followed by typecasting? That's the go way. No
surprises. Explicit instead if implicit behavior.

~~~
bsaul
If you have a look at swift, it's also very explicit, and non-magical ( which
is why i like it so much). The difference with go is that you can't make any
type error when unwrapping the enum, because the compiler knows what are the
different possibilities.

I see no reason for go not to adopt it, in all honesty. it's nothing like
generics, because it doesn't seem to add complexity to the rest of the
language ( imho ).

~~~
brandonbloom
> you can't make any type error when unwrapping the enum

This is also true in Go with type switches:

    
    
        switch y := x.(type)
            case MyStruct:
    

And with type assertions:

    
    
        y, ok := x.(MyInterface)
    

In both cases, y is of the correct type. The ok is optional, if omitted and
the assertion fails, you'll get a runtime panic.

~~~
dbaupp
y is of the type you asked for, yes, but that isn't necessarily the type that
should be there if the programmer makes a mistake, or if the underlying code
changes. With an enum, the types are written in one place, and the compiler
connects the dots, giving compile-time errors about mistakes/mismatched
expectations. This similar to how one can call `foo(x)` and the return value's
type is known, no need to first cast the function to the type the programmer
thinks it should be. The casting pushes type errors to execution-time rather
than compile-time.

~~~
brandonbloom
> The casting pushes type errors to execution-time rather than compile-time

Which is exactly what pattern matching does, which is what I was responding
about.

~~~
bsaul
Ok, i'm starting to understand what we're disagreeing on. You're talking about
pattern matching with dynamic expressions ( don't know the official name for
that), such as what you find in erlang, i'm talking very basic enum unwrapping
based on types, which is compile time checked. Swift also adds some kind of
dynamic expression to patterns, which may break exhaustiv checking, but in the
case of go, just a simple type check would be a great start.

Edit ( since i can't reply) : just look at
[https://developer.apple.com/library/content/documentation/Sw...](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html)
with something like the barcode example.

It's all compile time checked.

~~~
brandonbloom
> very basic enum unwrapping based on types, which is compile time checked

Sooo just accessing fields on a struct? I don't understand the distinction you
are trying to make.

~~~
dbaupp
It's like accessing fields on a struct, where you can only access the ones
that are guaranteed to be valid. For instance, in existing Go, the struct
method would be having two fields, * X and * Y, where (in theory) exactly one
of them is non-nil, but both can still be accessed. This requires manually
maintaining this invariant (and remembering to check when accessing), as well
as sacrificing performance by allocating. Using an ADT would allow storing the
X and Y by value, as well as guaranteeing that the invariant of "X xor Y" is
always true.

~~~
brandonbloom
Sounds like type-assertions cover that use case just fine. However, you are
correct that you can't do this without allocating. ¯\\_(ツ)_/¯

~~~
dbaupp
As people keep saying, type assertions do not have as strong compile time
assurances as ADTs.

~~~
brandonbloom
And as I keep saying: I don't value those assurances and in fact find them to
be a net loss when accounting for breaking changes changes to clients.

~~~
codygman
You pay the price of getting the bugs and edge cases out regardless of whether
you have compile time assurances.

The complexity is inherent and you can either choose to make it implicit and
play the losing game of ensuring it doesn't fail with tests or make it
explicit from the outset.

------
ekidd
I've always wanted to like Go, but every time I get ~1,500 lines in a project,
I remember my pain points. I totally see why other people like the current
version of Go, but as it stands, it's not an ideal match for my brain.

Dependency management is a big pain point for me. I'm really glad to see
several of my pain points on the list for this year, including another look at
generics.

Generics are genuinely tricky: They allow you to write many kinds of useful
functions in a type-safe manner, but every known approach for implementing
them adds complexity to the language. C#, Java and Rust all bit the bullet and
accepted (some) of this complexity. Maybe Go will find a sweet spot,
preserving its simplicity but adding a bit of expressiveness?

Anyway, it pleases me to see that the Go team is thinking hard about this
stuff. At the bare minimum, I'm going to be contributing code to other
people's open source Go projects for the foreseeable future. :-)

~~~
geodel
I think it is no surprise that one goal of Go is coding at large where large
teams are involved. For single person projects that I think you are doing,
many people want intellectually stimulating language where Go may fall short.

~~~
throwaw199ay
> I think it is no surprise that one goal of Go is coding at large where large
> teams are involved.

I don't buy that. There is no proof Go programming at large scales better than
Java programming at large.

Go didn't reach the scale of Java programs yet. And no, Kub or Docker, while
fairly large, are nothing compared to 15 y.o. multi-million line Java
codebases. Go certainly needs less bureaucracy due to the ease of deployment,
but it doesn't mean Go projects scale better in large teams.

> For single person projects that I think you are doing, many people want
> intellectually stimulating language where Go may fall short.

I really hate this kind of arguments. Features like generics aren't
intellectually stimulating, they are here because people want to write type
safe code. Context.Value(interface{})interface{} isn't type safe code.

Now tell me, what is more intellectually challenging? writing concurrent
programs free of race conditions or generics?

~~~
geodel
> Go didn't reach the scale of Java programs yet. And no, Kub or Docker, while
> fairly large, are nothing compared to 15 y.o. multi-million line Java
> codebases.

I didn't claim Java projects do not scale. They do. I use Java all the time at
my day job. I would use whatever makes sense. Maybe someday Rust is absolutely
essential I would use it then.

> Features like generics aren't intellectually stimulating, they are here
> because people want to write type safe code.

When people need generics they can use languages with generics facility then.
I am not arguing otherwise.

~~~
vkou
> When people need generics they can use languages with generics facility
> then. I am not arguing otherwise.

This is the point where Go's advocates disagree with its detractors. The
latter tend to feel that you need generics (Just like you need to program in
something higher level then assembly) far more frequently then they are told.

------
nine_k
Posts like this really return me the confidence in the future of Go the
language.

I very much wish Go to succeed, it's built on a few nice ideas, but where it
currently is it has a number of usability impairments that stop me from
wanting to work with it.

But I see that these impairments are _seen_ as problems by key developers, and
work is underway to eventually fix these problems. (And this is besides the
"routine", incremental but very important improvements, such as GC or stdlib.)

~~~
xienze
> But I see that these impairments are seen as problems by key developers, and
> work is underway to eventually fix these problems.

What will inevitably happen is that Pike et al will argue that such things are
merely problems because "you're doing it wrong" or "there's no way to do this
without any tradeoffs of any kind" (generics), and ultimately very little will
change.

~~~
twic
The other alternative is that they allow them, and Go slowly loses its magic
and becomes another Algol, C++, or Java.

~~~
meddlepal
God forbid it become as useful and ubiquitous as C++ or Java.

------
throwaw199ay
> Not enough Go code adds context like os.Remove does. Too much code does only

Well, the error interface is { Error()string } and gophers were told to use
errors as values, not errors as type because supposedly "exceptions are bad".
By providing context you are just re-inventing your own mediocre exception
system. Why use errors as value at first place if you need context? just put
exceptions in Go, therefore people don't need to use a third party library to
wrap errors in order to trace the execution context.

~~~
dilap
I really don't miss having invisible control flow for expected conditions
blowing up my programs with long stack traces.

There's a whole lot of space between "include useful context in errors" and
"exceptions".

(And FWIW, Go does have exceptions, it just calls them panics, and has a
culture not using them for "known knowns" error conditions.)

~~~
throwaw199ay
> I really don't miss having invisible control flow for expected conditions
> blowing up my programs with long stack traces.

As opposed to panics? Checked exceptions don't blow up in your face, you have
to handle them. Nil errors and type errors might yet these also happen to Go.
I see no difference with Java here. Go isn't better when it comes to error
handling, in fact Go is extremely tedious when it comes to error handling.

> (And FWIW, Go does have exceptions, it just calls them panics, and has a
> culture not using them for "known knowns" error conditions.)

So Go has both(unchecked exceptions and errors as "value"), how does it make
things better? it doesn't. If it did, the blog wouldn't be talking about
people "handling errors the wrong way".

~~~
dilap
I've found it helpful to distinguish between errors that are program bugs and
errors that are conditions of the outside world (network errors, invalid data,
etc).

I think it depends somewhat on the kind of software you're writing.

Being very careful with errors is quite handy for a long-running server
processes; maybe (maybe!) not so worth it for a program that starts and stops
within the attention span of a single user.

~~~
pvg
_errors that are program bugs and errors that are conditions of the outside
world_

That also happens to be the intended distinction between Java's checked and
unchecked exceptions.

------
stouset
> Not enough Go code adds context like os.Remove does. Too much code does only
    
    
       if err != nil {
           return err
       }
    

Is anyone else surprised that forcing programmers to do the tedious,
repetitive, and boring work of being a manual exception handler overwhelmingly
results in people doing the least amount of effort to make it work?

I feel like so many of the headaches of go could have been avoided had the
developers spent any time whatsoever thinking about the _programmers using
it_.

~~~
tombert
I think that the Go team worked very hard to make something that programmers
actually like using. Yes, it is annoying to do a lot of `check if err is nil`,
but at the same time, exception handling is something that can be esoteric,
whilst it's trivial to see what your example does.

I also feel like there has been a lot of emphasis put on keeping the APIs
consistent, which is something that a lot of developers will tell you makes
PHP a nightmare sometimes.

~~~
stouset
> Yes, it is annoying to do a lot of `check if err is nil`, but at the same
> time, exception handling is something that can be esoteric

People keep saying this, but the alternative doesn't have to be exceptions.

Rust strikes a great balance here. There's no nil, you _must_ handle the Err
case of a Result enum, or the None case of an Option enum (this is _much_
nicer than go; in go after `val, err := failingThing()`, it's entirely
possible to accidentally use `val` as a meaningful value, which is strictly
impossible in Rust), and you can use functions like `map` and `and_then` on
these types which has the benefits of explicit error handling without the
absurd loss of readability caused by dozens of identical error handling
clauses.

> I also feel like there has been a lot of emphasis put on keeping the APIs
> consistent

This isn't something special about go. This is a minimum requirement for a
language nowadays. Rust, Ruby, Python, Swift, and others all do this.

------
davekeck
Regarding error context: I'd advocate simple error-chaining using a linked
list. If a function fails, it returns an error wrapping the underlying error
as the cause, and so on up the stack. The top of the stack can inspect or
print the error chain ("A failed because B failed because ..."), or pinpoint
the error that was the root cause.

I would love for Go to include something like this:

    
    
        type Error struct {
            Description string
            Cause       error
        }
        
        func NewError(cause error, descriptionFmt string, args ...interface{}) error {
            return Error{
                Description: fmt.Sprintf(descriptionFmt, args...),
                Cause:       cause,
            }
        }
        
        func (me Error) Error() string {
            if me.Cause == nil {
                return me.Description
            }
            return fmt.Sprintf("%v: %v", me.Description, me.Cause.Error())
        }
        
        func RootCause(err error) error {
            if err, ok := err.(Error); ok && err.Cause != nil {
                return RootCause(err.Cause)
            }
            return err
        }

~~~
bjacokes
Check out [https://github.com/pkg/errors](https://github.com/pkg/errors)

~~~
bmurphy1976
Great library.

------
brightball
> In the long-term, if we could statically eliminate the possibility of races,
> that would eliminate the need for most of the memory model. That may well be
> an impossible dream, but again I’d like to understand the solution space
> better.

Unless I'm mistaken, this is an impossible dream as long as shared memory
exists. It's the core tradeoff that distinguishes the Erlang runtime from the
Go runtime (there are others, but they all stem from this).

Your goals are either memory isolation for better
distribution/concurrency/clustering/fault tolerance/garbage collection or
shared memory for ability to work with large datasets more efficiently.

It's one of those details that changing it would essentially create a new
language. You'd have code, packages and libraries that either worked that way
or they wouldn't.

IMO, this is an area where Go gets into dangerous territory of trying to be
all things to people. Be great at what you're good at which is the "good
enough, fast enough, portable enough, concurrent enough, stable enough"
solution for backend services in most standard web architecture.

If people need distributed, fault tolerant, isolated, race proof, immutable
run times that aren't quite as top end fast and aren't ideal for giant in RAM
data structures...there's already a well established solution there by the
name of Erlang (and Elixir). They made the tradeoffs already so you don't have
to reinvent them.

~~~
zzzcpan
> Your goals are either memory isolation for better
> distribution/concurrency/clustering/fault tolerance/garbage collection or
> shared memory for ability to work with large datasets more efficiently.

The isolation is not physical, but logical. Implementations are free to use
zero-copying and make everything just as efficient. Theoretically compiler
could even optimize message passing overhead away for systems with shared
memory in some cases. The opposite is also true, shared memory is also logical
and there is a lot of room for a lot of clever things, like eliminating races.

~~~
brightball
How can you eliminate races with shared memory in a concurrent environment?

~~~
dbaupp
Rust's "sharing xor mutability" guarantee eliminates data races by (usually
statically but also dynamically) ensuring that a memory location won't be
mutated when multiple places/threads can access it. Of course, the machinery
required for this in Rust is relatively complicated (e.g. as a side-effect, it
allows one to also forgo a GC without losing safety).

~~~
brightball
How is that different from a mutex lock?

~~~
dbaupp
Rust lets you be precise about placing the locks exactly where they are
needed, with compile time errors if a lock isn't locked when accessing data,
or a lock is missing. Fixing data races with locks for arbitrary code, without
more static guarantees in the language, essentially means locks have to be
held for most memory accesses: it's hard/impossible to tell if that location
will be accessed concurrently. (This is why CPython has a GIL: it's easier to
only let one piece of code execute at a time than to handle data races in
arbitrary code.)

[https://blog.rust-lang.org/2015/04/10/Fearless-
Concurrency.h...](https://blog.rust-lang.org/2015/04/10/Fearless-
Concurrency.html) is interesting reading.

------
geodel
Excellent read. Official package management looks more about 'when' than 'if'
now. As someone in Java world who did not graduated to Maven/Gradle and stuck
to ANT I hope it will be minimalistic and immediately useful to Go users.

~~~
Traubenfuchs
After three years of rogue Java development, maven was an epiphany to me. At
the beginning it has a very, very shallow learning curve.

------
sbov
> all the way up the call stack, discarding useful context that should be
> reported (like remove /tmp/nonexist: above).

It's simple. With exceptions, we got used to "errors" that are, by default,
debugable. But Go got rid of default debugable errors, and programmers are
lazy.

~~~
voidlogic
The problem isn't the methodology. Its the library support. I (for my
employee) wrote a library a few years ago (~go 1.1) with "errs.New" and
"errs.Append(err, ..work like fmt..)" that generates error that look like:

    
    
      main.go:13 main.main(): highest level error;
        Details: foo.go:8 foo.ExportedMethod(): mid level error;
        Details: foo.go:42 foo.innerMethod(): low level error!
    

It provides handy helpers like GetRootErr and PanicToError too. I hope we can
opensource it in the next month or two.

~~~
kodablah
It's not that it can't be done, it's that it's not in the stdlib. Without
being in the stdlib, each set of code solves the same problem in its own way
harming conformity. It's gotten so bad that some libs include stack traces and
some even parse panics. For example, how do I write a function that loops over
the error chain if it may have come from several libs with different impls?

The problem is they shot themselves in the foot and may have to incorporate a
form of "default" method to get around it like Java ended up having to. You
can't have a "ContextualError" type because what does "Cause()" return? If it
returns "errors.Error" then you require users to use a type assertion. If it
returns "ContextualError" then it can't chain existing errors without
wrapping. They also can't add anything to the "errors.Error" interface because
they would invalidate all existing impls of that interface.

~~~
Groxx
Python suffers immensely from this - libraries tend to reraise exceptions with
a new, descriptive type, but usually don't append the stack, and essentially
can't chain any custom data you may have added. Not having the complete causal
chain can seriously hamper debugging, and unless it's built in it's unlikely
to be adopted consistently.

Python 2 has nothing, and libraries haven't agreed on anything. Python 3 has
"raise ... from ...", which largely resolves it, but I'm not sure what
adoption is like. Anyone know?

------
zyxzkz
I really enjoyed reading this thoughtful post. He addresses a lot of the pain
points I've encountered when writing Go.

I know there probably won't be immediate fixes, but it gives me confidence in
Go's future.

------
jimbokun
"I don’t believe the Go team has ever said “Go does not need generics.” "

I think that's true, but I do think its been said by a number of Go users and
advocates, which is where the perception comes from.

~~~
kasey_junk
Meanwhile I've said "even if they don't introduce user defined generics it
would be nice if they fixed the language defined ones"

The builtin generics are a mess. At this point I don't trust the go team to
implement any more complicated generic system.

~~~
tomjakubowski
> The builtin generics are a mess.

Could you elaborate on this? I must not have used arrays, slices, maps, or
channels enough to find that there's some common issue with all of them, other
than that the user can't write her own functions generic over them.

~~~
kasey_junk
The most obvious problem is that variance doesn't work.

You cannot pass a []string to something that expects a []interface{} for
instance, even though you can put every item in the first in an instance of
the second.

------
vendakka
The go vet integration with go test looks interesting. I'm currently using
github.com/surullabs/lint [1] to run vet and a few other lint tools as part of
go test. It provides a nice increase in productivity for my dev cycle. Having
vet + other lint tools integrated into my dev+test cycle has caught a number
of bugs before they hit CI.

[1] [https://github.com/surullabs/lint](https://github.com/surullabs/lint)

Disclaimer: I'm the author of the above library.

------
maxekman
I would really like to see best practices in the documentation on how to
include the right amount of error context, as mentioned in the article.

Also what to put and not put in context objects is really important to
document as it could easily snowball into a catch-all construct and be totally
misused after a while.

------
kibwen
_> Test results should be cached too: if none of the inputs to a test have
changed, then usually there is no need to rerun the test. This will make it
very cheap to run “all tests” when little or nothing has changed._

I'll be curious to see how this pans out, because it sounds like a very deep
rabbit hole. Is there any precedent for this in other language toolchains?
I've seen some mondo test suites in Java that could desperately use it.

~~~
secure
[https://bazel.build/](https://bazel.build/) supports this. Bazel is Google’s
build system, open-sourced.

~~~
kibwen
From reading [https://bazel.build/versions/master/docs/test-
encyclopedia.h...](https://bazel.build/versions/master/docs/test-
encyclopedia.html) , it looks like Bazel's rules are quite strict (not to
mention Unix-specific), and requires writing a separate rules file to
configure test behavior (e.g. an "external" tag to denote tests that cannot be
cached). I anticipate that it would be difficult to retrofit such things onto
Go's existing ecosystem in-place (or any language's, for that matter),
especially without sacrificing Go's minimalist philosophy (i.e. "this function
is a test if its identifier begins with `Test`, end of story"), especially
considering Go's documented aversion to config files WRT package management.

As an optional external tool it may work quite nicely, however.

~~~
zaphar
Bazel's rules are _extremely_ strict. For what it's worth when I was at Google
all the Go code was built with Bazel. Most of the google engineers don't
experience this pain internally I imagine.

------
vbernat
Happy to see that being able to not use GOPATH is at last considered
seriously! During years, Go people wanted to force people to work their way.
We can still this state of mind in the associated bug report:
[https://github.com/golang/go/issues/17271](https://github.com/golang/go/issues/17271).

------
vorg
> it would be nice to retroactively define that string is a named type (or
> type alias) for immutable []byte

Perhaps an array is better than a slice, so `immutable [...]byte` Also, the
for-range loop would have to behave differently so I guess it's a version 2
change. And if semantics are changing anyway, I'd prefer a `mutable` keyword
to an `immutable` one.

~~~
tomjakubowski
> Perhaps an array is better than a slice, so `immutable [...]byte`

Slice is the right choice, I think. Were they to choose array as the alias,
the language would need to "bubble up" the "array length" type parameter to
the string type, which would make strings of different byte lengths
incompatible types. But hey, Go is already pretty clearly inspired by Pascal,
so maybe we'll see that after all :-)

------
jaekwon
Re dependencies:

Glide takes our team 90% of the way, but is a bit glitchy (need to wipe
~/.glide sometimes) & lacks a command for `npm link` type functionality.

------
jnlknl
Great !

------
BuuQu9hu
It is nice that Go is trying to learn from Pony and Midori. I wonder whether
any Gophers have started to learn about object-capability theory and the
_reasoning_ behind why so many values are immutable in Pony, Midori, Monte,
and other capability-safe languages.

To expand on this a bit, in ocap theory there is a concept of "vat", an
isolated memory space for objects which has its own concurrent actions
isolated from all other vats. In a vat model, data races are nearly
nonexistent; in order to race, one would have to choose a shared variable in a
single vat, and then deliberately race on it. But this is not common because
ocap theory enforces heavy object modularity, and so shared variables are
uncommon.

Additionally, a "deliberate race" is quite tricky. Vats prepare work with a
FIFO queue. In the Monte language:

    
    
      # A flag. We must start it as `false` because Monte doesn't allow uninitialized names.
      var flag :Bool := false
      def setFlag(value :Bool) :Void:
        flag := value
      # Set the flag to `true` immediately.
      setFlag(true)
      # Set the flag to `false` on the next turn.
      def first := setFlag<-(false)
      # Set the flag to `true` on the next turn.
      def second := setFlag<-(true)
      # And finally, when those two actions are done, use the flag to make a choice.
      when (first, second) ->
        if (flag) { "the flag was true" } else { "the flag was false" }
    

You might think that this is non-deterministic, but in fact the delayed
actions will each execute in order, and so the flag will be set first to
`false` and then to `true`.

