Object destructuring in method calls
See original GitHub issueHi
I want to propose an idea, allow destructing object over method invocation for avoid write “paramName = obj.paramName
”
Let me show you it with an example:
class Person(shared String lastName, shared String firstName, shared Integer birthYear){}
Person smith = Person("Smith", "John", 1985);
We want to create a copy modifying the birthYear for doing it we can create a copy method in the Person class, or create a new copy using the constructor.
Using the copy method design pattern: This design requires write a special method for create a new copy, maybe in a future the compiler can generate it automatically in some cases:
class Person_(shared String lastName, shared String firstName, shared Integer birthYear){
shared Person_ copy(String lastName = this.lastName, String firstName = this.firstName, Integer birthYear = this.birthYear) {
return Person_(lastName, firstName, birthYear);
}
}
Person_ smith_ = Person_("Smith", "John", 1985);
Person_ copy_ = smith_.copy{birthYear = 1980;};
Another approach is create a new copy using a constructor
Person copy1 = Person(smith.lastName, smith.firstName, 1980); // Parameter positional invocation
Person copy2 = Person { // Parameter named invocation
lastName = smith.lastName;
firstName = smith.firstName;
birthYear = 1980;
};
My proposition is to allow destructing object in the method invocation
Person copy = Person { // Parameter named invocation
...smith; // Unsupported syntax at this moment inspired in the object spread in EcmaScript 7
birthYear = 1980;
};
In this way we can create copies of simple objects without needed of a copy method in a easy way.
Rules: The method take from the destructed object the properties with the same name and compatible type missing in the method invocation
Syntax: Two options:
- As is in lower span. Eg:
...smith
- As in spread operator. Eg.:
*smith
I prefer the span syntax because the spread syntax can be confused with an spread argument
Thanks!
Issue Analytics
- State:
- Created 8 years ago
- Reactions:1
- Comments:6 (4 by maintainers)
Top GitHub Comments
I agree. And, spreading of labels tuples (#3851) for all named argument invocations.
While cloning with changes is important, it covers only a fraction of the potential use cases for spreading name->value mappings. This is especially true in Ceylon which favors immutability and null safety. 1) you can’t rely on mutability to populate fields using reusable functions that operate on superclasses, and 2) you can’t easily create “template” instances of a class that have only a few populated fields.
An example: construct both
Employee
s andCustomer
s using common code for their common fields (they’d likely be subclasses ofsealed abstract Person
, but that doesn’t help us).Today, you’d wind up with a bunch of code duplication:
with mutability (non-Ceylonic):
and with flexible named argument spreading, you might have:
I think the last example provides all of the benefits of Ceylon’s null safety and immutability, and the code reuse benefits currently only available with Java bean style mutability. This would be even better with #3851.
I tend to think that is an acceptable risk, and would only affect cases where the type’s new attribute has the same name and type as a defaulted parameter, and an argument for that parameter is not otherwise provided.
Person { *person; birthYear = 1980; }
does not resolve inheritance issues (this almost clone feature has the sames issues as clone 260while
create an instance of class Person.
In Java, i use the builder pattern with a cloneBuilder method that return a builder instance with copies values of “this” ; but it’s very heavy and verbose style.