Problems with "now" vs. "change" in I7 (6E72)

A warning for folks who are trying to get their older I7 stuff to compile with the “Use no deprecated features” option:

One of the deprecated features is the “change X to Y” syntax; all “change” phrases must be changed to “now X is Y”.

Unfortunately, Inform’s ability to interpret object properties in the “now” format is not equal to its ability to interpret them using “change”. Specifically, when using “now”, Inform’s ability to infer the object to which a property pertains disappears, making for more verbose code. For example, in the following code, Inform can infer which object is being referred to in the context of the “testing rules” object-based rulebook:

[code]A testing-entity is a kind of thing. A testing-entity has a number called X1.

The test-object is a testing-entity. The X1 is 12.

When play begins:
follow the testing rules for the test-object.

The testing rules are an object-based rulebook.

A testing rule for a testing-entity (called the subject):
let dx be the X1 - 6;
change the X1 to the X1 - dx;
say “X1: [X1 of the subject].”;

Test is a room.[/code]

But change the “change” in the testing rule to read

now the X1 is the X1 - dx;

and you get a compiler error, because Inform can’t do this equally well with conditions (which is how “now” parses things).

I’ve filed a bug report and hopefully we’ll see better parsing for “now” with the next release, but for the time being you may want to think twice unless you’re certain you haven’t used this kind of shortcut.

Thanks for the heads-up. I have to say, though, when I initially read your example code it immediately looked like the sort of syntax that I wouldn’t expect to work anyway due to vague construction. For example the following use of “now,” written with a bit more care, compiles and works fine (in terms of the example posted):

[code]A testing-entity is a kind of thing. A testing-entity has a number called X1.

The test-object is a testing-entity. The X1 of the test-object is 12.

When play begins:
follow the testing rules for the test-object.

The testing rules are an object-based rulebook.

A testing rule for a testing-entity (called the subject):
let dx be the X1 of the subject - 6;
now the X1 of the subject is the X1 of the subject - dx;
say “X1: [X1 of the subject].”;

Test is a room.[/code]
I’d say then that the whole matter is less a bug than an eccentricity of syntax, but that the eccentricity was actually in the original way you wrote your example (which, as I said, looked immediately odd to me). On the other hand, I believe that your main point was simply:

in which case I guess my revised example simply demonstrates your point. Perhaps I’m saying I personally wouldn’t have expected I7 to reliably make such inferences in the first place.

In general however I agree with the points you’ve made elsewhere about the phase-out of “change… to…” and think that the practical value of the “change” terminology to end-users should carry more weight than any aesthetic design considerations on the development side. I think it’s strange that “move… to…” isn’t being eliminated at this time, although the same arguments presented as reasons for eliminating “change” apply with equal relevance to “move.”

Yes, but that’s a whole lot longer, and what have you gained by the length? Trust me, in a real world example like the ones that failed in my WIP, you don’t want to have to write out the property’s object reference every time. The example isn’t very well written, though (I was intending to show how things fail only with “now”, while “let” assignments work correctly–that is, they infer from the context which object we are talking about). Realistically, I’d refer to the subject once, and then not again, e.g.:

A testing rule for a testing-entity (called the subject): let dx be the X1 of the subject - 6; now the X1 is the X1 - dx; say "X1: [X1 of the subject].";

But Inform does make them reliably, and has a pretty nicely set up internal mechanism for doing so, one that I take advantage of all the time. The stuff I’m working on isn’t “normal” IF, though–here’s a typical example:

change the win-x of the grid to win-x - (bitmap-width * dot-size) / 2

Now imagine stacks of those kinds of commands, one after another. I think unnecessary “of the ____”'s impede code readability in that situation. There is no doubt in my mind that this is a feature worth keeping (my perhaps poorly constructed example aside), but it isn’t one that the average user is ever going to be aware of.

Another problem with “now” vs. “change” (making this transition is a pretty big headache, one I keep putting off):

“Now” can’t handle assignments of the same complexity that “change” can. This, for example, compiles using “change” but not “now”:

now sprite-x is x-temp real times the scaling factor of current window real times the scaling factor of the current-sprite as an integer;

or, if we show the grouped terms:

now (sprite-x) is ( ( ( (x-temp) real times (the scaling factor of current window) ) real times ( the scaling factor of the current-sprite ) ) as an integer );

I’ve seen simpler conditions* fail too, fixable by just putting parentheses around one of the terms. That approach doesn’t work here.

I don’t want to split these into multiple phrases, but even if I do, “now” can’t handle it:

let x-calc be x-temp real times the scaling factor of current window real times the scaling factor of the current-sprite as an integer; now sprite-x is x-calc;

This produces the compiler error:

This has got to be a bug–I other set numbered properties to numbers all the time. It really seems like conditions parsing is really not ready to take over all assignments yet. This is partly due, I would guess, to problems with the recent overall of types, but also to weaknesses in parsing conditions.

Anyway, does anyone have any advice about how to get the complex condition to compile w/o splitting it into pieces? (There are undoubtedly pieces that would work, but it seems silly to clutter the code with temporary variables and extra lines that shouldn’t be necessary.)

Thanks,
Erik

  • FYI, “change” is implemented as an assignment of a value to a “storage”, whereas “now” reads the entire block as a condition and makes it true:

To change (S - storage) to (w - value)
(- {-assignment}; -).

To now (cn - now-condition)
(- {cn} -).

Just out of curiosity … would it be easier for you to hack the Standard Rules so as to restore the functionality of “change”? Or would that be impossible for some reason? Ordinarily I would avoid hacking the Standard Rules, but something this basic … or do you even have to hack that file? Could you restore the usability of the “change” syntax in your own game code?

I’m really curious about this.

–JA

I think it would be quite easy to define the necessary phrases in my own code. There are three phrases that define “change … to …”, and it ought to be straightforward enough to create a new extension that reimplements them. Effectively, that’s what I’ve decided to do, at least if “now … is …” isn’t fixed: I released the extensions without changing “change” to
“now”, so when the next version of Inform hits, they will be broken. (I just couldn’t bring myself to put in the hours to convert the deprecated syntax.)

–Erik