Kinds of value in local variables

I’m sure this makes sense for some reason.

lab is room. 

A foo is a kind of value. The foos are normal.
A foo has a text called the magic word.

Q is a foo. The magic word of Q is "naxum".

C is a list of foos that varies.

When play begins:
	let X be a foo;
	now the magic word of X is "frotz";
	add X to C;
	let Y be a foo;
	now the magic word of Y is "rezrov";
	add Y to C;

Instead of jumping:
	repeat with Z running through C:
		say "[magic word of Z] ";
	say "[magic word of Q]";

>jump
rezrov rezrov naxum

Is there a workaround, or do I fundamentally misunderstand the nature of values?

Looks like there is only one foo, called normal. Thus, every time you change the magic word of any foo, you’re changing the magic word of normal.

Even if there were more foos, when you write let X be a foo, that is exactly equivalent to let X be normal, because normal is the first foo that was defined.

1 Like

But then how do “rezrov” and “naxum” both get printed when jumping? Is Q a new value of kind foo?

Ah, I was wrong about there being only one foo, good point. Yes, Q is an entirely separate foo, because you defined it as such. It is not a variable, just an instance of the foo kind.

There’s no requirement that every possible value is defined in one sentence like “The foos are normal and Q.”. You can define any number of them later on.

1 Like

But the answer to my other question “do I fundamentally misunderstand…” is a profound yes. I wish the documentation just said “yo, these are type-safe enums”, which seems to be what they are.

You’ve created one kind (foo) with two instances (normal and Q). When you say “let X be a foo” without specifying which one, it picks the first one defined, which is normal. Then the same happens for Y.

3 Likes

Indeed, these sorts of kinds of value are just enums. They’re also known as “enumerated kinds of value”, that’s just too long to say normally.

2 Likes

You can definitely think of them as enums. However, I normally think of an enum as a fixed set defined in one place, but enumerated values in Inform differ from that in the sense that you can easily extend the type with more values elsewhere in the source code.

For example, if you use Emily Short’s Postures extension, there is nothing stopping you from writing rolling around is a posture, and now there are four types of postures instead of three. (Just doing that wouldn’t automatically make the extension understand the new posture, mind you.)

Perhaps a better example is scenes. Scenes are just another enumerated type, just as if the Standard Rules had a line a scene is a kind of value. Entire Game is a scene.. (It’s actually hard-coded into the compiler instead, but there’s not much if any difference from if it were defined that way.)

It’s because it’s a magic word. If you didn’t want magic results, you shouldn’t have specified a magic word, that’s just science.

When you specify the possible values for an I7 enumerated value, you’re defining platonic ideals of those values. But when you assign one of those values to a variable (or create a constant during your initial assertions; I’m not one to judge) you’re casting a specific shadow onto the wall of the cave, i.e., the runtime environment.

So the platonic ideal of normal the foo has a commensurately platonic ideal of a text property called the magic word. But its shadows have actual magic word text properties, and when you assign to one, you’re assigning to the magic word property of some particular runtime shadow of normal.

(I think it was probably a bad idea to let values be created on either side of is. It creates an opportunity for error and misunderstanding without adding anything we’d miss if it were gone.)

[ Edited: as noted below, this is totally wrong! never mind. ]

I don’t think that’s the case—if X and Y were individual runtime “shadows” with individual magic word properties, it should print “frotz rezrov naxum”, not “rezrov rezrov naxum”, no?

My understanding is there’s only a single “normal”, and no matter how many different variables you stick it into, it only has a single magic word property—first set to “frotz”, and then to “rezrov”. Generally, nothing with properties (objects and values) can be created at runtime in Inform; the place where each property is stored is determined at compile-time.

2 Likes

I was naïvely hoping I could make an endrun around the object restriction by creating values, since in fact texts can be created at runtime. I was sadly wrong.

yup, you’re totally right; I was totally wrong; I’d written a test case that totally convinced me of several wrong things!

Yeah, Inform has a heap that can allocate and deallocate blocks of memory at runtime, but as far as I’m aware that only works for types built into the compiler, like lists and texts. Dannii previously had a Data Types extension that added some new ones, like maps and tuples, but the new compiler doesn’t allow that.

The new compiler offers really cool new tools for this, but it has to be set up as a kit; I6 inclusions won’t cut it.

1 Like

Yeah I used his maps in Crash IIRC.