Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Pharo class definition Syntax #4671

Closed
Ducasse opened this issue Sep 20, 2019 · 13 comments
Closed

New Pharo class definition Syntax #4671

Ducasse opened this issue Sep 20, 2019 · 13 comments

Comments

@Ducasse
Copy link
Member

Ducasse commented Sep 20, 2019

The new syntax for class definition (just for the class and not for the methods) is (modulo changes based on feedback)

Superclass <<< #MyObject
uses: #MyTrait;
slots: { #a. #b };
classVariables: { #A. #B };
tags: #(Core) ;
package: #MyPackage

The minimal class definition is the following one:

Superclass <<< #MyObject
package: #MyPackage

Note that sending a message to the superclass is close to subclass: and it lets the class selects
a class definition parser if the syntax should be extended.
In addition having a binary message makes () unneccessary.

@dionisiydk
Copy link
Contributor

Hi @Ducasse .

Using superclass as receiver does not cover the case when it is nil. Currently for proxy kind objects we are forced to write two lines definition:

Object subclass: MyProxy
   ...
MyProxy superclass: nil

It does not looks right.

Did you discuss in team my idea to use Class as receiver?

Class <<< #MyObject
  superclass: Superclass;
  uses: #MyTrait;
  slots: { #a. #b };
  classVariables: { #A. #B };
  tags: #(Core) ;
  package: #MyPackage

The minimal definition in that case is

Class <<< #MyObject
  package: #MyPackage

Where superclass is Object by default

@gcotelli
Copy link
Member

Maybe we can use a block an evaluate it later with a class builder to create a proper class:

[:class |  
  class 
    name: #MyObject;
    superclass: Superclass;
    uses: #MyTrait;
    slots: { #a. #b };
    classVariables: { #A. #B };
    tags: #(Core) ;
    package: #MyPackage
]

For proxies just omit the superclass: configuration, for anonymous classes omit the name: and so on.

@Ducasse
Copy link
Member Author

Ducasse commented Sep 20, 2019

Denis
Yes we discuss it but then we thought that the superclass is better to be able to introduce a hook to let people have their own class definition parser.

Now I will define the parser and produce the same model than the default one and we can play with variation.

@Ducasse
Copy link
Member Author

Ducasse commented Sep 20, 2019

Gabriel
in fact what we propose is already a builder. The difference between
Class <<< and ASuperClass<<< is that one can be used to place hooks and dispatch responsibilities.

@gcotelli
Copy link
Member

Why not then something like subclassBuilder or another unary message? It's less cryptic than <<< and allows to use also unary messages to configure the builder without parenthesis , and doesn't make mandatory the subclass name so it can be used to create anonymous subclasses too. I think the unary messages can be useful for things like weak/variable/byte subclasses (For example sending beWeak).

Superclass subclassBuilder
    name: #MyObject;
    uses: #MyTrait;
    slots: { #a. #b };
    classVariables: { #A. #B };
    tags: #(Core) ;
    package: #MyPackage

@astares
Copy link
Member

astares commented Sep 20, 2019

(#MyObject asClass)
    superClass: SuperclassOrNil)
    uses: #MyTrait;
    slots: { #a. #b };
    classVariables: { #A. #B };
    tags: #(Core) ;
    package: #MyPackage

would be more message and object-oriented and works with the nil superclass if the #superclass message is left out or gives nil as argument.

It also can be extended later with different environments than the default one:

(#MyObject asClassInEnvironment: someEnvironment)
   ...

@Ducasse
Copy link
Member Author

Ducasse commented Sep 22, 2019

Because we wantt to have a simple syntax that we can type in a texteditor so no extra parentheses (T. asClass is not good because it presumes that there is only one env), gabriel
did you see the ruby class definition? We want a compact one so we may ask for idea for
which selector to use.

@gcotelli
Copy link
Member

I see the Ruby class definitions. It's similar to other languages, specific syntactic constructs. I will certainly don't introduce new syntactic elements, just message sending (as this issue already proposes since the beginning). I find the Ruby syntax more cryptic than proper names, < for subclassing is worse that a word IMHO and @ , @@ for variables makes me 😭 .

If we want that each class could provide a different subclass builder then we will need the message send (just we need to find a good name).

Also I would change the slot definition syntax. Instead of having to provide an Array with some complex syntax rules, why not simple methods on the builder tailored for each slot kind?
Something like:

Object subclassBuilder
  ...
  addBooleanSlotNamed: #booleanSlot;
  addInstanceVariableNamed: #normalInstanceVariable;
  addLazySlotNamed: #lazy withDefault: 5

and so on

If you can explain us a little the context and motivations for changing the syntax of class creation we can have a more productive discussion :) . I'm really happy that we will get rid of this exponential combination of subclass creation messages and replace it with a proper builder (and remove the ones in UndefinedObject).

@fortizpenaloza
Copy link

Hi,

this is great news, thanks to pushing this @Ducasse .

I don't understand the motivation behind a compact class definition. Why do we need a compact one? I find ruby class definition economic in terms of amount of typed chars but quite obscure, not intelligible.

I like the idea proposed by @gcotelli of using a unary message since I don't have to even think in a class name if I want an anonymous one. Not sure if subclassBuilder is the better option, but surely we can come up with a better one.

@mtabacman
Copy link

I would also like a syntax like the one proposed by @gcotelli
I much prefer the idea of the builder with addBooleanSlotNamed:, etc. BUT if the final solution uses messages like superClass:, slots:, etc then PLEASE change uses: for trait: or something similar, since it is not consistent with the others.

@dionisiydk
Copy link
Contributor

Denis
Yes we discuss it but then we thought that the superclass is better to be able to introduce a hook to let people have their own class definition parser.

My first thought: is the superclass really good place for such hook?
It will restrict special classes (classes with special definition) to be defined in single hierarchy or to duplicate implementation of hooks.
Another problem which I see is how to implement special definition for single class? It will always require two classes: superclass which overrides the class parser and class itself.

In my approach (with Class as receiver of definition syntax) the hook can be defined on the meta level. The class with special definition can be simply based on special kind of Class. So the special class will require special meta object:

MyTypeOfClass <<< #MyNewSpecialClass 
   superclass: Object;
   mySpecialProperty: '';
   package: #MyPackage

@dionisiydk
Copy link
Contributor

I would also like a syntax like the one proposed by @gcotelli
I much prefer the idea of the builder with addBooleanSlotNamed:, etc. BUT if the final solution uses messages like superClass:, slots:, etc then PLEASE change uses: for trait: or something similar, since it is not consistent with the others.

I agree with 'traits:' vs 'uses:'

@MarcusDenker
Copy link
Member

This can be closed as Fluid is now in (still needs more work, though)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants