[I7] Second order logic

I can define a properties holding a number for all people like this:

A person has a number called body. The body of a person is usually 5. A person has a number called mind. The mind of a person is usually 5. A person has a number called spirit. The spirit of a person is usually 5.
But I cannot have this and have body, mind and spirit all be objects of a certain kind, can I? I’d love to be able to write stuff like this:

repeat with X running through faculties: repeat with Y running through persons: now X of Y is 6
and thus setting the body, mind and spirit of every person to 6. But there is no way to get such second order logic in Inform 7, right?

Not easily.

“Body”, “mind”, and “spirit” in that code are constants of type “numbers valued property”. But there’s no simple way to make use of a variable of that type. You could write a phrase to do that using I6 code, but I wouldn’t recommend it.

The most straightforward way to do what you want, I think, would look like this:

An abstract stat is a kind of thing.
Body-stat is an abstract stat.
Mind-stat is an abstract stat.
Spirit-stat is an abstract stat.

To decide what number is the abstract (stat - abstract stat) of (P - person):
	if stat is body-stat, decide on the body of P;
	if stat is mind-stat, decide on the mind of P;
	if stat is spirit-stat, decide on the spirit of P.

Every turn:
	repeat with N running through abstract stats:
		say "You have [N] of [the abstract N of the player]."

Then you also need a phrase “set abstract (stat - abstract stat) of (P - person) to (N - number)”, of course. Writing these phrases out is tedious but easy.

Thanks, zarf. I suspected that something like this would be the only practical way of getting what I want, but I had some slight hope that I was missing a better way of doing it. Unfortunately, I wasn’t. :wink:

In every other programming language I can think of you could either use strings as keys directly and store the values in some sort of array or map or on-the-fly object (e.g. ruby, PHP, JavaScript), or you could at least use something like an enum or just integer valued variables and use them as indices into an array.

I’m thinking with some work you can do something similar in I7 too - using the name to dig out a line of a table, or using an integer value as an index to a list. Right?

Edit: I mean, obviously i7 is a compiled language so dynamic objects straight from JSON or whatever is hard to do, but even a typed compiled language can have maps using string keys.

Like I said, the name is a typed constant, and there are I6 internals which can apply a given property constant to a given object. Rigging this up is easy; I only disrecommend it because I6 internals may change between versions. You could request it as a feature and then it would be stable.

Another way to attack this in pure I7 is to use relations instead of properties. Start with “Strength relates one person to one number”, and then you can pass relation values around and say “let N be the number that Steve relates to by R”.

Yeah… It just seems like a complicated way of doing something that ought to be trivial - store values as key/value pairs, iterate over the keys or using keys from another list. Bam. All you need.

Maybe it’s just me still not having mastered the way of Inform7.

Your “bam” comes from languages where Everything Is A Map in some sense (Perl, Python, Javascript). It isn’t a universal. Really, in most compiled languages, data structures / objects are something else entirely; maps (dicts, hash tables) are a separate thing that comes in from a library somewhere. (You can’t iterate through the keys of a C struct or a Java object, except by tortuous circumlocutions.)

I7 behaves as a compiled language in this sense. But instead of going down the path of offering hash tables on the side, it gets into properties and then relations. Relations are exactly the same access pattern as hash tables (“get me the X of Y, stat!”) and largely fulfill the same role. That’s why I suggested them above.

(Arguably, I7 properties and relations are two different skins for the same underlying “X of Y” concept and should be unified. But that’s a separate argument.)

You’re right. I mean I know I7 is not a scripting language, and I was talking of maps “on the side” as you say, as in Java where you’d do something like

Map<String, Integer> stats = new HashMap<String, Integer>();

and iterate over them as

for(String stat : stats.keySet()){
    // set values using stats.put(stat, 3)
}

So I don’t quite agree, the “bam” can be there in compiled languages too, and I still think using explicit data structures to do things can be really straightforward.

But I get your point, and you’re right - Inform7 already has other ways of doing these things, it’s just that to me it’s not always intuitive to see how you’d do it. But that’s my problem. Thanks anyway, it’s useful for me to work out these mappings (no pun intended) of “how I’d do stuff in other languages” to “how it’s done in Inform7”.

C: No, but Java does allow that via its reflection mechanism.

I think I was safe in including Java’s reflection mechanism under “tortuous circumlocutions”. :slight_smile:

I’ve had another problem which could be solved more easily if it was possible to iterate through kinds. Are we sure that is impossible even in I6?

I don’t think the question has come up before…? At the I6 level, classes are just VM objects whose parent is the “Class” object. You can’t iterate through them using normal I6 code (objectloop or sibling()) because those have built-in tests for arguments that are not regular objects. But you could write a loop in assembly without much trouble.

You could try using the KindHierarchy array, which I7 generates as something like this:

Array KindHierarchy --> K0_kind (0) K1_room (0) K2_thing (0) K3_direction (0) K4_door (2) K5_container (2) K6_supporter (2) K7_backdrop (2) K8_person (2) K9_region (0) K10_man (8) K11_woman (8) K12_animal (8) K13_device (2) K14_vehicle (5) K15_player_s_holdall (5) ;

Unfortunately it’s not terminated, so you’d have to be careful about detecting the end of the array.

Thank you both. Is there a corresponding hierarchy array for kinds of values? Actually they probably don’t have a hierarchy do they…

My feeling is that my problem is connected to Victor’s, but I’m not sure exactly how!

IIRC they basically are, except for various-to-various and “in groups” relations, which are kind of strange anyway.

No, they’re two different language features which have overlapping – but not identical – capabilities. They require different syntaxes to use. There are things you can do with one that you can’t do with the other. That’s what I mean by “not unified”.

OK, yes, they use different syntaxes. But one-to-various and vice-versa use properties internally, right?

Sometimes. Static relations between objects are implemented with properties, yes. But dynamic relations (those that begin life in a variable or property) are implemented with hash tables, and IIRC so are some static relations involving values.

Another difference is that relations are optimized to answer the question “does the relation hold between X and Y”, so they may be less efficient than properties if you want to find the Y for a given X. For instance, some dynamic relations use a double hash arrangement where you need both values to do a regular hash table lookup.