I am not sure this is possible, but it will be great.
In Kotlin you can do:
var x = if (condition) {
value1
} else {
value2
}
And yes in Dart we can use x = aaa ? bbb : ccc; but we can't put any complex logic here (as well as use few branches)
Live example form code which I am writing right now
var entrantsValueText = '';
if (f.stakeFrom > 0 && f.stakeTo > 0) {
entrantsValueText = '$curSymbol ${f.stakeFrom}-${f.stakeTo}';
} else if (f.stakeFrom > 0) {
entrantsValueText = '>$curSymbol${f.stakeFrom}';
} else {
entrantsValueText = '<$curSymbol${f.stakeTo}';
}
will be MUCH more shorter
var entrantsValueText = if (f.stakeFrom > 0 && f.stakeTo > 0) {
'$curSymbol ${f.stakeFrom}-${f.stakeTo}';
} else if (f.stakeFrom > 0) {
'>$curSymbol${f.stakeFrom}';
} else {
'<$curSymbol${f.stakeTo}';
}
I would like to see in Dart all nice features from Kotlin like when, let, with and many more. Should I create an issue for each of them? Or this is totally impossibly due the language architecture?
I know Kotlin transforms all that code inside and generates needed properties, fields and functions, but Dart don't behave like this.
Maybe this is possible to create some lib / plugin for that? If somebody will teach me how to do it and will pay for it I would love to spend 1 month for that, for example =)
If that would be possible then I not far is losing requirement of empty braces for Function:
callBlock((){
// some logic here
});
and replace it with
callBlock({
});
or even:
callBlock {
};
It's definitely possible to introduce an expression-level if operator, but if it just has expressions as branches, then it's no more powerful than the existing conditonal operator ...?...:....
In general, you can usually take any statement-level control flow operation and change its sub-statements to sub-expressions and get an expression-level control flow operation. You have to handle the cases where no statement would be executed, because expressions always need a value (so, no if-expression without an else branch, maybe no while loop, only a do-while, or similar restrictions).
The try/catch/finally construct would work fairly well as an expression, but you might need to make rethrow an expression as well.
However, you ask for "complex logic" in the if expression. Would that mean statements?
If so, it's a much different feature: A "statement expression" where you can execute statements and then evaluate to a value.
The current approach for those is usually to have an immediately applied function expression:
var x = () {
if (...) {
....
return v1;
} else if (...) {
return v2;
}
return v3;
}();
Being inside another function means that you cannot do non-local control flow (you can't break to a target in the outer code, or return from the outer function.
If we had actual statement expressions, say a syntax like: { statement*; => expression; }, then you could perhaps write:
var x = {
if (...) {
....
=> v1
} else if (...) {
=> v2
}
=> v3
}()
(For nested such expressions, we might need to be able to label the block and emit a value from a labeled containing expression block).
The real complication here is for compilers, where any sub-expression can now do control-flow operations like return, break, or continue. That could complicate compilers.
It's possible, but it may also be a risk to readability. Currently understanding control flow is reasonably simple - control flow is only in statements, expressions cannot change that. If an expression can do control flow, then we can get code like:
var x = foo(someTest ? value : { return result; })
where the return is a return from the surrounding function. Much harder to reason about.
@lrhn
Thanks for detailed answer!
but if it just has expressions as branches, then it's no more powerful than the existing conditonal operator ...?...:....
Probably I said it wrong. I mean having 2+ branches IS the complex logic.
I don't need make any statements inside, only need more then two branches.
Yes, in Kotlin (and in you further example) you can put logic inside and then put the return value in the last line, but this is not good to write like that. If you make var x = if {...} best practice (as we all understand) is just to make return inside, no more, to keep things clear.
var x = {
if (...) {
....
=> v1
} else if (...) {
=> v2
}
=> v3
}()
That code is very close to what I need!
But ideally it should be
var x = if (...) {
....
v1
} else if (...) {
v2
} else {
v3
}
What is important:
return or => to return a value, just put value to the last line{}()else branchThe real complication here is for compilers, where any sub-expression can now do control-flow operations like return, break, or continue. That could complicate compilers.
Yes
It's possible, but it may also be a risk to readability. Currently understanding control flow is reasonably simple - control flow is only in statements, expressions cannot change that. If an expression can do control flow, then we can get code like:
In Kotlin guys solved it that way:
fun foo() {
listOf(1, 2, 3, 4, 5).forEach {
if (it == 3) return@forEach // local return to the caller of the lambda, i.e. the forEach loop
print(it)
}
print(" done with implicit label")
}
So they are add @anything when you are returning from nested scope, and (as far as I know) you can NOT put there pure return - it will show an error.
Also when is another amazing things
var x = when {
condition1 => a
condition2 => b
is String => d
in 1..10 => e
else => f
}
It works like if/else, but with super short syntax
try? else?
var? a = try valueOrException(); // null if error
var a = valueOrException() else value;
Most helpful comment
Also
whenis another amazing thingsIt works like if/else, but with super short syntax