Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » Xcore syntax for object creation and initialization
Xcore syntax for object creation and initialization [message #719247] Fri, 26 August 2011 14:05 Go to next message
Eclipse User
Originally posted by:

Hi,

I've been playing with the Xcore grammar and model, to support a nicer
syntax for initializing objects, inspired by HUTN and comments to a
previous post. Here's an example supported by the current design:

op Library createExampleLibrary() {
return new Library() {
authors:
val ibsen = new Person() { name = "Henrik Ibsen" },
val tolstoj = new Person() { name = "Leo Tolstoj" }
books:
new Book() { title = "War and Peace" authors: tolstoj },
val warAndPeace = new Book() { title = "War and Peace" authors:
tolstoj },
new Book() { title = "Peer Gynt" authors: ibsen }
customers : val hallvard = new Person() { name = "Hallvard" +
"Trætteberg"}
loans : new Loan() { books: warAndPeace borrower = hallvard }
}
}

- The initialization is done in an optional initialization block after
the new expression. I found this to be a useful extension of the
existing object creation syntax, particularly since it should work for
all Java classes and not only EClasses.

- The initialization block allows assignments to single-value features
using the existing = operator and multi-valued ones with the : operator.
The : operator is similar to +=, but allows a list of values separated
by , operators. I wanted to avoid the explicit creation of lists using
newArrayList, and this required the new : and , operators.

- The constructs creates a new scope where the this constant refers to
the newly created object, so you can refer to fields without
qualification. BTW, this has also been utilized in an experimental with
statement, with (expr) { ... expressions ...}, where this refers to expr
within the expressions.

- The only new element in Xcore.ecore is a new XWithExpression, to
handle the this scope. In addition, an XConstructorCall in the head of a
XWithExpression indicates this initialization construct. In fact, new
<class>() { ... } is parsed to with (new <class>()) { ... }.

- You can introduce read-only variables to contained values/objects, to
make it possible to refer across branches and create a graph. These
variables are created in the scope of the outermost new, e.g. new
Library in the example. So within this scope, all variables may be
referred to.

- I have not implemented the interpreter, but since the linking seems to
work (both Jvm names and variables), it shouldn't be that difficult. The
execution should be in two passes, the constructors and optional
variable assignments first and then the initializations.

The syntax (and semantics) is a compromise, based on considering many
trade-offs concerning the grammar, syntax implementation and (future)
interpretation.

Comments are welcome!

Hallvard
Re: Xcore syntax for object creation and initialization [message #719303 is a reply to message #719247] Fri, 26 August 2011 16:05 Go to previous messageGo to next message
Ed Merks is currently offline Ed Merks
Messages: 26086
Registered: July 2009
Senior Member
Hallvard,

Comments below.

On 26/08/2011 7:05 AM, Hallvard Trætteberg wrote:
> Hi,
>
> I've been playing with the Xcore grammar and model, to support a nicer
> syntax for initializing objects, inspired by HUTN and comments to a
> previous post. Here's an example supported by the current design:
>
> op Library createExampleLibrary() {
> return new Library() {
Should we consider reducing this further to eliminate the ()? I suppose
to handle general Java one wouldn't consider that...
> authors:
> val ibsen = new Person() { name = "Henrik Ibsen" },
> val tolstoj = new Person() { name = "Leo Tolstoj" }
> books:
> new Book() { title = "War and Peace" authors: tolstoj },
> val warAndPeace = new Book() { title = "War and Peace" authors:
> tolstoj },
> new Book() { title = "Peer Gynt" authors: ibsen }
> customers : val hallvard = new Person() { name = "Hallvard" +
> "Trætteberg"}
> loans : new Loan() { books: warAndPeace borrower = hallvard }
> }
> }
>
> - The initialization is done in an optional initialization block after
> the new expression. I found this to be a useful extension of the
> existing object creation syntax, particularly since it should work for
> all Java classes and not only EClasses.
That's definitely a cool thing. Perhaps something to incorporate in
Xbase...
>
> - The initialization block allows assignments to single-value features
> using the existing = operator and multi-valued ones with the :
> operator. The : operator is similar to +=, but allows a list of values
> separated by , operators. I wanted to avoid the explicit creation of
> lists using newArrayList, and this required the new : and , operators.
Are they really operators? (Rather than separators for a list.) I
suppose you mean in the same sense that ? and : are a ternary operator
in Java.
>
> - The constructs creates a new scope where the this constant refers to
> the newly created object, so you can refer to fields without
> qualification. BTW, this has also been utilized in an experimental
> with statement, with (expr) { ... expressions ...}, where this refers
> to expr within the expressions.
>
> - The only new element in Xcore.ecore is a new XWithExpression, to
> handle the this scope. In addition, an XConstructorCall in the head of
> a XWithExpression indicates this initialization construct. In fact,
> new <class>() { ... } is parsed to with (new <class>()) { ... }.
>
> - You can introduce read-only variables to contained values/objects,
> to make it possible to refer across branches and create a graph. These
> variables are created in the scope of the outermost new, e.g. new
> Library in the example. So within this scope, all variables may be
> referred to.
So there's a single flat scope across the entire initialization...
>
> - I have not implemented the interpreter, but since the linking seems
> to work (both Jvm names and variables), it shouldn't be that
> difficult. The execution should be in two passes, the constructors and
> optional variable assignments first and then the initializations.
>
> The syntax (and semantics) is a compromise, based on considering many
> trade-offs concerning the grammar, syntax implementation and (future)
> interpretation.
Life is a tradeoff...
>
> Comments are welcome!
We definitely need something like this...

Do you imagine something like this could be used as a serialization
syntax as well?
>
> Hallvard
Re: Xcore syntax for object creation and initialization [message #719392 is a reply to message #719303] Fri, 26 August 2011 21:47 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 26.08.11 18.05, Ed Merks wrote:
> Hallvard,
>
> Comments below.
>
> On 26/08/2011 7:05 AM, Hallvard Trætteberg wrote:
>> Hi,
>>
>> I've been playing with the Xcore grammar and model, to support a nicer
>> syntax for initializing objects, inspired by HUTN and comments to a
>> previous post. Here's an example supported by the current design:
>>
>> op Library createExampleLibrary() {
>> return new Library() {
>
> Should we consider reducing this further to eliminate the ()? I suppose
> to handle general Java one wouldn't consider that...

I did eliminate them first, but yes, to handle general Java we need to
support arguments. In HUTN, you may define (in a separate config model)
that certain features are parameters. This has two nice effects: It
forces you to provide values for these features and makes the syntax
more compact. E.g. a Point with features x, y. You usually want to
provide their values and new Point(10, 50) is quicker to both write and
read than new Point() { x = 10, y = 50}. I guess an annotation on the
EClass or its features can be used for declaring the parameters.

>> authors:
>> val ibsen = new Person() { name = "Henrik Ibsen" },
>> val tolstoj = new Person() { name = "Leo Tolstoj" }
>> books:
>> new Book() { title = "War and Peace" authors: tolstoj },
>> val warAndPeace = new Book() { title = "War and Peace" authors:
>> tolstoj },
>> new Book() { title = "Peer Gynt" authors: ibsen }
>> customers : val hallvard = new Person() { name = "Hallvard" +
>> "Trætteberg"}
>> loans : new Loan() { books: warAndPeace borrower = hallvard }
>> }
>> }
>>
>> - The initialization is done in an optional initialization block after
>> the new expression. I found this to be a useful extension of the
>> existing object creation syntax, particularly since it should work for
>> all Java classes and not only EClasses.
>
> That's definitely a cool thing. Perhaps something to incorporate in
> Xbase...

It's follows naturally from linking to the inferred Jvm model for the
X/E/GenClass, instead of the classes themselves. Whether you link to
"real" constructors or the inferred ones doesn't matter.

>> - The initialization block allows assignments to single-value features
>> using the existing = operator and multi-valued ones with the :
>> operator. The : operator is similar to +=, but allows a list of values
>> separated by , operators. I wanted to avoid the explicit creation of
>> lists using newArrayList, and this required the new : and , operators.
>
> Are they really operators? (Rather than separators for a list.) I
> suppose you mean in the same sense that ? and : are a ternary operator
> in Java.

: and , are operators in the sense that they parse to XBinaryExpression
objects and link to extension methods that implement their meaning, set
the content of a Collection and build Iterables, respectively. Note that
grammar only allow them within the initialization blocks.

>> - The constructs creates a new scope where the this constant refers to
>> the newly created object, so you can refer to fields without
>> qualification. BTW, this has also been utilized in an experimental
>> with statement, with (expr) { ... expressions ...}, where this refers
>> to expr within the expressions.
>>
>> - The only new element in Xcore.ecore is a new XWithExpression, to
>> handle the this scope. In addition, an XConstructorCall in the head of
>> a XWithExpression indicates this initialization construct. In fact,
>> new <class>() { ... } is parsed to with (new <class>()) { ... }.
>>
>> - You can introduce read-only variables to contained values/objects,
>> to make it possible to refer across branches and create a graph. These
>> variables are created in the scope of the outermost new, e.g. new
>> Library in the example. So within this scope, all variables may be
>> referred to.
>
> So there's a single flat scope across the entire initialization...

For all the initializers, yes, but you can have local scopes inside the
value expressions. A bit strange, but it feels natural in this context.
The rule for deciding whether the scope is local or within the
initialization and finding the outer initialization is pretty simple.

>> Comments are welcome!
> We definitely need something like this...

I think it provides benefits for both plain Java and X/Ecore, without
introducing too much and strange syntax.

> Do you imagine something like this could be used as a serialization
> syntax as well?

I think so (not for general POJOs but for Ecore). HUTN provides a
converter/serializer, and this isn't very different.

Hallvard
Re: Xcore syntax for object creation and initialization [message #719451 is a reply to message #719303] Sat, 27 August 2011 08:04 Go to previous messageGo to next message
Thomas Schindl is currently offline Thomas Schindl
Messages: 5342
Registered: July 2009
Senior Member
Am 26.08.11 18:05, schrieb Ed Merks:
> Hallvard,
>
> Comments below.
>
> On 26/08/2011 7:05 AM, Hallvard Trætteberg wrote:
>> Hi,
>>
>> I've been playing with the Xcore grammar and model, to support a nicer
>> syntax for initializing objects, inspired by HUTN and comments to a
>> previous post. Here's an example supported by the current design:
>>
>> op Library createExampleLibrary() {
>> return new Library() {
> Should we consider reducing this further to eliminate the ()? I suppose
> to handle general Java one wouldn't consider that...

.... could we not also eliminate the "new"?

Tom
Re: Xcore syntax for object creation and initialization [message #719652 is a reply to message #719451] Sun, 28 August 2011 07:50 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 27.08.11 10.04, Tom Schindl wrote:
> Am 26.08.11 18:05, schrieb Ed Merks:
>> Hallvard,
>>
>> Comments below.
>>
>> On 26/08/2011 7:05 AM, Hallvard Trætteberg wrote:
>>> Hi,
>>>
>>> I've been playing with the Xcore grammar and model, to support a nicer
>>> syntax for initializing objects, inspired by HUTN and comments to a
>>> previous post. Here's an example supported by the current design:
>>>
>>> op Library createExampleLibrary() {
>>> return new Library() {
>> Should we consider reducing this further to eliminate the ()? I suppose
>> to handle general Java one wouldn't consider that...
>
> ... could we not also eliminate the "new"?

This is a trade-off: How similar to normal Java should the syntax be.
Originally, there were no new keywords inside the initialization, there
were no parentheses and even the class name was optional (since you know
the feature, you can derive it). This made the construct look more
declarative, which I think is good. However, the grammar and model grew
a bit more than I liked, which would make the syntax less familiar for
Java developers and harder to implement (typing, scoping, interpretation
etc.). Hence I reverted to a design with minimal changes to Xbase, which
is the one I implemented and presented.

I wouldn't mind (and it shouldn't be difficult) removing (making
optional) the new keywords and parentheses (and even the class name),
but only if others want it.

Hallvard
Re: Xcore syntax for object creation and initialization [message #719655 is a reply to message #719451] Sun, 28 August 2011 08:07 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 27.08.11 10.04, Tom Schindl wrote:
> Am 26.08.11 18:05, schrieb Ed Merks:
>> Hallvard,
>>
>> Comments below.
>>
>> On 26/08/2011 7:05 AM, Hallvard Trætteberg wrote:
>>> Hi,
>>>
>>> I've been playing with the Xcore grammar and model, to support a nicer
>>> syntax for initializing objects, inspired by HUTN and comments to a
>>> previous post. Here's an example supported by the current design:
>>>
>>> op Library createExampleLibrary() {
>>> return new Library() {
>> Should we consider reducing this further to eliminate the ()? I suppose
>> to handle general Java one wouldn't consider that...
>
> ... could we not also eliminate the "new"?

I forgot to mention one thing I struggled with: Since you don't know the
type of feature you're initializing in advance (attribute vs. reference,
single- vs. multi-valued), you'll in general need to support all kinds
of expressions as the value. And this made it difficult to allow e.g.
object creation without new, since it quickly would give errors in the
grammar (ambiguity, etc). A possibility is to use assignment operators
specific to the kind of feature (attribute vs. reference), since that
would allow more specific grammar rules, but this may be confusing to
the user.

Hallvard
Re: Xcore syntax for object creation and initialization [message #719726 is a reply to message #719451] Sun, 28 August 2011 15:48 Go to previous messageGo to next message
Ed Willink is currently offline Ed Willink
Messages: 4056
Registered: July 2009
Senior Member
Hi
> ... could we not also eliminate the "new"?
>
I was going to make the same suggestion; you then end up with a
candidate OCL type constructor syntax.

But Xcore is Java-like, not OCL.

new is expected in Java
object creation may have side effects
removing a keyword can make parsing/error recovery very challenging

Regards

Ed Willink
Re: Xcore syntax for object creation and initialization [message #720541 is a reply to message #719392] Tue, 30 August 2011 19:27 Go to previous messageGo to next message
Eclipse User
Originally posted by:

The following initialization now works, both syntax and in the interpreter:

package foo.bar

class Bar
{
String value
}

class Foo
{
String value
contains Bar[*] bars1
refers Bar[*] bars2

op Foo bar() {
return new Foo() {
bars2 =* theBar
bars1 =* val theBar = new Bar() {
value = s
}, new Bar() {
value = val s = new String("bar")
}
value = s
}
}
}

We see a combination of single- (=) and multi-value (=*) assignment and
variable declarations within (theBar) and across initializations (s).
Note that I now use '=*' instead of ':', because ':' confused the
parsing of switch, e.g. in switch new Foo() { String : "" } ... the
block was interpreted as an initialization of Foo's (non-existing)
'String' feature instead of a switch body with a String (type) case! I'm
not satisfied with using '=*', but it works as a temporary solution.

Hallvard
Re: Xcore syntax for object creation and initialization [message #720925 is a reply to message #720541] Wed, 31 August 2011 13:50 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven Efftinge
Messages: 1767
Registered: July 2009
Senior Member
Hi,

as already mentioned in another thread we wanted to have a similar expression for some time now, but hold it back because we were not confident with the design so far and needed to focus on other topics.
However, we now managed to come up and implement a design we like and put it into Xbase.

It boils down to a classic let- or with-expression, where I can give a certain value an alias for a certain scope.
Syntactically we wanted it to be extremely concise, so we avoided a keyword.

The general syntax is :
: varName : expression {
   // block in which the expression is bound to varName
}

In addition to the varName the value is also bound to the implicit variable 'it'.
Such that :
: myString : "Foo" {
   assertSame( myString, it )
   assertEquals( myString.length, length )
}

The explicit variable name is optional :
: "Foo" {
   println("length of "+it+" is "+length)
}

And also the expression is optional if it can be inferred from the context (i.e. expected type). The default strategy is that if the expected type is a concrete Java type and has a default constructor that one is called implicitly:
// given Person is a POJO with a default constructor
val Person p = :{
   firstName = "Leo"
   name = "Tolstoj"
   books += :{
     title = "War and Peace"
   }
}

The language specific strategy however can be more sophisticated. For instance Xtend allows to have a field declared with a keyword 'instance factory'. In that case any operations with null arguments serve as factory methods. That allows for using this approach with EMF:
// Xtend and EMF

instancefactory LibraryFactory f

def Library createLibrary() {
  :{ 
    authors += :{
       name = "Leo Tolstoj"
    }
  }
}

That's it. We tried to avoid any special treatment of expressions in that context like flat scoping, special collection literals, etc. because we think it would be surprising for users if the semantics of expressions are different in different contexts.
I am aware that this solutions although very general doesn't solve the heavy-cross-linking-case. You'll have to declare elements you want to refer to up front.

It's in the repository now, if you want to try it.
It's going to be released in October.
So there's still some time to discuss this and incorporate feedback Wink

Best Regards,
Sven


--
Need professional support on Xtext or Xtend?
Mail to: xtext (at) itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de

[Updated on: Wed, 31 August 2011 13:52]

Report message to a moderator

Re: Xcore syntax for object creation and initialization [message #720999 is a reply to message #720925] Wed, 31 August 2011 16:24 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 31.08.11 15.50, Sven Efftinge wrote:
>
> It boils down to a classic let- or with-expression, where I can give a
> certain value an alias for a certain scope.

Yes, it looks like a combination. You bind and use it as scope for the
body. And return the bound value as the final result.

> Syntactically we wanted it to be extremely concise, so we avoided a
> keyword.

You mean you chose a concise keyword. I don't think (re)using ':', which
is often used as a separator, is a good idea, though. The examples made
me feel something is missing before the ':'... I admit it may be
difficult to find a good keyword, due to the construct's dual usage of
binding and/or creating and object.

> And also the expression is optional if it can be inferred from the
> context (i.e. expected type). The default strategy is that if the
> expected type is a concrete Java type and has a default constructor that
> one is called implicitly:

So val Person p = :{} will mean val Person p = new Person()? What about
collection types casting, will that introduce an expectation, e.g. will
<Person>newArrayList(:{}) create an ArrayList<Person> with one Person
element? And casting, will (:{} as Person) evaluate to a Person?

> The language specific strategy however can be more sophisticated. For
> instance Xtend allows to have a field declared with a keyword 'instance
> factory'. In that case any operations with null arguments serve as
> factory methods. That allows for using this approach with EMF:
>
> // Xtend and EMF

.... concerning EMF, how will this relate to Xcore? Will you allow :{ ...
} out-of-the-box without a factory declaration? Will you also allow an
ordinary new call?

> instancefactory LibraryFactory f

So it looks up any method in f without arguments that returns the
desired type?

> That's it. We tried to avoid any special treatment of expressions in
> that context like flat scoping, special collection literals, etc.

Yes, in general this is desirable. Since Collections are used so much, I
still think it deserves special support, or, since you're using Google's
Collection library, operators for Iterable values, like more
operator_plus methods:

IterablesExtensions:
public static <E> Iterable<? extends E> operator_plus(Iterable<? extends
E> it, E t) {
return Iterables.concat(it, Collections.<E>singletonList(t));
}

ObjectExtensions:
public static <E> Iterable<? extends E> operator_plus(E e1, Iterable<?
extends E> it) {
return Iterables.concat(Collections.<E>singletonList(e1), it);
}

public static <E> Iterable<E> operator_plus(E e1, E e2) {
return Iterables.concat(Collections.<E>singletonList(e1),
Collections.<E>singletonList(e1));
}

> I am aware that this solutions although very general doesn't solve the
> heavy-cross-linking-case. You'll have to declare elements you want to
> refer to up front.

I think heavy cross linking is an important use case. This means it will
be difficult to use it as a serialization format, like HUTN is?

> It's going to be released in October. So there's still some time to
> discuss this and incorporate feedback ;)

Well, I guess you can consider my own proposal a kind of 'feedback',
although I was hoping it would be used in the forward direction.

Regards,

Hallvard
Re: Xcore syntax for object creation and initialization [message #721071 is a reply to message #720999] Wed, 31 August 2011 20:08 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven Efftinge
Messages: 1767
Registered: July 2009
Senior Member
Eclipse User wrote on Wed, 31 August 2011 18:24
Originally posted by: <a href="mailto:"></a>
> Syntactically we wanted it to be extremely concise, so we avoided a
> keyword.

You mean you chose a concise keyword. I don't think (re)using ':', which
is often used as a separator, is a good idea, though. The examples made
me feel something is missing before the ':'... I admit it may be
difficult to find a good keyword, due to the construct's dual usage of
binding and/or creating and object.



Originally there was only one colon, so it was like in the for each loop or in the switch expression :
for (x : expr) {
}

x : expr {
}

We ran into ambiguities and had to let the expression begin with something unique, so we chose the colon:
:x : expr {
}


But I am also not so sure about it. The point you made about the usage as a separator is valid.
Any proposals for a small keyword (besides new) or a single special character?

Quote:

> And also the expression is optional if it can be inferred from the
> context (i.e. expected type). The default strategy is that if the
> expected type is a concrete Java type and has a default constructor that
> one is called implicitly:

So val Person p = :{} will mean val Person p = new Person()? What about
collection types casting, will that introduce an expectation, e.g. will
<Person>newArrayList(:{}) create an ArrayList<Person> with one Person
element? And casting, will (:{} as Person) evaluate to a Person?


Yes.

Quote:

> The language specific strategy however can be more sophisticated. For
> instance Xtend allows to have a field declared with a keyword 'instance
> factory'. In that case any operations with null arguments serve as
> factory methods. That allows for using this approach with EMF:
>
> // Xtend and EMF

.... concerning EMF, how will this relate to Xcore? Will you allow :{ ...
} out-of-the-box without a factory declaration? Will you also allow an
ordinary new call?


In Xcore I would like to have the factory methods of all referenced packages visible by default.
Regarding the constructor, I would prefer to use 'createEClass' instead of 'new EClass()' because I don't see much value in abstracting the underlying Java code away. It will leak through as soon as you start using the Xcore models with another JVM language and than it might be surprising that one can no longer use 'new EClass()'.
Also 'createEClass' isn't much different than 'new EClass()' in terms of readability, is it?

Quote:

> instancefactory LibraryFactory f

So it looks up any method in f without arguments that returns the
desired type?


Yes

Quote:

> That's it. We tried to avoid any special treatment of expressions in
> that context like flat scoping, special collection literals, etc.

Yes, in general this is desirable. Since Collections are used so much, I
still think it deserves special support, or, since you're using Google's
Collection library, operators for Iterable values, like more
operator_plus methods:

IterablesExtensions:
public static <E> Iterable<? extends E> operator_plus(Iterable<? extends
E> it, E t) {
return Iterables.concat(it, Collections.<E>singletonList(t));
}

ObjectExtensions:
public static <E> Iterable<? extends E> operator_plus(E e1, Iterable<?
extends E> it) {
return Iterables.concat(Collections.<E>singletonList(e1), it);
}

public static <E> Iterable<E> operator_plus(E e1, E e2) {
return Iterables.concat(Collections.<E>singletonList(e1),
Collections.<E>singletonList(e1));
}


The first one seems reasonable (i.e. iterable + obj) it might lead to surprises because we already have iterable + iterable.
I wouldn't want to define + for Object with this semantic. Maybe we should consider using another special operator? Scala uses ::

Quote:

> I am aware that this solutions although very general doesn't solve the
> heavy-cross-linking-case. You'll have to declare elements you want to
> refer to up front.

I think heavy cross linking is an important use case. This means it will
be difficult to use it as a serialization format, like HUTN is?


Inconvenient unfortunately. I agree that this is an interesting use case.
The semantic implications (flat scopes for BlockExpressions in this context) to get this working seam not worth it.

Quote:

> It's going to be released in October. So there's still some time to
> discuss this and incorporate feedback Wink

Well, I guess you can consider my own proposal a kind of 'feedback',
although I was hoping it would be used in the forward direction.


We of course already considered your initial proposal. Smile
That's why I post our's in this thread. Again: feedback is appreciated.

Sven


--
Need professional support on Xtext or Xtend?
Mail to: xtext (at) itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de
Re: Xcore syntax for object creation and initialization [message #721242 is a reply to message #721071] Thu, 01 September 2011 08:37 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 31.08.11 22.08, Sven Efftinge wrote:
>>
>> You mean you chose a concise keyword. I don't think (re)using ':',
>> which is often used as a separator, is a good idea, though. The
>> examples made me feel something is missing before the ':'... I admit
>> it may be difficult to find a good keyword, due to the construct's
>> dual usage of binding and/or creating and object.
>
> We ran into ambiguities and had to let the expression begin with
> something unique, so we chose the colon:
>
> :x : expr {
> }
>
> But I am also not so sure about it. The point you made about the usage
> as a separator is valid. Any proposals for a small keyword (besides new)
> or a single special character?

What about extending/reusing val to cover this, after all you're
initializing a value and optionally creating it. A trailing block is
within the scope of the variable bound to the value. I.e. 'var' (name=ID
'=')? value=XExpression (=> init=XBlockExpression)?

Examples:

// ordinary usage
val p = new Person()

// init block
val p = new Person() {
name = "Hallvard"
spouse = new Person() {
name = "Marit"
}
}

// the variable and = is optional
return val new Person() {
name = "Hallvard"
}

// or when Person is expected
op Person createPerson() {
return val {
name = "Hallvard"
spouse = val {
name = "Marit"
}
}
}

You often initialize a newly bound value, so combining it with val makes
sense. In most coding styles, you never have a trailing block, so using
it for this purpose should not affect existing code. You'll need to make
val construct "steal" the block using =>, since a trailing block is
legal, although not used in practice.

>> So val Person p = :{} will mean val Person p = new Person()? What
>> about collection types casting, will that introduce an expectation,
>> e.g. will <Person>newArrayList(:{}) create an ArrayList<Person> with
>> one Person element? And casting, will (:{} as Person) evaluate to a
>> Person?
>
> Yes.

That's a very nice feature and result of eager type inference!

> In Xcore I would like to have the factory methods of all referenced
> packages visible by default.

Sounds good.

> Regarding the constructor, I would prefer to use 'createEClass' instead
> of 'new EClass()' because I don't see much value in abstracting the
> underlying Java code away. It will leak through as soon as you start
> using the Xcore models with another JVM language and than it might be
> surprising that one can no longer use 'new EClass()'.
> Also 'createEClass' isn't much different than 'new EClass()' in terms of
> readability, is it?

As long as you avoid the length SomeFactory.eInstance.createEClass(), a
single call should be enough. My first attempt at language support for
EObject creation used the euro sign as an Ecore creation operator, both
because it fit the e-prefix used everywhere in EMF and because many of
the innovative EMF-users are European ;-)

> Maybe we should consider using another special operator? Scala uses ::

Yes, a cons operator like :: would be nice for an old lisp'er like me.
Scala has lots of collection operators and classes. XBase' += already
covers Scala's += and ++= (distinguishes between single and multi, to
allow adding collections to collections), but lacks -=. Scala uses **
for intersection, which XBase already uses for power.

>> I think heavy cross linking is an important use case. This means it
>> will be difficult to use it as a serialization format, like HUTN is?
>
> Inconvenient unfortunately. I agree that this is an interesting use case.
> The semantic implications (flat scopes for BlockExpressions in this
> context) to get this working seem not worth it.

Flat scopes is strange in a general language, I agree. Perhaps it's a
mistake trying to blend Xon (Xtext object notation) with Xbase, it need
to be more distinct. But if Xon is pursued for Xcore, it would still be
great to be able to combine it with Xbase (Xbase expressions Xon and Xon
expressions in Xbase).

> We of course already considered your initial proposal. :)
> That's why I post our's in this thread. Again: feedback is appreciated.

:-)

Hallvard
Re: Xcore syntax for object creation and initialization [message #721270 is a reply to message #721242] Thu, 01 September 2011 09:56 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven Efftinge
Messages: 1767
Registered: July 2009
Senior Member
We discussed reusing 'val' as well. But see two reasons why it's not a good choice:
1) the scoping is different
val x = new Person() {
    // x is bound to person
}
 // would x be visible here? it usually would.
// but what about 'it' if I have a second expression. is it redefined in the same scope?
val y = new Foo() {
}


2) the expression will often be used in the context of object creation. In that case the val keyword doesn't fit.
This becomes even more evident if you use all defaults:

   val Person p = val {
      name = "Halvard"
   }


Also variable declarations are only allowed and meaningful in block expressions. But the let expression not.
We also considered 'let' and 'with' btw. and generally a keyword seem to be too noisy.

Regarding the cons '::' operator. '::' is already taken by qualified names in static feature calls, so we cannot use it.

Sven


--
Need professional support on Xtext or Xtend?
Mail to: xtext (at) itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de
Re: Xcore syntax for object creation and initialization [message #721311 is a reply to message #721270] Thu, 01 September 2011 12:16 Go to previous messageGo to next message
Eclipse User
Originally posted by:

On 01.09.11 11.56, Sven Efftinge wrote:
> We discussed reusing 'val' as well. But see two reasons why it's not a
> good choice:
>
> 1) the scoping is different
>
> val x = new Person() {
> // x is bound to person
> }
> // would x be visible here? it usually would.
> // but what about 'it' if I have a second expression. is it redefined in
> the same scope?
> val y = new Foo() {
> }

I saw this problem, but would resolve it by having one rule for the
existing usage of val at the top-level in a block. In this case the
variable's scope extends throughout the block, while when it is used
further inside the expression tree, it would only be valid inside. The
it variable would only be valid inside, in both cases.

But I agree that needing such a rule is perhaps a sign that this design
is flawed.

> 2) the expression will often be used in the context of object creation.
> In that case the val keyword doesn't fit.
> This becomes even more evident if you use all defaults:
>
> val Person p = val {
> name = "Halvard"
> }

But wouldn't you write this as val p = new Person() { ... } instead of
having two levels of val?

> We also considered 'let' and 'with' btw. and generally a keyword seem to
> be too noisy.

What is considered "noisy" is person dependent (I know, with a 15 year
old son who likes rap. In fact, he thinks Motorpsycho is noisy ;-).
Perhaps you can make a keyword name poll, select between ':', 'let',
'with', 'new' or suggest your own :-)

Whatever decision, the construct will be nice to have.

> Regarding the cons '::' operator. '::' is already taken by qualified
> names in static feature calls, so we cannot use it.

Yes, :: is taken and ',', '++', are, too, but there are many other
characters to select among (is & taken?). Another decision is how it
handles different combinations of elements and Collections/Iterables,
i.e. which of the following are supported

Iterable cons(Object e1, Object e2) // create list
Iterable cons(Iterable l, Object e) // add/append
Iterable cons(Object e, Iterable l) // cons
Iterable cons(Iterable l1, Iterable l2) // concat, covered by +

Hallvard
Re: Xcore syntax for object creation and initialization [message #721453 is a reply to message #721311] Thu, 01 September 2011 19:41 Go to previous messageGo to next message
Sven Efftinge is currently offline Sven Efftinge
Messages: 1767
Registered: July 2009
Senior Member
Quote:

> 2) the expression will often be used in the context of object creation.
> In that case the val keyword doesn't fit.
> This becomes even more evident if you use all defaults:
>
> val Person p = val {
> name = "Halvard"
> }

But wouldn't you write this as val p = new Person() { ... } instead of
having two levels of val?


Yes, that might have been a bad example I tried to illustrate that you might want to use both expressions in a very close syntactical context.

Quote:

> We also considered 'let' and 'with' btw. and generally a keyword seem to
> be too noisy.

What is considered "noisy" is person dependent (I know, with a 15 year
old son who likes rap. In fact, he thinks Motorpsycho is noisy Wink.


Motorpsycho *is* noisy, but that's beautiful noise. I really like complex progressive rock, but in terms of software development I prefer clean and simple pop music.
In fact in the case of Xbase it needs to be a very simple drum&base pattern which leaves enough room for everyone's crazy sounds. Smile

Sven


--
Need professional support on Xtext or Xtend?
Mail to: xtext (at) itemis.com
Twitter : @svenefftinge
Blog : blog.efftinge.de
Re: Xcore syntax for object creation and initialization [message #1064883 is a reply to message #719247] Fri, 21 June 2013 14:05 Go to previous message
Michael Vorburger is currently offline Michael Vorburger
Messages: 62
Registered: July 2009
Member
anyone stumbling over this thread by Googling (like I just did) may be interested in my http://blog2.vorburger.ch/2013/06/efactory-ii-xobjects-ehutn.html, code on https://github.com/vorburger/efactory, demo on http://www.youtube.com/watch?feature=player_embedded&v=ToUWqIRHkHY

PS: What's described above is, meanwhile, the "With operator" in Xbase (Xtend) of course - but that's for Java bean objects - not dynamic ecore instances.
Previous Topic:[EMF] Problems with multiple supertypes in programatic metamodel creation
Next Topic:[EMF] Find out if a file is a model,
Goto Forum:
  


Current Time: Tue Sep 30 10:21:35 GMT 2014

Powered by FUDForum. Page generated in 0.02204 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software