Explanation of foo.(bar) syntax in Adv3Lite?

foo.(bar) is a frequently used construct in the Adv3Lite system libraries (not in Adv3 as far as I can see). For example, in a thread a year ago, Prof Eve cited this code:

The “bar” in this construct always appears to be related to object properties. Is this a macro for a passed anonymous function/method? It’s not a standard method call since it’s “foo.(bar)” not “foo(bar)” – note the full stop between “foo” and “(bar)”.

Can anyone point to more documentation about this? I can’t spot any explanation in the Library Manual, Library Reference, Tutorial, or Learning book. Or simply a brief definition if there is one? (Not that I’m expecting such; the line of code above is brief but hardly simple.)

Many thanks indeed for any help!

While I’m far from a TADS expert, I believe foo.(bar) means “run the calculation bar, then access the property of foo corresponding to the result”. In other words, (role.objProp) is finding the property that the library wants to access, and cmd.action.(role.objProp) is accessing that property.

In other words, it’s just the standard foo.bar object-property-access syntax, but using parentheses for grouping.

Not as thorough as Eric's answer

In this example bar is a property reference, and does not hold a property value.

bar can refer to a method or property or some other thing on foo (such a thing will be called baz for now).

You can assign a reference to baz to foo.bar. Then, you pull a value from it with foo.(bar). If a method got assigned to foo.bar, then the method is called when you pull a value from foo.bar.

Here’s the fun part:

Let’s say baz = 5. You assign foo.bar to be a reference to baz. foo.(bar) returns 5. Now, add 1 to baz. Do not assign anything to foo.bar. baz is now 6. Now, we pull a value from foo.(bar). We get 6 from that, too, despite never updating it. This is because foo.bar is a reference to baz. Every time you pull a value from foo.bar, it basically says “Sorry, you need to go to baz for that, instead”.

EDIT: Ah, I see Eric Eve is writing a reply. Please defer to his answer first.

EDIT 2: Collapsed my answer lol

1 Like

This is just standard TADS3 syntax, which you can read about in the System Manual. I’m pretty sure adv3 uses too,

Suppose obj is an object and prop is an property pointer prop = &foo, then the statement obj.(prop)has the same effect asobj.foo, the parentheses round prop tell TADS to use the property (here 'foo) that prop point to.

This may be clearer with an example. Suppose on the TAction class at some point we execute the statement:

   curDobj.(checkProp)

Now suppose we have a particular instance of the TAction class, say Take, on which we’ve defined:

Take: TAction
    ...
   checkProp = &checkDobjTake   
;

Then the library can use a statement like:

   action.curDobj,(action.checkProp);

When it wants to call the appropriate check method on the action’s current direct object (which we’ll suppose has been stored in the current action’s curDobj property.

Now, if action is currently Take and its current direct object action.curDobj is bar then:

   action.curDobj.(action.checkProp);

Becomes

bar.(&checkDobjTake);

Which in turn results in the execution of:

 bar.checkDobjTake

Which, roughly speaking, is how adv3Lite (and, I think adv3) calls the appropriate methods during command execution. The foo.(bart) syntax occurs in other situations too, but this example illustrates its use.

3 Likes

Many thanks for the prompt and clear explanations!

I see also now the discussion of “propertySpec” in the Expressions and Operators section of the System Manual.

2 Likes