Would it be possible to override Context.trap so that variables can be accessed with the -> operator?
It seems that in almost all cases, developers are going to use variable names that are legitimate Fantom identifiers. To me, it seems easier to type cx->counter than cx["counter"]. Few characters, one less shift, and I don't have to worry about accidentally typing cx['counter'] by mistake (which I do all the time in Fantom, coming from Javascript/PHP/Python).
Sometimes I wonder if that should be the default behavior for Map (or if we should have some class that lets you use a map like a Python/JavaScript associative array)
brianWed 2 Dec 2009
Actually what about this idea:
Rename Context to something more general purpose
Remove Context.actor to make it a stand alone piece of functionality
Finish up trap support to handle funcs (Python/JavaScript style)
Then we'd have nice associative array class which could be used with -> operator:
I think "Dynamic" might be a good name for such class (this name comes from HaXe, where there is a "Dynamic" class that does exactly that).
tcolarWed 2 Dec 2009
+1 like the idea. Name: DynArray ?
tacticsWed 2 Dec 2009
Maybe Dyn or DynObj instead of Dynamic. The word "dynamic" has a lot of baggage that comes with it, and if we shorten it, that baggage won't hold on so tightly.
Or maybe a totally different word. What about Store? It makes sense in the Actor case, because you "store" your state there. Maybe Stash.
OK, ok, I know that is a closure return type definition, but boy does it look confusing. Maybe that syntax shouldn't be doing double duty?
qualidafialThu 3 Dec 2009
There's also Expando from JavaScript if I remember correctly.
brianThu 3 Dec 2009
I was thinking more along the lines of a "collections" sort of class, since it will do double duty. Consider the proposed new Actor API:
new make(ActorPool, |Obj?, Dyn->Obj?|)
Things like Dyn or Dynamic don't seem to work that well. BTW, we should use this class for web::WebReq.stash too.
Some ideas: Bag, AList, AArray, Array?, Assoc, Rec
Seems like we should be able to find some word that implies general purpose Str to Obj? map.
DanielFathThu 3 Dec 2009
How about Dictionary or Dict? Con it sounds like Python and but its meaning is about right - a string tied to context.
PS when are you gonna add Set?
PPS. Is it just me or should Dyn->Obj? be a child of Map?
freddy33Thu 3 Dec 2009
I used AttributeBag or AttrBag in some App. For me, Dictionary kind of imply Str:Str maps.
brianThu 3 Dec 2009
Actually I really dig Dict (and from a Java 1.0 perspective it was the original Map superclass).
PS when are you gonna add Set?
I guess I've never really felt a strong desire for it b/w List and Map. So I don't think it is a core sys thing. But now that we have a util pod we could start putting collection helper classes in there.
PPS. Is it just me or should Dyn->Obj? be a child of Map?
I agree from a pure OO model, but I think delegation is the right model here since Map is such a special thing in Fantom. Subclassing List or Map would be a can of worms.
So let's make it Dict - a general purpose Str:Obj? map that overrides trap so that items can be accessed with -> operator.
brianThu 3 Dec 2009
Promoted to ticket #848 and assigned to brian
brianThu 3 Dec 2009
Renamed from Context.trap to sys::Dict
DanielFathThu 3 Dec 2009
I guess I've never really felt a strong desire for it b/w List and Map. So I don't think it is a core sys thing. But now that we have a util pod we could start putting collection helper classes in there.
Yeah but I really think {2.0, "String", 2} or {{2.0, "String", 2}} would be an awesome way to make sets and I'm unsure whether you can do this from a non-sys library.
I used AttributeBag or AttrBag in some App. For me, Dictionary kind of imply Str:Str maps.
First there is a reference to Python's dict (which unfortunately is Fantom Map equivalent) and secondly dictionary are more often Str:Str[] since words often have more than one meaning.
andyThu 3 Dec 2009
I've seen Dict used in this context before, so its probably ok. Though seems like it might be simpler to just make that the trap behavior on Map. What are the negatives to that approach?
tacticsThu 3 Dec 2009
Though seems like it might be simpler to just make that the trap behavior on Map.
I'm leaning towards this. It's neat, but it doesn't seem distinct enough from Map.
It reminds me of an issue I always have in PHP when I haven't used JSON in a while. I will always try:
It's frustrating, because the two syntaxes mean essentially the same darned thing. Forcing me to use one syntax over another is just splitting hairs.
andyThu 3 Dec 2009
It's frustrating, because the two syntaxes mean essentially the same darned thing. Forcing me to use one syntax over another is just splitting hairs.
I agree, and related, requiring a valid identifier to be used for Dict would get annoying real quick. I use . and - heavily right now in those contexts. It wouldn't be the end of the world if I had to use camel case or something, but if Map supported -> access, it would be a non-issue.
brianThu 3 Dec 2009
It wouldn't be the end of the world if I had to use camel case or something, but if Map supported -> access, it would be a non-issue.
I think the notion of requiring Dict to have it keys as valid identifiers is something to debate. Making them identifiers has potentially lots of nice future proofing for the things you can do that data and provides a nice guarantee of what the contract really means. The only negative is really you have to use camel case instead of dots, dashes, etc.
It's frustrating, because the two syntaxes mean essentially the same darned thing. Forcing me to use one syntax over another is just splitting hairs.
The [] syntax would be available to both Map and Dict. It is just a question of the -> syntax being different.
I've seen Dict used in this context before, so its probably ok. Though seems like it might be simpler to just make that the trap behavior on Map. What are the negatives to that approach?
The huge downside is that you can't use -> on any Map method, so simple things like this would no longer work:
map := runSomeTest
verify(map->isEmpty)
But wrapping the map in a Dict we can maintain the two namespaces (Map's slots vs data slots). Ideally you'd want to reserve one identifier to dynamically get the Dict's map (like Python does with double underbars), but maybe you just have to cast to Dict first.
DanielFathThu 3 Dec 2009
Nvm. Brian just posted an explanation.
andyThu 3 Dec 2009
I think my problem here is we are basically creating two Map constructs (which is a mistake IMO) - where the problem we're trying to solve is creating anonymous/dynamic types. Yeah, thats basically the same thing, but going down the path of Dict seems the wrong direction. I think we need to stew on this a bit more before we commit any changes.
brianThu 3 Dec 2009
Just to put things back into perspective - we already have an existing Context class, we are merely renaming it and making it more general purpose.
If the debate is about getting rid of Context all together and just using Str:Obj? then that is another matter.
qualidafialThu 3 Dec 2009
The huge downside is that you can't use -> on any Map method, so simple things like this would no longer work:
Wouldn't this also hose map deserialization?
tompalmerThu 3 Dec 2009
OK, ok, I know that is a closure return type definition, but boy does it look confusing. Maybe that syntax shouldn't be doing double duty?
I agree that the overloaded meaning of -> can be confusing.
This is a good discussion. There are obviously lots of sticky issues regarding the distiction between Dict and Str:Obj?.
I don't think we really need to solve the dynamic object thing immediately. However we have many cases where the notion of a Str:Obj? comes up and we should provide a consistent solution. Today I am aware of:
The Context class largely exists as only a wrapper for Str:Obj?. WebSession is larger a wrapper, but does provide some extra functionality. But in most other cases we just use a raw Str:Obj? map. I am not sure what a good rule of thumb should be.
Couple options I see:
Use raw Str:Obj? whenever possible, and avoid wrappers. In this option I would say Context should go away.
Use wrapper like Dict consistently. This would replace Context, and probably become a super class for WebSession. This option would require some special support for Fantom and JSON serialization. But that gets into tricky issues. Does JSON require Dict, or allow both Dict and Str:Obj??
Votes between those two options? Other ideas?
DanielFathSat 5 Dec 2009
I don't see a reason to introduce a wrapper for Str:Obj? so
+1 to first.
andySat 5 Dec 2009
I'm not fond of creating a new map construct, so I think we need to solve this with the existing Map type. If wrappers can be avoided, thats great.
Though WebSession looks fine as is. It has conveniences for get and set, but the map is still a proper Str:Obj? field, and the other fields seem required. This is the right design IMO.
Context, however, seems like that can be turned into a straight Str:Obj? map (and free up that useful term). The Context.actor field seems better served as Actor.current anyways.
lbertrandSun 6 Dec 2009
+1 for using basic Map if nothing added by the wrapper
jodastephenSun 6 Dec 2009
I don't believe that standard Map objects should use -> to access their values. But I do believe that -> access is useful in certain circumstances.
As such, I support the Dict class as an alternate Str:Obj?. (There are times when extra classes enhance APIs, and this is one of those times)
freddy33Mon 7 Dec 2009
I wanted to try something (but lack of time lately), can Dict be a mixin? I have the same issue trying to create a Matrix as a mixin of a List of ( Int, Float, Complex, ... )
DanielFathMon 7 Dec 2009
Freddy33 I've been making the same thing. My best bet is to make Matrix a wrapper for List, have a constructor that takes type and dimensions, and check using reflection whether or not the type fits or not (If it is Num then it is OK, otherwise check whether it has plus, negate, mult and div).
brianMon 7 Dec 2009
Let's wrap up this up by saying convention is to not wrap Str:Obj? unless the class provides real value (such as WebSession).
So that means we want to remove the sys::Context class.
But what to do with Actor API? There are two options:
tactics Wed 2 Dec 2009
Would it be possible to override
Context.trap
so that variables can be accessed with the->
operator?It seems that in almost all cases, developers are going to use variable names that are legitimate Fantom identifiers. To me, it seems easier to type
cx->counter
thancx["counter"]
. Few characters, one less shift, and I don't have to worry about accidentally typing cx['counter'] by mistake (which I do all the time in Fantom, coming from Javascript/PHP/Python).So something like
Could be typed up as
And there'd be just a little less noise.
brian Wed 2 Dec 2009
I dig it - done!
Sometimes I wonder if that should be the default behavior for Map (or if we should have some class that lets you use a map like a Python/JavaScript associative array)
brian Wed 2 Dec 2009
Actually what about this idea:
Then we'd have nice associative array class which could be used with
->
operator:What do you guys think of that?
What would be a good name for such a class?
MoOm Wed 2 Dec 2009
I think "Dynamic" might be a good name for such class (this name comes from HaXe, where there is a "Dynamic" class that does exactly that).
tcolar Wed 2 Dec 2009
+1 like the idea. Name: DynArray ?
tactics Wed 2 Dec 2009
Maybe
Dyn
orDynObj
instead ofDynamic
. The word "dynamic" has a lot of baggage that comes with it, and if we shorten it, that baggage won't hold on so tightly.Or maybe a totally different word. What about
Store
? It makes sense in theActor
case, because you "store" your state there. MaybeStash
.Where would you use it other than with
Actor
s?jodastephen Wed 2 Dec 2009
So why are you calling the Str method on self?
OK, ok, I know that is a closure return type definition, but boy does it look confusing. Maybe that syntax shouldn't be doing double duty?
qualidafial Thu 3 Dec 2009
There's also
Expando
from JavaScript if I remember correctly.brian Thu 3 Dec 2009
I was thinking more along the lines of a "collections" sort of class, since it will do double duty. Consider the proposed new Actor API:
Things like Dyn or Dynamic don't seem to work that well. BTW, we should use this class for
web::WebReq.stash
too.Some ideas: Bag, AList, AArray, Array?, Assoc, Rec
Seems like we should be able to find some word that implies general purpose Str to Obj? map.
DanielFath Thu 3 Dec 2009
How about
Dictionary
orDict
? Con it sounds like Python and but its meaning is about right - a string tied to context.PS when are you gonna add
Set
?PPS. Is it just me or should
Dyn->Obj?
be a child of Map?freddy33 Thu 3 Dec 2009
I used
AttributeBag
orAttrBag
in some App. For me,Dictionary
kind of implyStr:Str
maps.brian Thu 3 Dec 2009
Actually I really dig
Dict
(and from a Java 1.0 perspective it was the original Map superclass).I guess I've never really felt a strong desire for it b/w List and Map. So I don't think it is a core sys thing. But now that we have a
util
pod we could start putting collection helper classes in there.I agree from a pure OO model, but I think delegation is the right model here since Map is such a special thing in Fantom. Subclassing List or Map would be a can of worms.
So let's make it
Dict
- a general purpose Str:Obj? map that overridestrap
so that items can be accessed with->
operator.brian Thu 3 Dec 2009
Promoted to ticket #848 and assigned to brian
brian Thu 3 Dec 2009
Renamed from Context.trap to sys::Dict
DanielFath Thu 3 Dec 2009
Yeah but I really think
{2.0, "String", 2}
or{{2.0, "String", 2}}
would be an awesome way to make sets and I'm unsure whether you can do this from a non-sys library.First there is a reference to Python's
dict
(which unfortunately is FantomMap
equivalent) and secondly dictionary are more oftenStr:Str[]
since words often have more than one meaning.andy Thu 3 Dec 2009
I've seen Dict used in this context before, so its probably ok. Though seems like it might be simpler to just make that the trap behavior on Map. What are the negatives to that approach?
tactics Thu 3 Dec 2009
I'm leaning towards this. It's neat, but it doesn't seem distinct enough from
Map
.It reminds me of an issue I always have in PHP when I haven't used JSON in a while. I will always try:
But that's incorrect! Every time, I forget, it needs to be:
It's frustrating, because the two syntaxes mean essentially the same darned thing. Forcing me to use one syntax over another is just splitting hairs.
andy Thu 3 Dec 2009
I agree, and related, requiring a valid identifier to be used for Dict would get annoying real quick. I use
.
and-
heavily right now in those contexts. It wouldn't be the end of the world if I had to use camel case or something, but if Map supported->
access, it would be a non-issue.brian Thu 3 Dec 2009
I think the notion of requiring Dict to have it keys as valid identifiers is something to debate. Making them identifiers has potentially lots of nice future proofing for the things you can do that data and provides a nice guarantee of what the contract really means. The only negative is really you have to use camel case instead of dots, dashes, etc.
The
[]
syntax would be available to both Map and Dict. It is just a question of the->
syntax being different.The huge downside is that you can't use
->
on anyMap
method, so simple things like this would no longer work:But wrapping the map in a
Dict
we can maintain the two namespaces (Map's slots vs data slots). Ideally you'd want to reserve one identifier to dynamically get the Dict's map (like Python does with double underbars), but maybe you just have to cast to Dict first.DanielFath Thu 3 Dec 2009
Nvm. Brian just posted an explanation.
andy Thu 3 Dec 2009
I think my problem here is we are basically creating two Map constructs (which is a mistake IMO) - where the problem we're trying to solve is creating anonymous/dynamic types. Yeah, thats basically the same thing, but going down the path of
Dict
seems the wrong direction. I think we need to stew on this a bit more before we commit any changes.brian Thu 3 Dec 2009
Just to put things back into perspective - we already have an existing Context class, we are merely renaming it and making it more general purpose.
If the debate is about getting rid of Context all together and just using Str:Obj? then that is another matter.
qualidafial Thu 3 Dec 2009
Wouldn't this also hose map deserialization?
tompalmer Thu 3 Dec 2009
I agree that the overloaded meaning of
->
can be confusing.mwanji Thu 3 Dec 2009
Not sure it's really relevant, but Gilad Bracha's latest blog post is called Objects Are Not Hash Tables :)
brian Sat 5 Dec 2009
This is a good discussion. There are obviously lots of sticky issues regarding the distiction between
Dict
andStr:Obj?
.I don't think we really need to solve the dynamic object thing immediately. However we have many cases where the notion of a
Str:Obj?
comes up and we should provide a consistent solution. Today I am aware of:web::WebSession
web::WebReq.stash
The
Context
class largely exists as only a wrapper forStr:Obj?
.WebSession
is larger a wrapper, but does provide some extra functionality. But in most other cases we just use a rawStr:Obj?
map. I am not sure what a good rule of thumb should be.Couple options I see:
Str:Obj?
whenever possible, and avoid wrappers. In this option I would sayContext
should go away.Dict
consistently. This would replaceContext
, and probably become a super class forWebSession
. This option would require some special support for Fantom and JSON serialization. But that gets into tricky issues. Does JSON requireDict
, or allow bothDict
andStr:Obj?
?Votes between those two options? Other ideas?
DanielFath Sat 5 Dec 2009
I don't see a reason to introduce a wrapper for
Str:Obj?
so+1 to first.
andy Sat 5 Dec 2009
I'm not fond of creating a new map construct, so I think we need to solve this with the existing Map type. If wrappers can be avoided, thats great.
Though
WebSession
looks fine as is. It has conveniences forget
andset
, but the map is still a properStr:Obj?
field, and the other fields seem required. This is the right design IMO.Context
, however, seems like that can be turned into a straightStr:Obj?
map (and free up that useful term). TheContext.actor
field seems better served asActor.current
anyways.lbertrand Sun 6 Dec 2009
+1 for using basic Map if nothing added by the wrapper
jodastephen Sun 6 Dec 2009
I don't believe that standard
Map
objects should use->
to access their values. But I do believe that->
access is useful in certain circumstances.As such, I support the
Dict
class as an alternateStr:Obj?
. (There are times when extra classes enhance APIs, and this is one of those times)freddy33 Mon 7 Dec 2009
I wanted to try something (but lack of time lately), can
Dict
be a mixin? I have the same issue trying to create aMatrix
as a mixin of a List of (Int
,Float
,Complex
, ... )DanielFath Mon 7 Dec 2009
Freddy33 I've been making the same thing. My best bet is to make
Matrix
a wrapper forList
, have a constructor that takes type and dimensions, and check using reflection whether or not the type fits or not (If it isNum
then it is OK, otherwise check whether it hasplus
,negate
,mult
anddiv
).brian Mon 7 Dec 2009
Let's wrap up this up by saying convention is to not wrap
Str:Obj?
unless the class provides real value (such as WebSession).So that means we want to remove the sys::Context class.
But what to do with Actor API? There are two options:
Str:Obj?
mapOpinions?
lbertrand Mon 7 Dec 2009
I really don't see the added value of sys::Context above the standard map
Str:Obj?
.So I will vote for relying only on sys::Actor.locals
andy Mon 7 Dec 2009
I don't have a whole lot of experience with the Actor API - but the cx param seems like it can be cleanly modeled using
Actor.locals
. So I vote #2.qualidafial Mon 7 Dec 2009
It does seem like sys::Actor.locals and sys::Context are duplicate APIs.
I vote for #2: remove sys::Context in favor of sys::Actor.locals.
Edit: clarify my vote
brian Tue 8 Dec 2009
Renamed from sys::Dict to Remove sys::Context
brian Fri 18 Dec 2009
Ticket resolved in 1.0.48
I wasn't able to implement this change and keep the old behavior as deprecated. So it just a clean breaking change:
Replace use of
Context
withActor.locals
.Note that the version in hg tip the constructor still takes a two param func, but that will be fixed right before the build.