Is there a repo of i6-in-i7 stubs? If not, is this a good place?

I’m not a huge I6 user, but I’ve picked up neat stubs from others along the way.

This morning I discovered the following trivial code, which is most certainly old hat for I6 programmers but neat for (new) I7 programmers. (Yes, I probably should’ve experimented to try/find it earlier.)

The I6flip routine (yes, there are probably better names) works, but stateflip doesn’t as it works with a local variable. And the boolval subroutine is useful for adding truth states.

to i6flip (ts - a truth state):
	(- {ts} = ~{ts}; -)

to stateflip (ts - a truth state):
	now ts is whether or not ts is false; [this line works if it is not part of a subroutine]

to decide what number is boolval of (t - a truth state):
	(- {t} -) [works because, I think, booleans are defined as integers in i6]

Test code:

when play begins:
	let x be false;
	say "[x].";
	stateflip x;
	say "[x].";
	i6flip x;
	say "[x].";

If this isn’t the right place, would this be worth, say, making a gist on github?

Note that the first snippet has the potential to cause I6 errors if you use it wrong.

For example, “whether or not the player is a person” is a valid truth state expression. (It’s true in most games, obviously.) So the I7 compiler will accept this:

i6flip whether or not the player is a person;

But the generated I6 code is nonsense and gives you a “translating the source” failure.

1 Like

Do you know whether it is intended behaviour that temporary variables can’t be changed by subroutines? It looks a little surprising to me.

Yes, it’s intended. I7 routines are always call-by-value so they cannot modify their arguments.

(This is true of I6 as well. If x is a variable, you can’t write a function flip(x) which modifies x. You’d have to say x = reverse(x) or something like that.)

When you define an I6 phrase for I7, it’s more like a macro, so it can modify the argument. This is something of a side effect of the way the compiler works. I don’t think the Standard Rules ever do it; there’s always a risk of opaque errors.

1 Like

The canonical I7 way to do this sort of thing is to write

let x be not x;

This works with any kind of truth state, including using immutable expressions on the right hand side.

As zarf said, the only reason your original version works is because I6 code is inlined into the generated routine, while I7 code is called as a subroutine. But you really shouldn’t rely on this and you should avoid doing things like your original code.

1 Like
let x be not x;

This doesn’t work as written because there’s no “not” function defined. The shortest way to do it in pure I7 is:

let x be whether or not x is false;

You could define a function to shorten that, of course.

I wouldn’t go that far. When you put in I6 inclusions, you’ve committed to being a bit hacky. This may be the right solution for your particular problem – as long as you know what you’re doing and what to watch out for.

Sticking to pure I7 will always be safer. That’s generally preferable, but I’d never say that it’s required. (Mostly because I go leaping into I6 whenever the heck I feel like it…)

1 Like

Speaking of I6 problems to watch out for – I just noticed a problem in the original i6flip definition:

to i6flip (ts - a truth state):
	(- {ts} = ~{ts}; -)

The single tilde operator is bitwise negation. You want to use the logical negation operator, ~~. Otherwise you’ll get bad results:

Instead of jumping:
	let x be true;
	say "X is initially [x].";
	i6flip x;
	say "X is now [x].";


X is initially true.
X is now true.

Changing ~ to ~~ fixes this.


Hmm, you’re right – I was mixing it up with the is not syntax.

Interestingly, an attempt to define a concise not function doesn’t really end up any shorter, due to I7’s special treatment of the truth state kind vs any other kind (you have to use decide if instead of decide which truth state, with similar constraints on how it can be called):

To decide if not (B - truth state):
	decide on whether or not B is false.

When play begins:
	let x be true;
	let x be whether or not not x;
	if not x, say "x is untrue; ";
	say "x is [x]".

I7 is a little inconsistent in this regard, requiring whether or not for assignment but not inside if.

All in all, it’s probably less long-winded and confusing to use whether or not x is false directly.