ink icon indicating copy to clipboard operation
ink copied to clipboard

DivertTarget errors

Open inquisitivecrystal opened this issue 8 years ago • 8 comments

A few places in my code, I use diverts as variables, like ~ save = -> start_trench. It would be helpful if they would convert to a bool (true, as they have a value) when needed rather than giving errors such as Cannot perform operation '!' on DivertTarget and Shouldn't use a divert target (to start_trench) as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows). This would make them consistent with basic types, like strings or numbers. Admittedly I can see how this might sometimes be a user error, but if that's a problem some way of marking it as intentional would be more helpful.

inquisitivecrystal avatar Mar 26 '17 06:03 inquisitivecrystal

Just to make sure we're on the same page, there's a difference between:

~ temp x = -> start_trench
-> x

...and without the arrow:

~ temp x = start_trench
{x}  // print read count of start_trench
{x:You have read x at least once}  // test read count of start_trench (in this case, treat as bool)

BUT what you're talking about is perhaps "does this variable have a divert target value at all"? i.e. a bit like testing the existence of a pointer in C++?

The odd thing is that there's no such thing as "null" in ink, but you can optionally set a variable to zero. In the past we've also created something like:

== none ==
-> DONE

...and then initialised divert targets to -> none.

But potentially you're right, we could make !divertTarget return 1 (true) if it has a value that isn't zero...

joethephish avatar Mar 27 '17 08:03 joethephish

Yeah, I understand the difference between counts and divert targets. Your ->none idea is interesting, and will probably work in the short run, but it feels a bit... clumsy. Basically what I'm asking for is for divert targets to play nicely with other types. Trying to use them as conditions ({-> start_trench: true}) gives an error, and comparing them with other values (-> start_trench == var_which_equals_false) produces a rather unfriendly compiler error. It feels like they should behave just like a string, where {"a": true} appears to display properly.

inquisitivecrystal avatar Mar 29 '17 05:03 inquisitivecrystal

So, I would ordinarily agree, it should be possible to treat them as booleans, the only reason I can think not to is to prevent accidentally using them with the ->, but intending to check "have you visited this knot", which is the main use case for using a knot name as a boolean.

This decision should probably be left to @joningold, being our primary writer and user of ink!

joethephish avatar Mar 31 '17 09:03 joethephish

So, I'm definitely wary of the number of different ways a divertTarget boolean could be intended. As Joe said we use "-> none" as a hand-rolled null value.

That said, I did just see that:

~ temp x = -> knot

{ x: yup }

=== knot blah -> END

produces the error

"Line 4: Shouldn't use a divert target (to knot) as a conditional value. Did you intend a function call 'likeThis()' or a read count check 'likeThis'? (no arrows) <#>"

...the second part of which isn't true (you can't test x to mean read count at all) and the first part is something I hadn't actually considered: a divertTarget can actually be a function. Does that mean we can do callbacks and stuff?!?

Note this also produces a strange edge case: you normally couldn't do "knot()" in the above, because knot isn't marked as a function, but you can do x().That's a weird one, because marking knots as functions intended as a kind of type-checking at compile time, but in this case it would have to be a runtime error. Still, it's probably necessary, to stop the knot diverting away and doing strange stuff. I'll raise a new issue on that as I have a crash case.

My inclination is:

  • I still think divert targets shouldn't be used as booleans directly: they should be treated with a level of caution, as they're pointers not absolute references and the user shouldn't allowed to forget that.
  • a test for READ_COUNT(divertVariable) would be useful. I imagine READ_COUNT(normalKnot) would probably work too, but whatevs.
  • we should probably run time error for knotNotFunctionVariable() as above
  • I should document that divert targets can store functions, as that's not obvious if you don't know the structure underneath

cheers jon

On Fri, Mar 31, 2017 at 10:40 AM Joseph Humfrey [email protected] wrote:

So, I would ordinarily agree, it should be possible to treat them as booleans, the only reason I can think not to is to prevent accidentally using them with the ->, but intending to check "have you visited this knot", which is the main use case for using a knot name as a boolean.

This decision should probably be left to @joningold https://github.com/joningold, being our primary writer and user of ink!

— You are receiving this because you were mentioned.

Reply to this email directly, view it on GitHub https://github.com/inkle/ink/issues/293#issuecomment-290667504, or mute the thread https://github.com/notifications/unsubscribe-auth/AA40o3BYeNT-XIhxwQYR5WJanNZ5L1lOks5rrMoDgaJpZM4MpVn5 .

joningold avatar Mar 31 '17 09:03 joningold

I see your points. If you're opposed to implicit conversion into booleans (and I see where you're coming from on that), may I suggest some form of explicit conversion or casting system?

inquisitivecrystal avatar Apr 04 '17 06:04 inquisitivecrystal

If an external function returns either a divert or something null-ish/void, how can I check a divert has been returned? I can't compare it to false/null, I can't check !divertVariable either. There may be no null in ink but there's void.

floriancargoet avatar Nov 13 '22 22:11 floriancargoet

A null divert type would be useful: in the interim, try defining a knot called 'no_knot' with no content of note, and use that as a null value: you can do "target != -> no_knot"

Message ID: @.***>

joningold avatar Nov 14 '22 07:11 joningold

Thanks. I retrieve the no_knot from outside (JavaScript) and I return it instead of returning null or nothing, it works well.

floriancargoet avatar Nov 14 '22 07:11 floriancargoet