pharo-project / pharo

Pharo is a dynamic reflective pure object-oriented language supporting live programming inspired by Smalltalk.
http://pharo.org
Other
1.19k stars 351 forks source link

Write a test that ClassDefinitionParser should allow global message node receivers for slots #4636

Closed astares closed 1 year ago

astares commented 4 years ago
Ducasse commented 4 years ago

Hi torsten

we got a good discussion with pablo, esteban, marcus and we came up to this agreement. we will support

{

x .

x => Observable .

x => (Observable keyword: literal message: literal2)

}

I will update the class parser definition and marcus will fix the rest.

Ducasse commented 4 years ago

We compromise because I did not like the #x => Observable keyword: literal message: literal2 and esteban is right that having the variables first is good to have. I think that we got a good compromise so that we can build a nice class definitions and visitors (for example to export to tonel).

We will also build the new class definition that I propose (and modified a bit) class definition to avoid the combinatioral explosion of possibitlieis

Superclass <<< # MyClass slots: {}; ... package: # MyPackage

the spaces between # and the rest are there because this crappy editor :)

astares commented 4 years ago

@Ducasse

it's fine to have the #x => definitions (even when complicated) but PLEASE additionally keep the possiblities we already have to just provide an object that responds to #name which is required to place the slot into the object.

SO PLEASE CONSIDER TO STILL ALLOW REGULAR (composable) SLOT OBJECTS THAT ARE CREATED FROM MESSAGES:

{
   (BaseSlot named: literal)
          keywordMessage1: param1;
          keywordMessage2: param2 with: param3;
          unaryMessage1;
          unaryMessage2.          
}

where only objects are used. It's the most natural form we can have and is possible to provide non-composed and composed slot objects with it.

It is more natural and will easily support definitions like:

