Symbols are constant -- their values do not change.
The type of a symbol is Symbol, which has, among other methods, a val() method that returns the value of the symbol.
Symbols are bound to the pod in which they are used.
They are two types of symbols:
Bound symbols. These are symbols that are bound to a method, class, etc. The value for such symbols must be specified at compile-time. These symbols are known as facets. Different instances of the same symbol may have different values.
Unbound symbols. These are free standing symbols that are not attached to anything. Their value is typically determined at application startup by localization or configuration files, but it is also possible to specify a default value at compile-time. All instances of the same symbol have the same value.
Unbound symbols do not need to be declared in order to be used. They are similar to string literals in languages that support them.
The value of an unbound symbol with no default is determined by the following procedure:
Search for symbol value in default localization file.
Search for symbol value in configuration override.
Search for symbol value in bundled configuration file.
If a value for the symbol cannot be found in any of the above locations, the symbol acquires the value null.
All strings and URIs support symbol interpolation:
s := "Hello, @worldSymbol"
The interpolation is performed on the value of the symbol.
tacticsMon 18 May 2009
This seems pretty clean and straightforward.
tompalmerMon 18 May 2009
Symbols are bound to the pod in which they are used.
Maybe I misunderstand, but I like Brian's recommendation which allows symbols from other pods to be used.
JohnDGMon 18 May 2009
OtherPod::@mySymbol, using OtherPod::@mySymbol, etc.
tacticsMon 18 May 2009
Are you thinking that symbols should be declared in the pod build script? Or did you have another idea in mind?
brianMon 18 May 2009
John, thanks for your feedback. You are going down the same path I was trying to go down last week - unification of facets and symbols. I like your idea of "bound" and "unbound".
But here is the problem I ran against which I think we have in your bound/unbound proposal: the notion of declaration versus usage. Let's consider the transient facet used to mark a field as not-serialized:
** Declaration of transient for fandoc and default value
Bool transient := false
The declaration is important for a bunch of reasons - most importantly because it creates a qualified symbol name @sys::transient. We can reflect the symbol and document it too.
But declaration is different than usage:
@transient Str someField
// remember that is just sugar for this:
@transient=true Str someField
In this case, the declaration @sys::transient must already exist so that my using statements can resolve it. Not only do I need @transient declared for namespace resolution, but I want to generate a compiler error if it hasn't been declared. Static type checking was a key benefit of the original proposal.
So there is definitely a difference between declaration versus usage. So I am not sure how facet usage can also be declaration - we really need two different constructs (say the difference between := and =).
tompalmerMon 18 May 2009
So there is definitely a difference between declaration versus usage. So I am not sure how facet usage can also be declaration - we really need two different constructs (say the difference between := and =).
I'm trying hard to understand, but I don't get the issue.
Side note, wouldn't you want to declare @transient like so for a default to true?
Bool transient := true
Alternatively, you could make "presence-only" facets like so:
Void? transient := null
Then, either it is there (and null) or it isn't, but slot.facets.containsKey(@transient) needs so much more typing than slot.facet(@transient). Does null evaluate to false in boolean tests, by the way? Sorry not in a convenient circumstance to try it out right now.
brianTue 19 May 2009
Side note, wouldn't you want to declare @transient like so for a default to true?
A field is considered persistent unless explicitly marked transient, so the default is false. I don't want to get hung up on boolean facets, because they are sort of a special case in that @foo is sugar for @foo=true.
The issue is that within the same pod, I need to be able to distinguish between a declaration and a usage in to do namespace binding and compile-time checking.
JohnDGTue 19 May 2009
The issue is that within the same pod, I need to be able to distinguish between a declaration and a usage in to do namespace binding and compile-time checking.
How about requiring that bound symbols be declared beforehand? e.g.:
class MyFacets {
public static Symbol @serializable
public static Symbol @transient
}
Or something of that nature. Making facets ordinary instance variables would also alleviate the namespace concerns.
brianTue 19 May 2009
Or something of that nature. Making facets ordinary instance variables would also alleviate the namespace concerns.
But really they are "fields" on pod. It is @sys::transient, not @sys::MyFacets.transient. If we go back to my original proposal, that is effectively what we are doing, declaring symbols at the pod level. Then using them as keys for facets - but clearly symbols and facets are two different things in that proposal.
tompalmerTue 19 May 2009
@foo is sugar for @foo=true.
Thanks for clarifying/reminding. That makes sense. So the discussion of "default value" means that saying slot.facet(@mySymbol) would return that default value if the facet is missing rather than null?
If so, I guess slot.facet(@mySymbol, null) could still give null no matter what. If that's what a particular person wanted. And slot.facets.containsKey(@mySymbol) would still be available for those needing an explicit answer, too, even though it seems somewhat like bad form to dig so deep, now that I (hope I) understand what is meant by the default value.
The issue is that within the same pod, I need to be able to distinguish between a declaration and a usage
The examples you've shown don't look ambiguous to me. I'm just missing something, but if everyone else gets it, I guess I'll just be the odd one out for now.
tompalmerTue 19 May 2009
And I see that is indeed what you recommended previously:
Obj? facet(Symbol sym, Obj? def := sym.val)
My bad missing that before.
brianTue 19 May 2009
Based on this conversation, I'm still thinking my original proposal is best:
symbols are identifiers added to the pod namespace
@symbol is a symbol literal use name resolution just like types
facets are keyed by a symbol
But I might let this feature bake a bit longer before diving into it.
JohnDG Mon 18 May 2009
Here's my sketch of a symbol proposal:
A symbol is anything of the form:
@foo
Symbols are constant -- their values do not change.
The type of a symbol is
Symbol
, which has, among other methods, aval()
method that returns the value of the symbol.Symbols are bound to the pod in which they are used.
They are two types of symbols:
Unbound symbols do not need to be declared in order to be used. They are similar to string literals in languages that support them.
The value of an unbound symbol with no default is determined by the following procedure:
If a value for the symbol cannot be found in any of the above locations, the symbol acquires the value
null
.All strings and URIs support symbol interpolation:
The interpolation is performed on the value of the symbol.
tactics Mon 18 May 2009
This seems pretty clean and straightforward.
tompalmer Mon 18 May 2009
Maybe I misunderstand, but I like Brian's recommendation which allows symbols from other pods to be used.
JohnDG Mon 18 May 2009
OtherPod::@mySymbol
,using OtherPod::@mySymbol
, etc.tactics Mon 18 May 2009
Are you thinking that symbols should be declared in the pod build script? Or did you have another idea in mind?
brian Mon 18 May 2009
John, thanks for your feedback. You are going down the same path I was trying to go down last week - unification of facets and symbols. I like your idea of "bound" and "unbound".
But here is the problem I ran against which I think we have in your bound/unbound proposal: the notion of declaration versus usage. Let's consider the
transient
facet used to mark a field as not-serialized:The declaration is important for a bunch of reasons - most importantly because it creates a qualified symbol name
@sys::transient
. We can reflect the symbol and document it too.But declaration is different than usage:
In this case, the declaration
@sys::transient
must already exist so that my using statements can resolve it. Not only do I need@transient
declared for namespace resolution, but I want to generate a compiler error if it hasn't been declared. Static type checking was a key benefit of the original proposal.So there is definitely a difference between declaration versus usage. So I am not sure how facet usage can also be declaration - we really need two different constructs (say the difference between
:=
and=
).tompalmer Mon 18 May 2009
I'm trying hard to understand, but I don't get the issue.
Side note, wouldn't you want to declare
@transient
like so for a default to true?Alternatively, you could make "presence-only" facets like so:
Then, either it is there (and
null
) or it isn't, butslot.facets.containsKey(@transient)
needs so much more typing thanslot.facet(@transient)
. Doesnull
evaluate tofalse
in boolean tests, by the way? Sorry not in a convenient circumstance to try it out right now.brian Tue 19 May 2009
A field is considered persistent unless explicitly marked transient, so the default is false. I don't want to get hung up on boolean facets, because they are sort of a special case in that
@foo
is sugar for@foo=true
.The issue is that within the same pod, I need to be able to distinguish between a declaration and a usage in to do namespace binding and compile-time checking.
JohnDG Tue 19 May 2009
How about requiring that bound symbols be declared beforehand? e.g.:
Or something of that nature. Making facets ordinary instance variables would also alleviate the namespace concerns.
brian Tue 19 May 2009
But really they are "fields" on pod. It is
@sys::transient
, not@sys::MyFacets.transient
. If we go back to my original proposal, that is effectively what we are doing, declaring symbols at the pod level. Then using them as keys for facets - but clearly symbols and facets are two different things in that proposal.tompalmer Tue 19 May 2009
Thanks for clarifying/reminding. That makes sense. So the discussion of "default value" means that saying
slot.facet(@mySymbol)
would return that default value if the facet is missing rather thannull
?If so, I guess
slot.facet(@mySymbol, null)
could still givenull
no matter what. If that's what a particular person wanted. Andslot.facets.containsKey(@mySymbol)
would still be available for those needing an explicit answer, too, even though it seems somewhat like bad form to dig so deep, now that I (hope I) understand what is meant by the default value.The examples you've shown don't look ambiguous to me. I'm just missing something, but if everyone else gets it, I guess I'll just be the odd one out for now.
tompalmer Tue 19 May 2009
And I see that is indeed what you recommended previously:
My bad missing that before.
brian Tue 19 May 2009
Based on this conversation, I'm still thinking my original proposal is best:
But I might let this feature bake a bit longer before diving into it.