kaosjester
Joined 15 years ago
Joined 15 years ago
Dark Souls does precisely this in a fantastic way in two major mechanisms. The first is the shared player "graffiti", wherein players can write messages that are then propagated into others' games. The second is the shared "death ghosts', which play back a player's last moments before death in others' games as a ghost you can't interact with. These make the game feel like you're playing with others in a large world without having to actually put you in the same instance.
Can you give an example of what you mean?
"Global variables" are simply variables declared at a top-level scope. They don't need to be "dynamically bound" if you unravel the top-level into a sequences of statements that thread their environment (which is a bog-standard practice for interpreters, and how you should handle blocks, too), unless you'd like to be able to reference variables declared below you in the global scope. And that can be resolved by passing a dynamic environment in addition to the lexical one. Or by making a single pass over the global space, grabbing all the declared names, and making that your initial lexical environment. But, of course, this is all speculation without an example.
> I considered having a problem exercise to do effectively that, but I felt like it might be reaching a little too far for a first-time language implementer.
Uniquely renaming variables is, in my opinion, a far simpler concept to grasp than nesting scope resolution. It would also be far easier to implement, with notably less code change, and continue to allow you to add another compiler pass and allow the reader to cover ground. The actual downside is that it achieves your goal without needing to explain the whole mess, which means the chapter doesn't get to spend time explaining how to think about resolving variables.
> code like this is not common:
Your toy example is, obviously, a situation where you should reconsider what you're doing. However, a program such as
lookup :: Env -> Ear -> Value
lookup = ...
f :: Env -> Expr -> Expr
f env exp =
let lookup = lookup env
in ...
is a fairly common pattern in automatically curried languages, or languages with functional-style loops (see [0] for such a usage of shadowing). I don't think that your stance is wrong, but I think decrying other stances isn't particularly fair to the language design world, where there are many languages where such shadowing is neither rare nor often an error. Of course, there is some play here insofar as treating function declarations differently from other variables, which is not the case in many languages where this behavior is accepted.Also, for what it's worth, translating the above code to JavaScript yields a stack overflow error if you invoke lookup inside of `f`.
0. https://github.com/cisco/ChezScheme/blob/06f858f9a505b9d6fb6...
1. The first canonical solution, which the author even describes, is persistent environments. Unfortunately, this requires passing the current environment as part of the recursive pattern, which means heavily modifying the existing code. He doesn't do this because it would require revisiting too much.
2. The second canonical solution, which you would find in any modern compiler, is to uniquely rename all the variables. His "resolver" traversal has ample opportunity to do this, and would provide a far cleaner solution (with less space overhead than his expr/scope depth lookup table).
Instead, the author creates a stack of environments and annotates variables with information akin to de Bruijn indicies for scopes. Compared to the alternatives above, this is over-engineered and inelegent, plus it complicates reasoning about scopes far beyond what's necessary.
As an aside, this assertion is also completely absurd:
> Shadowing is rare and often an error so initializing a shadowing variable based on the value of the shadowed one seems unilkely [sic] to be deliberate.
> We ate on the balcony and, as we shared a bottle of wine and listened to the chorus of insects, I began to think that the year of groundwork I had put in was about to pay off. Marylin stayed the night.
It's one thing to give people the space and support they ask for. It's quite another to shove space and support, unsolicited, upon them.
> Are you on Facebook? Is this your profile?
> Yes, but I'm not gonna accept your friend request.
The reply was usually a bit snarky with a bit of a chuckle, and that did it for most college-aged people. The few times someone persisted, I explained that Facebook is an aspect of my social life, not my professional life, and I intended to keep it that way.