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, <stepharo@netcourrier.com> 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 8 Sep 2019, at 10:15, tesonep@gmail.com wrote:
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?
I had the same :) Now I wondered if allowing a block would make sense. But it automatically raises the evaluation environment so I would prefer not.
Cheers.
On Sun, 8 Sep 2019, 09:41 ducasse, <stepharo@netcourrier.com <mailto:stepharo@netcourrier.com>> 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.
El 8 sept 2019, a las 17:55, ducasse <stepharo@netcourrier.com> escribió:
On 8 Sep 2019, at 10:15, tesonep@gmail.com <mailto:tesonep@gmail.com> wrote:
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?
I had the same :) Now I wondered if allowing a block would make sense.
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
But it automatically raises the evaluation environment so I would prefer not.
Cheers.
On Sun, 8 Sep 2019, 09:41 ducasse, <stepharo@netcourrier.com <mailto:stepharo@netcourrier.com>> 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 8 Sep 2019, at 09:17, ducasse <stepharo@netcourrier.com> 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.
El 8 sept 2019, a las 17:59, ducasse <stepharo@netcourrier.com> escribió:
On 8 Sep 2019, at 09:17, ducasse <stepharo@netcourrier.com> 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.
maybe #slotClassName instead of #slotClass? Iâm not against the symbol...
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
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.
S.
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.
maybe #slotClassName instead of #slotClass?
Yes I will rename typeName
Iâm not against the symbol...
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
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)
Yes I did this.
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 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)
S.
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 <stepharo@netcourrier.com> 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.
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 <astares@gmx.de> 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>
Th¡¡
El 8 sept 2019, a las 23:48, Torsten Bergmann <astares@gmx.de> 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>
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 <stepharo@netcourrier.com> 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.
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
El 9 sept 2019, a las 9:57, Marcus Denker <marcus.denker@inria.fr> 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 <stepharo@netcourrier.com> 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 <guillermopolito@gmail.com> wrote:
El 9 sept 2019, a las 9:57, Marcus Denker <marcus.denker@inria.fr> 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
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 <marcus.denker@inria.fr> wrote:
On 9 Sep 2019, at 16:03, Guillermo Polito <guillermopolito@gmail.com> wrote:
El 9 sept 2019, a las 9:57, Marcus Denker <marcus.denker@inria.fr> 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 <stepharo@netcourrier.com> 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
I would prefer that we discuss also because we need to have a design that suits us. I do not think Pharo will benefit to have a complex class definition. Stef
On 9 Sep 2019, at 17:20, Marcus Denker <marcus.denker@inria.fr> wrote:
On 9 Sep 2019, at 17:00, ducasse <stepharo@netcourrier.com> 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
Hi. Another option is to not expose slot class names at all and use messages instead: - #first slot lazy default: 5 - #second slot boolean - #instVar3 slot weak lazy - #typedVar slot type: Integer; lazy #slot here will return SlotDefinition. And following messages will configure it or produce new instances. I think it is more simple approach than having "binary message algebra" for slots composition. Implementation of slots in that case will force developers to extend the slot definition API and therefore the parser. пн, 9 ÑенÑ. 2019 г. в 18:21, ducasse <stepharo@netcourrier.com>:
I would prefer that we discuss also because we need to have a design that suits us. I do not think Pharo will benefit to have a complex class definition.
Stef
On 9 Sep 2019, at 17:20, Marcus Denker <marcus.denker@inria.fr> wrote:
On 9 Sep 2019, at 17:00, ducasse <stepharo@netcourrier.com> 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
participants (6)
-
Denis Kudriashov -
ducasse -
Guillermo Polito -
Marcus Denker -
tesonep@gmail.com -
Torsten Bergmann