Ever since the introduction of with blocks and constructors, there has been one pattern I have repeatedly run into. Take for instance the (broken) code:
class Person
{
new make(|This| f) { f(this) }
Str lastName
Str firstName
Int age
override Str toStr() { "$firstName $lastName (age $age)" }
static Void main()
{
me := Person
{
firstName = "Michael"
lastName = "Maloney"
age = 24
}
echo(me)
}
}
The compiler doesn't allow this because y and z are never set in the constructor. They are set in a with block provided to the constructor, and the extra level of indirection shields them from being seen.
You end up having to choose between three really bad options:
Set defaults to every field in the constructor before f(this)
Write a constructor that doesn't take an it block.
Make every field nullable
The first option is incredibly tedious boilerplate.
The second option defeats the with blocks.
The third option is usually the one I choose, but it's not much better. It defeats non-nullable typing. Adding the ? to the type on every field is also tedious.
My proposal, then, is to allow the programmer to automatically create a "smart" it block constructor. It would effectively be a macro for the following.
new make(|This| f)
{
f(this)
<<assert every field in this has been set or has a default>>
}
I'm thinking we would give it a special syntax. Maybe something like:
class Person
{
new it make
Str lastName
Str firstName
Int age
...
}
Personally, I've run into this pattern more times than I can count. It's terribly annoying every time I do. I think something like this would help for lightweight data structures where I don't care to think about the best way to expose the constructor.
Plus, it reduces the amount of "swearing" in Fantom: f(this) :P
It will let you compile code without explicitly setting the non-nullable fields, but will insert auto-generated checks which will throw a Runtime exception is the it-block didn't set every non-nullable field.
tacticsWed 3 Mar 2010
Ah, indeed it is.
lbertrandThu 4 Mar 2010
I have started writing code in Fantom recently and have been beaten by all these issues, either on constructor or on serialization... Especially when we add to this the use of const fields...
Will the solution also solve the fact that we do not set const fields directly in constructors or from serialization?
tactics Wed 3 Mar 2010
Ever since the introduction of with blocks and constructors, there has been one pattern I have repeatedly run into. Take for instance the (broken) code:
The compiler doesn't allow this because y and z are never set in the constructor. They are set in a with block provided to the constructor, and the extra level of indirection shields them from being seen.
You end up having to choose between three really bad options:
f(this)
The first option is incredibly tedious boilerplate.
The second option defeats the with blocks.
The third option is usually the one I choose, but it's not much better. It defeats non-nullable typing. Adding the
?
to the type on every field is also tedious.My proposal, then, is to allow the programmer to automatically create a "smart" it block constructor. It would effectively be a macro for the following.
I'm thinking we would give it a special syntax. Maybe something like:
Personally, I've run into this pattern more times than I can count. It's terribly annoying every time I do. I think something like this would help for lightweight data structures where I don't care to think about the best way to expose the constructor.
Plus, it reduces the amount of "swearing" in Fantom:
f(this)
:PWhat do you all think?
brian Wed 3 Mar 2010
This is what ticket #832 is designed to solve.
It will let you compile code without explicitly setting the non-nullable fields, but will insert auto-generated checks which will throw a Runtime exception is the it-block didn't set every non-nullable field.
tactics Wed 3 Mar 2010
Ah, indeed it is.
lbertrand Thu 4 Mar 2010
I have started writing code in Fantom recently and have been beaten by all these issues, either on constructor or on serialization... Especially when we add to this the use of const fields...
Will the solution also solve the fact that we do not set const fields directly in constructors or from serialization?