{ 
      (AttributeSlot named: #'x') 
               type: #Integer;
               default: 2;
               beLazy.

      (AttributeSlot named: #'y') 
               type: #Integer;
               default: 2;
               beLazy.
}

or when written more compact:

{ 
      (AttributeSlot named: #'x') type: #Integer; default: 2; beLazy.
      (AttributeSlot named: #'y') type: #Integer; default: 2; beLazy.
}

This even works for compositions where the #beLazy method can care on the composition (be it defined internally directly or done using composing with LazySlot using the #+ message as in Marcus's demo). So we can even hide the complexity of slot compositions or change them behind the scenes if we need to.

So anyone is free to have custom slots and own compositions / messages like:

{ 
      (RelationSlot named: #'x') opposite: OtherClass -> #foo; beNavigable.
       ...
}

easily with this already supported scheme. It is already possible in Pharo 7/8. and one does not even require a special parser or understanding to fiddle with such definitions.

What also comes for free: if one wants to extend with new behavior one can easily add more simple methods (as extension) to the base slot (like AttributeSlot) and with that extend the possibilities of the definitions on one side - but also keep them natural and readable on the other side.

Keeping this definition style (either solely or as a possibility beside =>) would provide the following benefits:

Also as this notation is currently already possible in P7/P8 you will break existing code if you now take away this possibility of the definition.

So I hope this fourth form:

{

x .

x => Observable .

x => (Observable keyword: literal message: literal2)

(Observable named: #x) message: literal2 }

is still possible anymore in the future (to return an object able to respond on the slot name).

Unfortunately I'm not at your place or able to take part on all your direct discussions to get heard. Reducing the possibilities would for me mean to loose possibilities that I now have and really need. Reducing to the above 3 in Pharo would mean the platform I now use goes in opposite direction than the flexibility I now have and also require in the future - which for me would be very sad and hard to work around over time.

So I can only hope that this style "just return an object that responds to name" for the slot definition is continued to be supported among the available definition possibilitis as I explained and demoed in

https://lists.pharo.org/pipermail/pharo-dev_lists.pharo.org/2019-September/276248.html

Unfortunately I can not do more than just trying to explain it to get you closer to my POV and needs.

[Pharo-dev] Slot definition API?
Ducasse commented 4 years ago

Hi Marcus explained us your solution and we looked at it. We are expert in language design and tools. We want a syntax that support the fact that we can have a class definition referencing objects that do not exist in the system. For the flexibility people will be able to define their own slots and extensions following our patterns. So we will work on the solution we decided. And people willing to have super extensibility will be able to brainstorm in their corners.

astares commented 4 years ago

Be aware that your answer is and can not be satisfying. It does not give a single answer or argument why we can not ADDITIONALLY allow what is already possible.

{ (Observable named: #x) message: literal2 }

It's totally fine to have the => syntax and no problem with having it as the DEFAULT and get better support in tools for it. Also if the parser would simply ignore the other style - but still allow to define slots only with that by evaluating.

Pharo should not prevent the possibility to work without it. Because then it would stop people (like me) to explore other paths. I still wonder if we can not work out a way where we can support this DEFAULT or other.

Also claiming "WE are the experts" "follow OUR patterns" "WE decided" quickly gets the smell of a very exclusive club ignorant to outside views and needs. Such statements are unnecessary and are contrary to statements that Pharo is based on a community model. Also somehow sad to hear.

I know something must be agreed upon ... and all is work and effort.

As I said I dont have a problem with the => syntax and decision per se - when it is used as the DEFAULT. But when this LIMITS to to be the "one and only" in Pharo we should really rethink if we would (for special needs) allow to disable it or provide hooks to bring in other ways for the slot definitions. It was nothing more that I asked for.

Ducasse commented 4 years ago

We will pay attention that you can experiment but you should understand that we want to have some properties. We introduce a class definition AST (and the surface syntax will change) and we want to make sure that we get the right properties from this. People will be able to use their own slots but the class definition will not allow any messages, nor block. What we can check is that people can specify their own classDefinition parser.

We are understanding what you are doing with relationships. I even have a name for that. Pharo Modeling platform and I really encourage you to continue it. Now it cannot just be the default Pharo. For this I would define a separate layers with its own decided class definition. This is not because we have message everywhere that it is good. In fact this is a lack of design and after we end up in situation where we cannot build adequate tools because we have "black holes" in which everybody can put Anything. So it is better to have a layered architecture. You see we can have a simple extension mechanism that select the correct layer (here ClassParserDefinition). And please note that I'm not the only one to decide we dropped the => and esteban argument convinced us, then Pablo and guille who are building a lot of infrastructure have also really interesting point of views. I'm more public to protect their engineering time but it does not mean that we are not collegially thinking what is a good compromise and I think that we got one. So to me I'm for Pharom but pharom ~= pharo.

MarcusDenker commented 4 years ago

I would have formulated Stef's note differently:

We discussed and I wanted to write a public report about it. The discussion is not "we decided", I see it more as "we discussed and had and idea that seems to be good for all".

The idea is to get a (simple) default in the system (using #a => notation, enforce to use (), composition has to be done by creating your own Slot (subclass of ComposedSlot, details have to b e worked out).

The reason is that there are too many open questions about slot definition as part of the class definition: How to do it syntax wise? Do really need it or is it not too complex?

We need to explore the space more.

This means that I will make sure that there is a loadable package which allows us to experiment with defining slot composition in the class directly.

This then allows us to explore all the ideas (e.g. mine with the Slot1+Slot2, yours, denis' with just #symbols).

astares commented 4 years ago

Hi @Ducasse , @MarcusDenker

thanks for your response and understanding.

As I said I'm totally fine with whatever

There is no need to change existing composition ideas - or make it a loadable package. I already have a custom implementation anyway for my extended and specific needs - even with a syntax allowing blocks.

So I can happily stay with default Pharo here. For the class definition I would require object based definition syntax (either in the default ClassDefinitionParser or by the possibility to provide a custom one). So a hook would be enough (see https://github.com/pharo-project/pharo/issues/4653)

@Ducasse I'm not doing a Pharo Modeling platform - maybe you just got that impression from the UML videos. This was just a side product that I needed to bootstrap quicker own meta-metamodels that can run other metamodels and models and applications basd on that ...

The approach is independentfrom UML - even from language, platform after the bootstrap. So I can run on top of Pharo, JS or other. Hard to explain - Marcus has seen a little bit of it at ESUG but not all.

Ducasse commented 4 years ago

Ok PharoM for me = Pharo + relationships.

MarcusDenker commented 1 year ago

I merge this PR into #4629 (as implementing it needs a test, too)