Hi
I’m fixing the class definition parser and I have a question. I’m stabilizing the API of CDSlotNode 1 ‘first' => LazyClassVariable default: 5. 2 ’second' => InstanceVariableSlot. 3 ‘instVar3’ Here is a proposal slotdefinition(3) name ? variable name >>> ’instVar3' slotDefinition(2) slotClass? >>> InstanceVariableSlot slotDefinition(1) initializationMessage >>> 'default: 5’ or better >>> Node(default: 5) if it exist S. |
Hi, I really like the idea of returning a node object for the initialization. From seeing the class definition, I think we should assume that: - the receiver of the slot instantiation message is a Slot. - the parameters to the slot instatiation message are literals or literal-only expressions. Do you think that these assumptions / constraints are cool / enough? Cheers. On Sun, 8 Sep 2019, 09:41 ducasse, <[hidden email]> wrote: Hi |
Now I wondered if allowing a block would make sense. But it automatically raises the evaluation environment so I would prefer not.
|
If you need behaviour specific for your domain, you can always create a subclass of slot and redefine read: and write:, ++ you don’t need a block :D ++ it makes it super explicit you’re doing some magic
|
In reply to this post by ducasse
> On 8 Sep 2019, at 09:17, ducasse <[hidden email]> wrote: > > Hi > > I’m fixing the class definition parser and I have a question. > > I’m stabilizing the API of CDSlotNode > > > 1 ‘first' => LazyClassVariable default: 5. > 2 ’second' => InstanceVariableSlot. > 3 ‘instVar3’ > > Here is a proposal > > slotdefinition(3) name ? variable name > >>> ’instVar3' > > slotDefinition(2) slotClass? > >>> InstanceVariableSlot Right now I return a symbol instead of the class but I could return a class. Now I would like to avoid to blindly think that we have a single namespace. So returning a class implies to be sure that the definition is parsed in the same environment than the class it refers and to me this is a constraint I do not like. So I will return a symbol. Let me know what you think. > slotDefinition(1) initializationMessage > >>> 'default: 5’ > or better > >>> Node(default: 5) if it exist Now I do not know what to do: because I can create a message with an empty receiver. Because > > S. > > > |
maybe #slotClassName instead of #slotClass? I’m not against the symbol...
Two simple solutions that come to my mind 1) ‘instVar3’ generates a CDSlotNode with a default #slotClassName = #InstanceVariableSlot (I like this solution the less because it hardcodes in the parser knowledge about the runtime) 2) we have two different nodes (becase they have different syntax) CDSlotNode and CDDefaultSlotNode and DefaultSlotNode does not have a class name and should be visited differently.
|
Yes I did this.
Yes. I was wondering what would be initializationMessage part of a normal slot. And may be having these two can solve the problem. I do not like to put a nil or #() in the initializeMessage (and I was thinking that I would need a NullMessage but this is not nice. So I’m thinking that having two different nodes may be good now I do not know what to do for the initializeMessage (if it would be an action I would do nothing)
|
I’m thinking that I should subclass RBMessageNode to have RBSlotInitializationNode
Ideally I have the impression that it would be nice to have RBNoReceiverMessageNode as a subclass or RBMessageNode. This way we could also simplify the logic of cascade :) - but this is another story. Stef |
> On 8 Sep 2019, at 18:30, ducasse <[hidden email]> wrote: > > I’m thinking that I should subclass RBMessageNode to have RBSlotInitializationNode So now I’m creating RBSlotInitializationNode as a subclass of the superclass of MessageNode because it felt too much as a bad subclassing practice. > > Ideally I have the impression that it would be nice to have RBNoReceiverMessageNode as a subclass or RBMessageNode. > This way we could also simplify the logic of cascade :) - but this is another story. > > Stef > |
Hi,
I'm not too deep in the CDSlotNode and related - but I wonder why we need the specific #=> selector and slotName => Definition mapping form in the definition at all. What are the benefits of the additional "=>" style ? To me it looks not very natural to write: #id => InstanceVariable. or other specific forms. The custom subclasses of class "Slot" are already inheriting the "name" iVar for the slotName. So using the additional slotName in the definition is - disrupting the slot name from other arguments - redundant if the slot creation should have the name as well Why not use just the plain slot object by creating it directly with a class message? We can just use custom class side instantiation methods for the slots including the name like #named: #named:type: #named:type:default: ... or other. I mean #=> dispatches to #named: on the slot anyway. If we define the class / slot objects like this: Object subclass: #MyTask slots: { BOInstanceVariableSlot named: #'id'. #anotherIVar. BOTypedSlot named: #'description' type: String. BOAttributeSlot named: #'isDone' type: Boolean default: true. BOAttributeSlot named: #'created' type: Date default: [ Date today ] } classVariables: { } package: 'CustomSlots-Definitions-Examples' is more natural than the => forms where the name is just disrupted from the other arguments. The attached file out from a Pharo 8 example demonstrates this. Just file it in and have a look at class MyTask or inspect "MyTask new created" or "MyTask new created: 2" to see that the implemented simple slot typing and defaults are working. Then look at the definition of #MyTask class, which looks like written above. It could be made even more readable using Object subclass: #MyTaskEvenEasier slots: { BOAttributeSlot named: #'id'. BOAttributeSlot named: #'anotherIVar'. BOAttributeSlot named: #'description' type: String. BOAttributeSlot named: #'isDone' type: Boolean default: true. BOAttributeSlot named: #'created' type: Date default: [ Date today ] } classVariables: { } package: 'CustomSlots-Definitions-Examples' only. The benefits without the => indirection are: - a simple, compact and easy readable class definition even when slots are used - slot definitions are regular messages to the slot class - simply evaluate or inspect the full slot class side message - we keep the possibility to mix slots with other instance variables (here #anotherIVar in the example by using the symbol) - we keep the possibility to evaluate the full slots definition and check the array of their definition - we unify the definition with the "MyClass slots" message - as both are just return the array of slot objects - we do not rely on an additional specific definition API one has to remember So where is the real value in the often used additional indirection of the => message in slot definitions? Thanks T. CustomSlots-Definitions.st (13K) Download Attachment |
Good question. I will let marcus answer.
I’m just the guy that makes sure that the AST behind class definition is working. I prefer your solution because it is easier since I do not have to make AST transformation :). S. > On 8 Sep 2019, at 23:48, Torsten Bergmann <[hidden email]> wrote: > > Hi, > > I'm not too deep in the CDSlotNode and related - but I wonder why we need the specific #=> selector and > > slotName => Definition > > mapping form in the definition at all. What are the benefits of the additional "=>" style ? > > To me it looks not very natural to write: > > #id => InstanceVariable. > > or other specific forms. The custom subclasses of class "Slot" are already inheriting the "name" iVar for the slotName. > So using the additional slotName in the definition is > > - disrupting the slot name from other arguments > - redundant if the slot creation should have the name as well > > Why not use just the plain slot object by creating it directly with a class message? We can just use custom class side instantiation > methods for the slots including the name like > > #named: > #named:type: > #named:type:default: > ... > or other. I mean #=> dispatches to #named: on the slot anyway. > > If we define the class / slot objects like this: > > Object subclass: #MyTask > slots: { BOInstanceVariableSlot named: #'id'. > #anotherIVar. > BOTypedSlot named: #'description' type: String. > BOAttributeSlot named: #'isDone' type: Boolean default: true. > BOAttributeSlot named: #'created' type: Date default: [ Date today ] } > classVariables: { } > package: 'CustomSlots-Definitions-Examples' > > is more natural than the => forms where the name is just disrupted from the other arguments. > The attached file out from a Pharo 8 example demonstrates this. > > Just file it in and have a look at class MyTask or inspect "MyTask new created" or "MyTask new created: 2" to see that > the implemented simple slot typing and defaults are working. > > Then look at the definition of #MyTask class, which looks like written above. It could be made even more readable using > > Object subclass: #MyTaskEvenEasier > slots: { BOAttributeSlot named: #'id'. > BOAttributeSlot named: #'anotherIVar'. > BOAttributeSlot named: #'description' type: String. > BOAttributeSlot named: #'isDone' type: Boolean default: true. > BOAttributeSlot named: #'created' type: Date default: [ Date today ] } > classVariables: { } > package: 'CustomSlots-Definitions-Examples' > > only. > > The benefits without the => indirection are: > - a simple, compact and easy readable class definition even when slots are used > - slot definitions are regular messages to the slot class - simply evaluate or inspect the full slot class side message > - we keep the possibility to mix slots with other instance variables (here #anotherIVar in the example by using the symbol) > - we keep the possibility to evaluate the full slots definition and check the array of their definition > - we unify the definition with the "MyClass slots" message - as both are just return the array of slot objects > - we do not rely on an additional specific definition API one has to remember > > So where is the real value in the often used additional indirection of the => message in slot definitions? > > Thanks > T. > <CustomSlots-Definitions.st> |
In reply to this post by ducasse
I will have a look, but I feel that we should first get the Composed Slots into the image
as they will change everything again. > On 8 Sep 2019, at 09:17, ducasse <[hidden email]> wrote: > > Hi > > I’m fixing the class definition parser and I have a question. > > I’m stabilizing the API of CDSlotNode > > > 1 ‘first' => LazyClassVariable default: 5. > 2 ’second' => InstanceVariableSlot. > 3 ‘instVar3’ > > Here is a proposal > > slotdefinition(3) name ? variable name > >>> ’instVar3' > > slotDefinition(2) slotClass? > >>> InstanceVariableSlot > > slotDefinition(1) initializationMessage > >>> 'default: 5’ > or better > >>> Node(default: 5) if it exist > > S. > > > |
> I will have a look, but I feel that we should first get the Composed Slots into the image
> as they will change everything again. Yes - would like to see them in as quickly as possible - but I fear they need more work from your side which is time and prio related as always. ComposedSlots can make things easier and allow to better control the different variations. Compositions will change how things can be composed together. But for the definition I guess we still have to decide for either - either for the "=>" approach - the plain objects approach For compositions the => syntax would allow to just write the class name if there are no parameters for the slot: { ’someIVar' => InstanceVariableSlot + LazySlot } But using the "just objects" approach one could would make it look like: { (InstanceVariableSlot named: 'someIVar') + LazySlot new } When "+" is implemented also on instance side for composing one could even have: { (InstanceVariableSlot named: 'someIVar') + LazySlot } or { LazySlot + (InstanceVariableSlot named: 'someIVar') } to stay symmetric. It would also allow for: { ComposableSlot for: 'someIVar' using: LazySlot } "assuming that an InstanceVariableSlot is always in or { ComposableSlot for: 'someIVar' with: LazySlot new } "if one uses an existing slot instance" Anyhow - we can only experiment when https://github.com/MarcusDenker/SlotComposition moves on and becomes part of the image... Bye T. |
I would really like a solution that does not change the syntax.
Why we cannot have a slot defined before the class use. Like I defined my LazySlot class and after in the class definition I just write LazySlot named: ’someIVar’ Like that the syntax stays under control. I do not really get why the composition should be done in the class definition. We can have composedSlots at the level of slots without having to define them within the class definition. I think that composing a slot property should be more exceptional than the normal business. So why can we have a library of slots that use composition without having it mixed inside the class definition. Could we keep things simple? >> I will have a look, but I feel that we should first get the Composed Slots into the image >> as they will change everything again. > > Yes - would like to see them in as quickly as possible - but I fear they need more work from your side which > is time and prio related as always. > > ComposedSlots can make things easier and allow to better control the different variations. > > Compositions will change how things can be composed together. But for the definition I guess we still > have to decide for either > - either for the "=>" approach > - the plain objects approach > > > For compositions the => syntax would allow to just write the class name if there are no parameters for the slot: > > { ’someIVar' => InstanceVariableSlot + LazySlot } > > > But using the "just objects" approach one could would make it look like: > > { (InstanceVariableSlot named: 'someIVar') + LazySlot new } > > When "+" is implemented also on instance side for composing one could even have: > > { (InstanceVariableSlot named: 'someIVar') + LazySlot } > > or { LazySlot + (InstanceVariableSlot named: 'someIVar') } > to stay symmetric. > > It would also allow for: > > { ComposableSlot for: 'someIVar' using: LazySlot } "assuming that an InstanceVariableSlot is always in > > or > > { ComposableSlot for: 'someIVar' with: LazySlot new } "if one uses an existing slot instance" > > Anyhow - we can only experiment when https://github.com/MarcusDenker/SlotComposition moves on and > becomes part of the image... > > Bye > T. > > > > |
In reply to this post by Torsten Bergmann
> Anyhow - we can only experiment when https://github.com/MarcusDenker/SlotComposition moves on and
> becomes part of the image… No if we decide that composed traits should be defined prior to class definition. Marcus will have all the freedom to work on slot composition without breaking the tools. And we can have a simple synatx for slots and use it. Stef |
In reply to this post by Torsten Bergmann
Th¡¡
> El 8 sept 2019, a las 23:48, Torsten Bergmann <[hidden email]> escribió: > > Hi, > > I'm not too deep in the CDSlotNode and related - but I wonder why we need the specific #=> selector and > > slotName => Definition > > mapping form in the definition at all. What are the benefits of the additional "=>" style ? > > To me it looks not very natural to write: > > #id => InstanceVariable. > > or other specific forms. The custom subclasses of class "Slot" are already inheriting the "name" iVar for the slotName. > So using the additional slotName in the definition is > > - disrupting the slot name from other arguments > - redundant if the slot creation should have the name as well > > Why not use just the plain slot object by creating it directly with a class message? We can just use custom class side instantiation > methods for the slots including the name like > > #named: > #named:type: > #named:type:default: > ... > or other. I mean #=> dispatches to #named: on the slot anyway. > > If we define the class / slot objects like this: > > Object subclass: #MyTask > slots: { BOInstanceVariableSlot named: #'id'. > #anotherIVar. > BOTypedSlot named: #'description' type: String. > BOAttributeSlot named: #'isDone' type: Boolean default: true. > BOAttributeSlot named: #'created' type: Date default: [ Date today ] } > classVariables: { } > package: 'CustomSlots-Definitions-Examples' > > is more natural than the => forms where the name is just disrupted from the other arguments. > The attached file out from a Pharo 8 example demonstrates this. > > Just file it in and have a look at class MyTask or inspect "MyTask new created" or "MyTask new created: 2" to see that > the implemented simple slot typing and defaults are working. > > Then look at the definition of #MyTask class, which looks like written above. It could be made even more readable using > > Object subclass: #MyTaskEvenEasier > slots: { BOAttributeSlot named: #'id'. > BOAttributeSlot named: #'anotherIVar'. > BOAttributeSlot named: #'description' type: String. > BOAttributeSlot named: #'isDone' type: Boolean default: true. > BOAttributeSlot named: #'created' type: Date default: [ Date today ] } > classVariables: { } > package: 'CustomSlots-Definitions-Examples' > > only. > > The benefits without the => indirection are: > - a simple, compact and easy readable class definition even when slots are used > - slot definitions are regular messages to the slot class - simply evaluate or inspect the full slot class side message > - we keep the possibility to mix slots with other instance variables (here #anotherIVar in the example by using the symbol) > - we keep the possibility to evaluate the full slots definition and check the array of their definition > - we unify the definition with the "MyClass slots" message - as both are just return the array of slot objects > - we do not rely on an additional specific definition API one has to remember To me there is a drawback on this: even though being a message send is actually more flexible, arbitrary messages can be hard to cope with by tools. For example, if we want to validate if a slot definition is valid before loading it (e.g., if its class exists), we need to identify the slot kind/class from that message send. The same happens with the slot name. If someone defines a slot as MySlot new name: #asd. or MySlot withName: #asd. tools will just be much harder to implement Although this can be helped by strong name conventions (i.e., always a slot definition is a message send, always the receiver is a class, always the first keyword is #named: ?, all args are literal). ^^ > > So where is the real value in the often used additional indirection of the => message in slot definitions? > > Thanks > T. > <CustomSlots-Definitions.st> |
In reply to this post by Marcus Denker-4
> El 9 sept 2019, a las 9:57, Marcus Denker <[hidden email]> escribió: > > I will have a look, but I feel that we should first get the Composed Slots into the image > as they will change everything again. Marcus, how much time could it take you to have a mature version we can test and try? I'd avoid moving research experiments into the image before they have some maturity... > > >> On 8 Sep 2019, at 09:17, ducasse <[hidden email]> wrote: >> >> Hi >> >> I’m fixing the class definition parser and I have a question. >> >> I’m stabilizing the API of CDSlotNode >> >> >> 1 ‘first' => LazyClassVariable default: 5. >> 2 ’second' => InstanceVariableSlot. >> 3 ‘instVar3’ >> >> Here is a proposal >> >> slotdefinition(3) name ? variable name >> >>> ’instVar3' >> >> slotDefinition(2) slotClass? >> >>> InstanceVariableSlot >> >> slotDefinition(1) initializationMessage >> >>> 'default: 5’ >> or better >> >>> Node(default: 5) if it exist >> >> S. >> >> >> > > |
> On 9 Sep 2019, at 16:03, Guillermo Polito <[hidden email]> wrote: > > > >> El 9 sept 2019, a las 9:57, Marcus Denker <[hidden email]> escribió: >> >> I will have a look, but I feel that we should first get the Composed Slots into the image >> as they will change everything again. > > Marcus, how much time could it take you to have a mature version we can test and try? > I'd avoid moving research experiments into the image before they have some maturity… > Marcus |
Marcus to me the point is that we should not rush this kind of things.
What we should think is - freeze a syntax - I like the idea of guille to make sure that we cannot have any message in the slot - take the time to discuss the design, do code review, make sure that we have tests - to me a programmer should not compose slot property in the class definition. Stef > On 9 Sep 2019, at 16:12, Marcus Denker <[hidden email]> wrote: > > > >> On 9 Sep 2019, at 16:03, Guillermo Polito <[hidden email]> wrote: >> >> >> >>> El 9 sept 2019, a las 9:57, Marcus Denker <[hidden email]> escribió: >>> >>> I will have a look, but I feel that we should first get the Composed Slots into the image >>> as they will change everything again. >> >> Marcus, how much time could it take you to have a mature version we can test and try? >> I'd avoid moving research experiments into the image before they have some maturity… >> > I am trying to block time to finish it till next week… > > > Marcus > > |
> On 9 Sep 2019, at 17:00, ducasse <[hidden email]> wrote: > > Marcus to me the point is that we should not rush this kind of things. > What we should think is > - freeze a syntax - I like the idea of guille to make sure that we cannot have any message in the slot > - take the time to discuss the design, do code review, make sure that we have tests > - to me a programmer should not compose slot property in the class definition. > I will finish it and then we can discuss. Marcus |
Free forum by Nabble | Edit this page |