class Example {
Str doStuff() {
if (someCondition)
return moarStuff()
return otherStuff()
}
Str moarStuff() { "6" }
Str otherStuff() { "9" }
}
And I decide doStuff() should return an Int, so I update the class:
class Example {
Int doStuff() {
if (someCondition)
return moarStuff()
return otherStuff()
}
Int moarStuff() { 6 }
Int otherStuff() { 9 }
}
Cool, that was easy, just a minor change to the return types.
But then I realise the return value isn't used at all, so I decide to make doStuff() return Void:
class Example {
Void doStuff() {
if (someCondition) {
moarStuff()
return
}
otherStuff()
}
Void moarStuff() { /* wotever */ }
Void otherStuff() { /* wotever */ }
}
Wow! That was a BIG code change! I had to re-jig my if statement, introduce code blocks and delete return keywords! All because I can't return Void.
So, if Void is an object, why can't we return it? (A rhetorical question.)
I'm not asking to be able to create instances of Void and return them, but it would be nice to chain Void return values. That way, in the examples above, changing the return type to Void would be the same as changing it to Int (Well, as far as doStuff() is concerned.)
Above is a small example, but a while ago I did such a change in BedSheet where I was using a chain of command / pipeline pattern and the re-factor ended up being a lot bigger than I wanted.
matthewWed 11 Mar 2015
Not sure about your specific use case, but I've often thought it would be cool if we could return/assign Void. If we could, we'd be a little closer to making all statements be expressions, which would yield some pretty expressive constructs.
I've frequently wanted to be able to do something like this.
a := if (condition) { 6 } // else Void/null?
val := switch(foo) {
case 1: "bar"
case 2: "baz"
default: null // Void?
}
Your example presumably has a larger ripple effect. If you were returning an Int and now you are returning Void, what about all the code that was assigning the returning value or comparing against it?
This concept would need some fleshing out for how Void relates to null I think, but maybe this is for another thread?
SlimerDudeThu 12 Mar 2015
Hi Matthew,
If you were returning an Int and now you are returning Void, what about all the code that was assigning the returning value or comparing against it?
Yes, the leaf methods that return a value would have to change (as they do in the example) but if the values aren't used (which is why I'm returning Void) then there's nothing comparing it.
In all, changing a return value to Void still requires a lot more effort and code changes than simply changing it to another other object.
When I write:
return otherStuff()
What I am saying is, "Return what otherStuff() is returning". That statement shouldn't care what otherStuff() returns, be it Void or some other object, it's just passing the buck.
I just think it'd be neat if the compiler let you chain together methods that return Void.
Making Void a Real Object
I'm all for making Void a true object. But one with a private ctor that you can't instantiate.
It would make reflection a lot cleaner. Currently Void methods return null... Err?? No! Void methods should return Void instances!
Obviously this would be a big, compatibility breaking, change. An option for Fantom 1.1 maybe?
Void vs Null vs Undefined
What you want is similar to undefined in Javascript which causes a lot of confusion. Granted, that confusion is mainly due to implicit coercion, but I'm still not keen. Given Fantom is compiled and strongly typed - there is no undefined!
In your examples I would just assign a default value first.
a := null
a = if (condition) { 6 }
But yes, statements as expressions can be cool. It also allows you to write some pretty convoluted and evil code!
brianThu 12 Mar 2015
I actually have been noodling on a small tweak to the language to allow this:
Void foo()
{
if (x) return bar
}
Void bar() {}
Right now you have to do this:
Void foo()
{
if (x) { bar; return }
}
That use case seems to come up a lot, so would be nice to fix. I don't really want to take it much further, really just limit to that you can use return any type inside a Void method.
SlimerDudeThu 12 Mar 2015
That would be awesome and is exactly what I'm after!
:D
Yeah, it does come up quite a bit!
elyashivFri 13 Mar 2015
I guess changing the semantics to allow a call to a allow something like this:
Void foo()
{
return bar
}
Void bar() {...}
shouldn't be too complex, and will allow the wanted functionality.
SlimerDudeFri 13 Mar 2015
shouldn't be too complex
Guess we'll just have to wait and see how Brian's noodling comes along!
brianTue 23 Jun 2015
Ticket promoted to #2403 and assigned to brian
brianTue 23 Jun 2015
Ticket resolved in 1.0.68
Fix compiler to allow return inside a Void method to optionally include an expression of any type.
So now this is legal Fantom:
Void foo(Int x)
{
if (x == 0) return bar
if (x == 1) return baz
}
Void bar() {}
Str baz() { "baz" }
SlimerDudeTue 23 Jun 2015
Cool. Interesting that Void methods may now return any value. My thinking only went as far as returning Void and keeping the type checking, meaning you'd have to do this:
Void foo(Int x)
{
if (x == 0) return bar
if (x == 1) return
}
Void bar() {}
Str baz() { "baz" }
But I can't envision return baz doing any harm, so... sweet!
brianWed 1 Jul 2015
Yeah its been really nice, used it already a bunch
SlimerDude Wed 11 Mar 2015
Suppose I have this class:
And I decide
doStuff()
should return anInt
, so I update the class:Cool, that was easy, just a minor change to the return types.
But then I realise the return value isn't used at all, so I decide to make
doStuff()
returnVoid
:Wow! That was a BIG code change! I had to re-jig my
if
statement, introduce code blocks and deletereturn
keywords! All because I can't returnVoid
.So, if
Void
is an object, why can't we return it? (A rhetorical question.)I'm not asking to be able to create instances of
Void
and return them, but it would be nice to chainVoid
return values. That way, in the examples above, changing the return type toVoid
would be the same as changing it toInt
(Well, as far asdoStuff()
is concerned.)Above is a small example, but a while ago I did such a change in BedSheet where I was using a chain of command / pipeline pattern and the re-factor ended up being a lot bigger than I wanted.
matthew Wed 11 Mar 2015
Not sure about your specific use case, but I've often thought it would be cool if we could return/assign
Void
. If we could, we'd be a little closer to making all statements be expressions, which would yield some pretty expressive constructs.I've frequently wanted to be able to do something like this.
Your example presumably has a larger ripple effect. If you were returning an
Int
and now you are returningVoid
, what about all the code that was assigning the returning value or comparing against it?This concept would need some fleshing out for how Void relates to
null
I think, but maybe this is for another thread?SlimerDude Thu 12 Mar 2015
Hi Matthew,
Yes, the leaf methods that return a value would have to change (as they do in the example) but if the values aren't used (which is why I'm returning
Void
) then there's nothing comparing it.In all, changing a return value to
Void
still requires a lot more effort and code changes than simply changing it to another other object.When I write:
What I am saying is, "Return what
otherStuff()
is returning". That statement shouldn't care whatotherStuff()
returns, be itVoid
or some other object, it's just passing the buck.I just think it'd be neat if the compiler let you chain together methods that return
Void
.Making Void a Real Object
I'm all for making
Void
a true object. But one with a privatector
that you can't instantiate.It would make reflection a lot cleaner. Currently
Void
methods returnnull
... Err?? No!Void
methods should returnVoid
instances!Obviously this would be a big, compatibility breaking, change. An option for Fantom 1.1 maybe?
Void vs Null vs Undefined
What you want is similar to
undefined
in Javascript which causes a lot of confusion. Granted, that confusion is mainly due to implicit coercion, but I'm still not keen. Given Fantom is compiled and strongly typed - there is no undefined!In your examples I would just assign a default value first.
But yes, statements as expressions can be cool. It also allows you to write some pretty convoluted and evil code!
brian Thu 12 Mar 2015
I actually have been noodling on a small tweak to the language to allow this:
Right now you have to do this:
That use case seems to come up a lot, so would be nice to fix. I don't really want to take it much further, really just limit to that you can use return any type inside a Void method.
SlimerDude Thu 12 Mar 2015
That would be awesome and is exactly what I'm after!
:D
Yeah, it does come up quite a bit!
elyashiv Fri 13 Mar 2015
I guess changing the semantics to allow a call to a allow something like this:
shouldn't be too complex, and will allow the wanted functionality.
SlimerDude Fri 13 Mar 2015
Guess we'll just have to wait and see how Brian's noodling comes along!
brian Tue 23 Jun 2015
Ticket promoted to #2403 and assigned to brian
brian Tue 23 Jun 2015
Ticket resolved in 1.0.68
Fix compiler to allow return inside a Void method to optionally include an expression of any type.
So now this is legal Fantom:
SlimerDude Tue 23 Jun 2015
Cool. Interesting that
Void
methods may now return any value. My thinking only went as far as returningVoid
and keeping the type checking, meaning you'd have to do this:But I can't envision
return baz
doing any harm, so... sweet!brian Wed 1 Jul 2015
Yeah its been really nice, used it already a bunch
Jeremy Criquet Wed 22 Jul 2015
Neat. Now we just need Xored to update F4!