# [I7] Understanding via relation to KOV

I’m missing something here. The following (contrived, yes) example should make it obvious:

``````Color is a kind of value. The colors are red, green, blue.

Hue relates a thing to a color. The verb to like means the hue relation.

Hue-indirection relates a thing (called x) to a color (called y) when x likes y.

A person (called its fan) likes every color.

Understand "[something related by reversed hue-indirection]" as a person.

There is a room.  All persons are here.

Test me with "x red fan".
``````

My original attempt was understand via the reversed Hue relation directly. I got a slew of runtime errors. However, what I can’t quite understand without going into the I6 layer (something I don’t have the time for at the moment) is why the indirection of using a computed relation fails to give a positive result even when the hue relation should hold.

Did you try `x red's fan` instead? That’s what they’re actually called.

Or am I misunderstanding your problem?

I’m afraid so.

What I want is the ability to Understand based not on a property, a relation of things to things, or a relation-ss-value (i.e computed), but by a relation of things to (kind of) value.

In the example, I used the automatic generation of objects to quickly generate objects that would have the relations already set. Perhaps that muddled my point; here’s another attempt.

``````"Undertest" by Björn Paulsen

Color is a kind of value. The colors are red, green, blue.
Hue relates a thing to a color. The verb to like means the hue relation.

Adam, Betty, Claire, David and Edith are people.

Adam and David like red.
Betty likes blue.
Claire likes green.

Understand "fan of [something related by reversed hue]" as a person.

There is a room.  All persons are here. Test me with "x fan of red".
``````

This fails, and I’m not clear on why it shouldn’t work, at least conceptually. If we reverse the understand token (`Understand "fan of [something related by hue]" as a person.`) we also get a cascading runtime error.

Alternative answer 1: if you use `(called fan of it)` instead then Inform will automatically recognise `red fan` without the understand rule.

But I don’t think you can do it that way. `[something]` must match an object, not a value, so it reasonably follows that `[something related by reversed hue]` could only work if `color` was a kind of thing, not a kind of value.

(I don’t get any errors when writing `something related by reversed hue`, incidentally. It just doesn’t match anything.)

This sort of works, though:

``````Understand "[color]" as a person when the item described likes the color understood.
``````

For reasons I don’t entirely understand, `x red` and `x red fan` both work with this, while for blue and green it will consider it ambiguous if you only mention the color and not also `fan`.

Edit: oh wow, this is really weird. I’m getting completely inconsistent results from that now, including having it sometime ambiguous, sometimes matching one object (and not necessarily the right one), and changing behaviour when parser tracing is on. Probably that means it needs a different variable name in the definition, but I’m not sure which one.

Indeed it sort of works, but only for your first attempt. After that, it will automatically match even the wrong person.

But I don’t think you can do it that way. `[something]` must match an object, not a value, so it reasonably follows that `[something related by reversed hue]` could only work if `color` was a kind of thing, not a kind of value.

I’m unclear why that isn’t possible, since it’s perfectly possible to do that very thing to a KoV property.

You can obviously do the indirection of adding it as a blank property, then do a ´when play begins´ rule that loops over each of these objects that match and sets the property if the relation holds. That’s what I’m doing at the moment. It’s verbose and it doesn’t really add anything to code legibility save confusion.

What I’m asking is, I suppose, if it’s not more reasonable to consider this a bug, since one would expect property tests and relation tests to not behave similarly, irrespective of implementation differences.

It’s not a bug, it’s just not a feature. Relations were originally intended to relate objects to other objects; relations to values seem like more of an afterthought.

In fact, try typing `RELATIONS` in this test story and you’ll see an actual related relation bug.

That one can be fixed by adding this, however:

``````Include 6M62 Patches by Friends of I7.
``````
2 Likes

That is excellent. It’s a pity that, as you say, the two bugs aren’t quite related, but it’s still good to see.

I believe you’re right. I can accept that it’s not part of the full featureset, and yet it’s very cool that we’re able to patch at least some things related to object creation without touching NI.

@Eleas, I’m quite familiar with this problem, having written a bug report about this issue years ago. (I’d cite it on Mantis, but it’s still down.)

