0 votes
by (860 points)

I'm getting some really bizarre behavior from temporary variables used inside hooks. It seems like hooks attached to macros (and only when attached to macros) treat temporary variables set outside the hook as if they were never set.

Works fine:

(set: _test to "Foo")
_test

Also works fine:

(set: _test to "Foo")
[_test]

Displays the "there isn't a temp variable named _test in this place" error:

(set: _test to "Foo")
(link: "Test")[_test]

I get that temporary variables set inside a hook only exist in the hook. (Similar to local variables in a function in javascript, yeah?) But the variable was set in the main part of the passage and it works fine when the hook isn't attached to a macro. So unless I'm missing something this just makes no sense.

Bug maybe?

1 Answer

+1 vote
by (159k points)
selected by
 
Best answer

There are two possible behaviours that could be causes the error you are seeing.

1. Variables (both Story and Temporary) that are references in hooks that are associated with interactive macros are not evaluated until after the interaction has occurred (eg. until after the link is clicked), and that can effect both: the current value the variable at the time of the interaction; and the existence of the variable.

2. Hooks that are associated with some macros are given their own copy of the current Temporary variables to use, which can cause issues with the variable's current value (and possibly existence). This can be seen when using the (for:) macro like so..

(set: $list to (a: "one", "two", "three", "four", "five"))\
(set: _counter to 0)\

List:
(for: each _item, ...$list)[{
	(set: _counter to it + 1)\
	_counter: _item<br>
}]

Counter: _counter

 

by (860 points)

Well, the error happens literally any time a temporary variable set in the main part of the passage is used inside any hook associated with an interactive macro. So those hooks must not be receiving a copy of the temporary variables at all. (Works fine with macros like (if:) by the way.)

After messing around a bit, I found out the error also happens with hooks hidden with the |x)[] syntax:

(set: _test to "Foo")
|a)[_test]
(link: "Test")[(show: ?a)]

It's almost like the temporary variables are cleared at the end of the passage instead of when leaving the passage. If so, since "code" in hidden hooks isn't evaluated until the hook is shown, no temporary variable set in the main part of the passage will exist.

by (159k points)

... instead of when leaving the passage.

There isn't a "leaving the passage" event as such, only a "show this Passage instead of the current one" activity.

After a very brief look at the Harlowe source code, as I understand things variables are stored in one of two places:

1. Story variables are stored within the current Moment of the (Story) State system, which is why they are available to activities that occur after the current passage has been shown.

2. Temporary variables are stored in the Section that they were defined in and a Section is used to represent the Passage about to be shown, or in some special cases one of that passage's sub-components which results in the "Passage" Section containing child Sections.

The (parent) Section seems to only exist during the process that first converts (compiles) the contents of the Passage into the equivalent HTML elements / CSS styling / JavaScript code, and then adds all that to the current HTML page that is about to be rendered.

This would explain why the Temporary variables aren't available after the above process has finished.

by (860 points)
edited by
Makes sense. Shame, since it makes temporary variables kind of useless. There are very few actual use-cases for them, mostly involving making sections of macros in the main part of the passage a bit more readable compared to just using convoluted nested macros.

Otherwise, my solution has been to just use global variables for everything.
by (159k points)

... just use global variables

In case you're not aware, Story variables and global variables aren't the same thing.

Temporary variables only purpose is to allow the storing of temporary values during the processing of content like that of the current Passage or of post rendering activities like the hooks of (live:) macros, if those temporary values persisted outside the context they were created in then they aren't temporary are they? *smile*

...