Why the following code works fine with if/else and not with ternary operator?
ListView(
children: [
// Commented code not working
// isLogged ? ...loggedRows(context) : loginRow(context),
// Working code
if (isLogged)
...loggedRows(context)
else
loginRow(context),
ListTile(...),
ListTile(...),
])
loggedRows and loginRow methods:
ListTile loginRow(BuildContext context) {
return ListTile(...)
}
List<ListTile> loggedRows(BuildContext context) {
return [ListTile(...), ListTile(...)];
}
I try to show different ListTiles depending on if the user is logged in or not, and it works perfectly using if/else but when I try to do the same with ternary operator I get error.
I tried several parenthesis combinations, but none of them worked for me.
Using the simplest mode, as in commented code, I get 3 errors on Dart Analysis:
Expected to find ']'.
Expected to find '.'.
Expected an identifier.
Shouldn't behave the same ternary operator and if/else?
Why do I get these errors?
Does anyone know which should be the right syntax to use ternary operator?
Your use of the ternary operator doesn't work because each of the "then" and "else" operands (and therefore the result of the ternary operator itself) must evaluate to an expression, and the spread operator (...) doesn't produce an expression. The spread operator (and collection-if and collection-for) instead evaluates to one or more collection elements. (I highly recommend reading Bob Nystrom's article that discusses the design of these language features.)
Your use of the ternary operator would work if you moved the spread operator out:
...(isLogged ? loggedRows(context) : [loginRow(context)]),
although that is more awkward since it creates an extra List if isLogged is false. Using collection-if instead would be much more appropriate for this usage.
Related
It appears that in Game Maker 8, 8.1, and Studio (at least) that the assignment operator = is identical to the comparison operator ==. For example, these lines do the same thing:
if (a=b) {}
if (a==b) {}
Is this function meant to be friendly to new users? Should I continue using == or switch to =? Or does it make no difference?
P.S. Things like incrementing still work with = similarly to ==:
if a=b++{} //b is still incremented, but a does not change
This functionality was left over from previous versions as stated in the GameMaker help file.
"However, this is a legacy from old GameMaker versions and you should use the == operators for comparing and = for assigning."
It would be good practice for you to use == when comparing as that is what it is designed for. Also, if you were to move onto another languages like PHP, using the = operator would actually initialize the variable in the if statement. This could give you quite a headache if you are in the habit of using the single = operator.
Please help me reason out for the error I am getting with this statement, in Linux environment.
p_pAphErrorMessage->getSvc()?l_AphUpdateMessage->setSvc(p_pAphErrorMessage->getSvc()):0;
p_pAphErrorMessage->getObj()?l_AphUpdateMessage->setObj(p_pAphErrorMessage->getObj()):0;
This code is successfully compiled in windows but its giving error in Linux enviroment.
src/aph.cpp:7320: error: âl_AphUpdateMessage->AphMessage::setSvc(((AphUpdateMessage*)p_pAphErrorMessage)->AphUpdateMessage::<anonymous>.AphFidValuesMessage::<anonymous>.AphMessage::getSvc())â has type âvoidâ and is not a throw-expression
src/aph.cpp:7321: error: âl_AphUpdateMessage->AphMessage::setObj(((AphUpdateMessage*)p_pAphErrorMessage)->AphUpdateMessage::<anonymous>.AphFidValuesMessage::<anonymous>.AphMessage::getObj())â has type âvoidâ and is not a throw-expression
I investigated this a bit and suspect returning 0; could be the reason for it.
Can we use conditional operator in such a way to use it just for if not for else, eg,
c= a?a:/*DO NOTHING*/;
But, this way I am not getting any success in compilation. Any other recommended way to achieve it.
You have to cast the zero to void, like
condition ? expression : (void) 0;
The reason is that both the setSvc and setObj are declared as returning void (as seen in the error messages). This means the result of the expression where you call them is nothing. But the other "false" expression is an expression with a value. So the ternary expression have one branch that doesn't return a value and one branch that does return a value, which is not allowed. Casting the "false" expression to void makes both branches the same.
No, you can't use the ternary operator this way, as it operates with 3 arguments:
expression1 : expression2 ? expression3
But you always can do:
c = a ? a : c;
Is
--foo++;
a valid statement in C? (Will it compile/run) And is there any practical application for this?
Sorry for changing the question in an edit but I found something out.
According to my C++ compiler (Visual Studio 2010):
--++foo;
is a valid command but
foo--++;
is not. Is there any reason for this?
No, it is not valid because the result of the increment / decrement operators is not a lvalue.
EDIT: the OP edited his question by adding two more examples . So here we go, for the same reason:
--++foo;
--foo++;
foo--++;
are all invalid expression statements because the result of increment / decrement operators is not a lvalue. A compiler could extend the language and accepts these expressions, but a strictly conforming program cannot contain any of these expressions.
As this is a C expression it should follow some cascading evaluation steps to find out result.
your expressions are
--++foo;
ok lets evaluate this
first step:-
++foo;
must be evaluated to proceed
it is some how pre increment so foo become foo+1 .
then assignment happen
that is this evaluate to foo=foo+1;
and value of foo return for assignment to a variable(if nothing present then ignored).
so now our expression is like below
--(++foo); evaluated to
--(a constant value);//result of foo+1
again the statement evaluated like
a constant value=constant_valu+1;//right part is ok but left part is not a variable
as left side of assignment operator is not a variablle and raise an error.
so now no valid operand for -- /decrement operator So lvalue required error
When answering this question I made some research which really confuses me.
I noticed that two ifstreams that succesfully open are not equal but two ifstreams that fail are.
At first i checked cplusplus.com. The operator ! returns the status of the badbit and failbit. I think that the opposite of this would still be to return the status of these two bits, but flipped.
Wrong, because two succesful calls are not equal.
So then I figured it was an operator bool somewhere that would return something. So I tried to backtrack from ifstream and found the istream::operator bool(), which is returning _Ok.
Still wrong however, this doesn't seem to be called at all (and couldn't be, since the two successful calls are still not equal).
So I changed my approach and checked the disassembly from Visual Studio. And what do I find?
if (file0 != file1) { doesn't call the operator bool(), but rather the operator void* () (or really __imp_std::ios_base::operator void *).
So the questions I have are..
Shouldn't any operator bool () found be called before trying to casting it to pointer values?
Is it some operator bool() I missed that in turn is calling the operator void* ?
Is this some optimizing that I don't understand?
Or am I completely wrong in that C++ actually thinks that void* is a better match than bool in this comparison?
1.) You cannot overload multiple times but with different return types.
2.) Yes, operator! returns the badbit/failbit, but operator! is something entirely different from operator!=, which is the one you are using.
Solved: I figured out a clean way to do it with setjmp()/longjmp(), requiring only a minimal wrapper like:
int jump(jmp_buf j, int i) { longjmp(j, i); return 0; }
This allows jump() to be used in conditional expressions. So now the code:
if (A == 0) return;
output << "Nonzero.\n";
Is correctly translated to:
return
((A == 0) && jump(caller, 1)),
(output << "Nonzero.\n"),
0;
Where caller is a jmp_buf back to the point of invocation in the calling function. Clean, simple, and efficient to a degree that is far less implementation-defined than exceptions. Thank you for your help!
Is there a way to emulate the use of flow-control constructs in the middle of an expression? Is it possible, in a comma-delimited expression x, y, for y to cause a return?
Edit: I'm working on a compiler for something rather similar to a functional language, and the target language is C++. Everything is an expression in the source language, and the sanest, simplest translation to the destination language leaves as many things expressions as possible. Basically, semicolons in the target language become C++ commas. In-language flow-control constructs have presented no problems thus far; it's only return. I just need a way to prematurely exit a comma-delimited expression, and I'd prefer not to use exceptions unless someone can show me that they don't have excessive overhead in this situation.
The problem of course is that most flow-control constructs are not legal expressions in C++. The only solution I've found so far is something like this:
try {
return
x(), // x();
(1 ? throw Return(0) : 0); // return 0;
} catch (Return& ret) {
return ref.value;
}
The return statement is always there (in the event that a Return construct is not reached), and as such the throw has to be wrapped in ?: to get the compiler to shut up about its void result being used in an expression.
I would really like to avoid using exceptions for flow control, unless in this case it can be shown that no particular overhead is incurred; does throwing an exception cause unwinding or anything here? This code needs to run with reasonable efficiency. I just need a function-level equivalent of exit().
You may want to research cfront, which is a program from the late 80's/early 90's that translated C++ into C (no templates or exceptions back then), because there were few, if any, native C++ compilers.
The way it handled inline functions is very similar to what you are trying to do: lots of trinary (?:) operators, commas, and parentheses. However, it could not convert an inline function with control flow more complex than if/then, e.g. a for or while loop, to an expression, and would have to implement that function as non-inline.
The only way to "prematurely exit a comma-delimited expression" would be with the trinary operator and parentheses. For example:
(
first thing,
second thing,
test expression?
(
next thing if successful,
another thing,
return value
)
:( // How often can you use an emoticon as an operator, anyway?
something to do if unsuccessful,
more cleanup,
return value
)
)
If the compiler doesn't short-circuit the then and else clauses of the trinary operator, you're out of luck.
what for? C++ is imperative language. Expressions there are just expressions. Use functional languages if you want to do everything as expressions/functions.
I get the feeling you just have a functional specification (in terms of pre- and post-conditions, for example) of how the translation process must be performed. Since C++ is not a declarative language, but an imperative one, you have to derive yourself a procedural implementation of that translation process before you start coding. And, as you have already seen, it's not as simple as concatenating all your original expressions using commas.
What you are trying to do is have the C++ compiler do your work for you. This won't work, since C++ is not a declarative language, and its compiler won't dynamically try to interpret what you meant from your specifications. And, if this could work, C++ would have to be just another dynamic declarative language, and you would be probably targeting another static language.
A hint on what could work: Analyze every original expression completely (with its possible side-effects) and only then output code. If your expression is compound (it has sub-expressions), don't output anything until you have analyzed the bigger expression.