The `Understand` line from @mirality very much seems like it should work, but the way that it is translated at the I6 level has an order of operations problem, such that the value of `parsed_number` (which will hold the color understood) is being checked prior to the attempt to parse the color word (which will set `parsed_number` to the desired value).

There’s no way to change the compiler behavior, but you can insert a short I6-level workaround:

``````"Undertest"

Color is a kind of value. The colors are red, green, blue.
Hue relates a thing to a color. The verb to like means the hue relation.

Adam, Betty, Claire, David and Edith are people. Understand "fan" as a person.

Adam and David like red.
Betty likes blue.
Claire likes green.

Include
(-
Global dct_wn_tmp;

[ DummyColorTest ;
dct_wn_tmp = wn;
ParseTokenStopped(GPR_TT, Kind_GPR_53);
wn = dct_wn_tmp;
];
-).

To decide whether the next word is a color word: [force "early" parsing of next word to set parsed_number]
(-
(DummyColorTest())
-).

Understand "[color]" as a person when the next word is a color word and the item described likes the color understood.

There is a room.  All persons are here. Test me with "x blue fan / x green fan / x red fan / david".
``````

which yields:

``````room
You can see Adam, Betty, Claire, David and Edith here.

>X BLUE FAN
You see nothing special about Betty.

>X GREEN FAN
You see nothing special about Claire.

>X RED FAN
Who do you mean, Adam or David?

>DAVID
You see nothing special about David.
``````

and seems to work reliably in my brief tests.

EDIT: I should add that this is a bit brittle because it uses the generated name for the routine (`Kind_GPR_53`) which could change if the source code is modified. There should be a way to use an I7-level insertion, though.

EDIT: This is slightly more resilient to changes in source code:

``````Include
(-
Global dct_wn_tmp;

[ DummyColorTest ;
dct_wn_tmp = wn;
ParseTokenStopped(GPR_TT,  DCTSetParsedNumber);
wn = dct_wn_tmp;
];

[ DCTSetParsedNumber
original_wn ! internal use only
group_wn ! internal use only
v ! internal use only
w ! internal use only
rv ! internal use only
;
original_wn = wn;
wn = original_wn;if (NextWordStopped() ~= 'red') jump Failed_1;
parsed_number = (+ red +); return GPR_NUMBER;
.Failed_1;
wn = original_wn;if (NextWordStopped() ~= 'green') jump Failed_2;
parsed_number = (+ green +); return GPR_NUMBER;
.Failed_2;
wn = original_wn;if (NextWordStopped() ~= 'blue') jump Failed_3;
parsed_number = (+ blue +); return GPR_NUMBER;
.Failed_3;
return GPR_FAIL;
];
-).
``````

At least, changing the order of declaration of kinds of value doesn’t break it.

Note that changes to the list of colors would require tinkering with the `DCTSetParsedNumber()` routine (which is a modified copy of the generated `Kind_GPR_53()` routine) to update the dictionary words and the I7 includes for color values. Not pleasant, but I couldn’t find any kind of linkage between the color KOV and the GPR routine to get around this. (Maybe the only such linkages that exist are temporarily stored in a compiler table during I6 code generation?)

1 Like

You can use a local variable rather than declaring `dct_wn_tmp` global there. Or just `@push`/`@pull` it.

Otherwise, good catch. I tried to find the “understand” implementation in the code at first but got lost in the maze, so didn’t quite work out what it was doing wrong. Now I see what you meant by checking the condition before setting the variable, though. That’s unfortunate.

Thanks, @mirality. The first version did use @push/@pull, but since I haven’t read the details of those operations yet (and I’ve learned to take nothing for granted via comparison to other languages), I went the “safe” route for the above in case there could be undesirable side effects. A local variable would save a few bytes and is better practice.

I realized while writing this up that there is a certain sense to the way that the compiler works now: The design seems to be that the condition after `when` is used as a “gate” to decide whether the `Understand` line should apply or not. That’s fine unless the condition depends on the not-yet-parsed word, as in this case. I’m not sure that this kind usage is anticipated, but, like you, the way I read the documentation certainly made it seem that the `Understand ... when ...` construction would be appropriate to this kind of use.

I hope the workaround is useful to you, @Eleas, or to others who happen across this thread.

1 Like