I’ve asked a lot of TADS3-related questions here over the past several months, but there are even more questions that I almost asked, but worked out the answer for myself in the process of asking the question.
This is probably because I’m in the habit of trying to reproduce the problem in a little self-contained minimalistic-but-compilable example. And often in writing out a version of the problem code without anything else, either it turns out that the problem wasn’t in the bit I thought it was, or just framing the sample code to illustrate what simple things the problem isn’t, what the problem is suddenly becomes apparent.
Anyway, I know that I personally search the forums for old posts whenever I have a problem, so I was wondering if it makes sense to post topics that are “just” solutions, rather than are questions that need to be answered.
Like for example, I recently was briefly flummoxed by the semantics of invoking a callback via a property on an object. Specifically, if obj._callback
is a function assigned to a property on the object, then (_callback)()
and (self._callback)()
produce different results (when used in methods on obj
). So:
#charset "us-ascii"
#include <adv3.h>
#include <en_us.h>
class CallbackThing: object
_callback = nil
construct(fn) { _callback = fn; }
foo() { return((_callback())); }
bar() { local v = _callback; return(v()); }
baz() { return((self._callback)()); }
;
DefineIAction(Foozle)
_callbackThing = nil
_getCallbackThing() {
if(_callbackThing == nil)
_callbackThing = new CallbackThing(function() {
return('[foozle]');
});
return(_callbackThing);
}
execAction() {
local obj;
obj = _getCallbackThing();
"Foo is <q><<toString(obj.foo())>></q><.p> ";
"Bar is <q><<toString(obj.bar())>></q><.p> ";
"Baz is <q><<toString(obj.baz())>></q><.p> ";
}
;
VerbRule(Foozle) 'foozle' : FoozleAction verbPhrase = 'foozle/foozling';
startRoom: Room 'Void'
"This is a featureless void. "
;
me: Person
location = startRoom
;
versionInfo: GameID
name = 'sample'
byline = 'nobody'
authorEmail = 'nobody <foo@bar.com>'
desc = '[This space intentionally left blank]'
version = '1.0'
IFID = '12345'
;
gameMain: GameMainDef
initialPlayerChar = me
;
…produces:
Foo is "function#91267 "
Bar is "[foozle]"
Baz is "[foozle]"
In this case an anonymous function is assigned to (an instance’s) CallbackThing._callback
. This produces different results if it is called (via methods on CallbackThing
) as (_callback())
versus (self.callback)()
(or fn = _callback; fn()
). Which is not what I would have expected.
Not a big deal or anything, but I spent more time on working out the problem then I would’ve had to if searching for “TADS callback” produced any meaningful results.
That’s one specific example, but I think I’ve almost asked many questions, only to hit “cancel” instead of “Create Topic” at the last moment because I’d just discovered the solution. And it recently struck me that if I encountered the same problem again in a couple months, there’s a fair chance that I’d have forgotten the solution (because it’s somewhat counterintuitive, and I’m not constantly writing code that involves the problematic syntax), and since I never asked the question there’d be no record of either the problem or the solution.