Options for meta-object access
tactics
24 Jul 2009
I can see where a pod literal syntax might be nice, but the alternative syntaxes you provide don't seem much more intuitive.
tompalmer
24 Jul 2009
I also prefer the current syntax (A) over the other options given here, although I can see the idea of consistency in option C. And I also agree that pod literal syntax might be handy at times.
And I still think accessing a slot tied to an object might be nice, but I also still think that the whole data binding concept ought to be considered with it. I just haven't thought much about that myself so far.
brian
24 Jul 2009
I don't think we necessarily have everything ironed out, but I'm a bit exhausted by all the symbol/repo work from this month to give it much thought. I need to take a break and revisit it a few weeks.
I am definitely coming around to using # instead of .type to free up type as a valid slot identifier.
Also it sure would be nice to have qualified name syntax match literal syntax (but that ship may have sailed).
tompalmer
24 Jul 2009
If there were a change to allow #object (or object#) on local vars, say, I would recommend it mean a "pointer" to the object, as in, some kind of Field object to let you read and write the object. I don't think such a thing should give the type of the object.
So, for example:
class Refs {
Void main() {
num := 1
numRef := #num
numRef.set(null, 2)
echo(num) // Prints 2
}
}
That seems the most consistent meaning of # if it were to be supported on arbitrary vars.
tompalmer
28 Jul 2009
I've got a story about syntax and symbols and objects/types/pods and literals. It's the not exactly the Fan looks today, and it almost certainly isn't the way it ought to be. Just trying a fresh perspective to see if it sheds light on things.
Symbols aren't slots in pods the way types have slots, though I think it's possible that pods could be const singleton instances of the Pod class or some subtype of Pod. In any case, since pod namespace access today looks like pod::Type or @pod::symbol, is there a reason why pod object access couldn't simply be pod (rather than pod::#)?
But that would make them an odd duck compared to needing special chars (such as # or @) to get at other top-level items.
So, pods are odd in this sense. Maybe could say pod.Type and pretend they really are members, though I've tended to like the pod::Type syntax, and I understand it makes some handling easier.
Now, I want to pretend for a moment that symbols are simply namespaced globals (whether accessed by . or ::) or rather that "global" (under pod namespaces) consts exist in Fan:
** Totally global. Implied const or explicit?
const Float pi = 3.14f
** A class in the same file.
class PiGreeter {
Void main() {
echo(pi) // or could be 'myPod::pi' (or 'myPod.pi')
}
}
Well, then global (or even class member?) field (or even method?) objects could be the typed, namespaced symbols for facets or otherwise:
** Totally for facets.
const Str author = ""
** Using the pod-level field for a facet, using facet syntax.
@author="Me"
class MyClass {
Void main() {
// But when I access it, I just use a field literal.
echo(type.facet(author#))
}
}
Here I'm using Stephen's postfix syntax. If want the value of author, I reference it like I would use it like a var (that is, author), but if I want it as a symbol, I use the literal (that is, author# or myPod.author# or whatever). And you could perhaps still have virtual pod-level fields related to overriding things for customization. I haven't thought through the best unification theory on that. (Is there such a thing as multiple pod types, and letting one pod subtype another or oddness like that?)
And, anyway, then say we really do just use trailing # for all literals: pod#, field#, SomeType.field#, somePod.SomeType.field#, SomeType.method#, somePod.someField#, and so on.
Again, some of this story doesn't depend on :: vs. ., and I know some of the pain of needing to wait until a name resolution phase to identify pods if . is used.
I'm just looking for an alternative unification theory as food for thought. I don't expect Fan to switch to this style, and it might raise more questions than it could possibly answer. So again, just a mental exercise.
brian
28 Jul 2009
Idealistically pod::Type.slot are all just variables in scope. But in practice having slots or symbols implicitly in your scope would be annoying, so I think we always want a special care to indicate reflection literal.
Ideally this will be done consistently with any qname or unqualified name in scope using a prefix operator like @ or postfix operator like #.
However we have a couple inconsistencies that I see problems with:
@Type.slotorType.slot#would be ambiguous - are you calling a static method or referencing the slot literal- symbols are an odd case right now
I haven't given this a lot of thought, but the ideal design comes around to a single operator or syntax mechanism which operates on the follows identifier strings:
pod => Pod pod::Type => Type Type => Type pod::Type.slot => Slot Type.slot => Slot slot => Slot pod::symbol => Symbol
Note that what we do today is replace . with # to make types/slots work.
tompalmer
29 Jul 2009
By the way, I've thought about how if we don't like the global look of plain symbol for symbol values (rather than the meta-object access), maybe ::symbol would work. I think that gives some intuitive feel about how we're accessing a different scope than just members/locals.
And maybe @symbol is almost a shorthand for #::symbol, and @pod::symbol is also still allowed for general @ usage. Not sure that's ideal, but it's a thought.
As for a common operator for all of it, the problem with prefix operators generally is that they need to bind tightly or you need parens to wrap the scope. Which is why @ is okay for symbols but not ideal for @pod::Type.slot. What object is reflected, Type or slot? Otherwise, I actually sort of like the @ prefix (Pascal-ish) if we don't care about distinguishing symbols from members of the enclosing type.
Oh, and I should bring back up my requested stand-alone # as a reference to the statically enclosing type.
brian
29 Jul 2009
just took a jog and was noodling on this thought:
- make symbol literals work just like type literals (except they can only be a literal):
transient# t.facet(simple#)
- unify symbol value access and field storage access via
@(moving back to old field storage syntax):@transient @localizedMessage Str field { set { @field = val } }
only issue is that you might have ambiguity b/w field access and symbols if you have conflicting names
tompalmer
29 Jul 2009
The main niceness to @symbol literals is that accessing them in code looks similar to applying them. Though I've also mentioned alternatives above, I'm not sure it's worth giving up that niceness. Something to keep in mind, at least.
tompalmer
29 Jul 2009
Maybe this would work:
// A symbol for facets or whatever. // Accessed later by '@author' or '@pod::author'. // No need for value reference. Str @author // A configuration field. // Accessed later by 'serviceUri' (or '::serviceUri'?) or 'pod::serviceUri'. // Reflected later by 'serviceUri#' (or '::serviceUri#'?) or 'pod::serviceUri#'. virtual Uri serviceUri := `https://somewhere/serviceUri`
Maybe? Current Symbol would be renamed to Config? And a new separate Symbol (or Sym?) type introduced?
And for pods, configs, types, and slots (but not the new plain symbols), maybe just use the trailing # as suggested by Stephen?
jodastephen
29 Jul 2009
Type.slot#would be ambiguous - are you calling a static method or referencing the slot literal
How would this be a static method call? I'd define it as "everything from the start of the expression to the # is the literal".
make symbol literals work just like type literals
Yep. Sounds good. This moves us closer to all programmatic elements having a consistent literal (just need to add pods).
unify symbol value access and field storage access via @ (moving back to old field storage syntax)
That could work, although it still feels a little odd.
jodastephen
29 Jul 2009
Interestingly, what I wonder is what the difference is between a symbol and a static (const final) field on a class? These have similarities in that they are both namespaced singleton values, essentially immutable (IIUC, symbols are immutable?). Whereas fields are entirely different, being mutable and accessed via properties (which can have manual getter/setter).
Taking this approach leads me to what might be described as "symbols" on both pods and types. Both could be overridden in config files, although the final keyword would prevent this.
pod foo symbol values overridden in foo.fansym class Bar symbol values overridden in Bar.fansym
I know I'd find the ability to override class level constants very useful. The extra namespacing level actually feels more appropriate for config items, and way more powerful. (And would allow for a constants class like FooConfig dedicated to config, if the developer wanted to organise code that way.)
In fact, I wonder if this leads to a separation of facets from symbols? Symbols defined in the pod file would be facets. Symbols defined in a class file would be regular symbols. (We'd probably need some new terminology, but I hope I'm explaining myself:
pod foo {
myFacet := "HelloFacet" // virtual by default?
}
class Bar {
static mySymbol := "HelloSym" // final by default?
// replaces current static const final var
}
brian
29 Jul 2009
I think the basic idea of treating static consts as symbols at either the pod or type level (or maybe just the type level) is really interesting
lots of different ideas swirling around here:
- symbols
- facets
- configuraiton/localization "constants"
- static const fields
- field storage grammar problem
- pod meta-data
- reflection syntax unification
I feel we are on the right track, but I am not seeing everything click into place yet
jodastephen
31 Jul 2009
lots of different ideas swirling around here I agree.
Lets work on the basis (for now) that configurable values (avoiding the word symbol just now) on a per field in a class basis is a goal.
Then we need to work out if we need to have separate concepts for static fields (constants) and these configurable values.
Both are static.
Both are effectively immutable. But perhaps we allow mutable configuration values (which are cloned each time they are returned?).
The meta-object for a configurable value is more complex (default value, localisation, etc).
So, are the concepts the same or different?
If different, should we have a different syntax?
tompalmer
31 Jul 2009
The meta-object for a configurable value is more complex (default value, localisation, etc).
I still think that for configuration, the overridden/localized value (if overridden/localized) is by far the most important, and that this value is more important than reflecting a meta-object. (There might still be occasions to get at default values and whatnot, but I think they'd be very rare.)
jodastephen
23 Jul 2009
Breakout from Symbols.
Fan is a language where reflection and the meta-objects are important. By this I mean the
Pod,Symbol,Type,MethodandFieldobjects.Extending my suggestion makes the # sign the key symbol for access to meta-objects.
Option A, current:
Option B, based on current with a few tweaks:
Option B1, (added) for symbols:
Option C, with the # is always at the end:
I find the current setup (A) quite confused. and I prefer option C if it can be made to work with the grammar.