Technicalia
|
In some cases it may help to explicitly store a dynamic element in a (local) variable of the appropriate type, especially when it
is a dymanically embedded class/struct.
Dynamic routines would typically be implemented as integers, to which is assigned a standard routine_id(),
and would usually need to be invoked via an explicit call_func() or call_proc(),
such as call_proc(p.show,{p}) , or rather as an OO-pagan, I simply don’t get how/why you w/could have p.show()
at the same time as wanting/needing to declare show dynamically. One thing you can trivially do is declare a class method
procedure task(); (ie virtual) along with actual methods easy() and hard(), and then just p.task = p.easy or
p.task = p.hard before invoking p.task() .
It is questionable as to whether there is any actual benefit in hierarchies of, and hence extending, dynamic classes, but you can.
The compiler currently rejects abstract + dynamic, but I’m open to persuasion if you’ve got a proper use for it.
The dynamic keyword is optional when extending an already dynamic base class. You cannot disable dynamic half-way down the tree.
Technically speaking, class/struct field access is a subversion of subscripting, such that s.field is the
same as s["field"] , except that in the former you are pretty much obliged to reference pre-existing fields
whereas the latter syntax allows a fully dynamic field name to be constructed at run-time. Note the following:
constant one = "two"
class thing
string one = "one",
two = "two"
function tre()
return "tre"
end function
end class
thing s = new()
?s.one -- "one"
?s.two -- "two"
?s.tre -- 2473 (a routine_id)
?s.tre() -- "tre"
?s["one"] -- "one"
?s["two"] -- "two"
?s["tre"] -- 2473 (a routine_id)
--?s["tre"]() -- invalid syntax
?s[one] -- "two" (because of that constant!)
--?s[two] -- two undefined (even though s.two exists)
--?s[tre] -- tre undefined (even though s.tre exists)
--?s."one" -- invalid syntax
--?s[3] -- compile-time and/or run-time error
One other small point to note: while s.employee is equivalent to s["employee"], s.employee.name is
(possibly) legal whereas the square bracket syntax is strictly single-level only and s["employee"]["name"] is treated as invalid syntax,
and therefore if you are using an expression for "employee" rather than a literal string, the latter statement must be broken up into two
or more lines, with appropriate (or base) struct/class types on any temporary variables, in order to give the compiler sufficient hints.
In other words all dynamically-created fields are implicitly "object", and hence must be stored in an explicit struct/class variable
before any further dot or ["string"] field-accessing operations can be performed.
Likewise s[expr].field is never valid, but s[expr][int] might sometimes be, ie when the second and
subsequent [] are of the more traditional integer-index subscript variety.
Another way of saying this is that in C++ you can pass around (a reference to) an instance as a void* , but it must be cast
to some appropriate class before using dot notation. In a similar fashion, you can pass Phix struct/class references about as objects
(or store them in tables/sequences), but /must/ store them in local struct/class type variables or routine parameters, before you can
use dot notation.
By default the compiler assumes all "dot /and/ []" are traditional integer subscripting of sequences, unless a variable/parameter is
unambiguously a struct/class (that is, according to its declaration).
Dynamic class instances are simply implemented as independent dictionaries, with dot-notation and automatic cleanup.
Obviously you should expect fairly disappointing figures from a pointless benchmark: p["index"] is without any doubt going to be at the very
least 5 times slower than p[1], probably much worse, and even the most mediocre of programmers could apply optimisations way better than any
compiler ever could. Only use dynamic classes when you value the improved code clarity more than the 0.0001s being lost, and yes, ten thousand
dynamic class instances is probably fairly likely to take (aka waste) a whole second to set up, use, and tear down, if not more, but then again
if you only have a dozen or so of them, lightly used, then you simply just don’t care one jot about their performance.
|