This question already has answers here:
Is this ternary conditional ?: correct (Objective) C syntax?
(4 answers)
Closed 8 years ago.
In this iOS tutorial, there is a line of code with a ? followed by a :. In the context of the comment for the code, I thought it was some sort of ternary operation, however, that's obviously not the syntax for a ternary operator. Is there a name for what is happening in this code with the ?:?
// Initialize the list of weather items if it doesn't exist
NSMutableArray *array = self.xmlWeather[#"weather"] ?: [NSMutableArray array];
It's a GCC extension:
6.7 Conditionals with Omitted Operands
The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
Therefore, the expression
x ? : y
has the value of x if that is nonzero; otherwise, the value of y.
This example is perfectly equivalent to
x ? x : y
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
Related
I am new to F# and I do not understand how a bit shift works in F#.
I tried the command below in fsi.
> 4
- |>((<<<) 1uy);;
The screen shot is as below.
Why is this result 16uy but not 8uy?
Even confused me more when I tried the command below because the result is 48uy...
> 4
- |>((<<<) 3uy);;
Would you somebody describe me how this works?
From the documentation:
Bitwise left-shift operator. The result is the first operand with bits shifted left by the number of bits in the second operand. Bits shifted off the most significant position are not rotated into the least significant position. The least significant bits are padded with zeros. The type of the second argument is int32.
It's been a while since I've used F#, but assuming its operator prefixing works like Haskell's then the way you've used it:
4 |> ((<<<) 1uy)
will apply 1 as the left-hand argument, and 4 as the right-hand argument:
1 <<< 4
Which will be 16.
To get it to equal 8, try removing the parentheses around the operator itself (meaning it won't be prefixed but instead just partially applied with the right-hand argument) to get:
4 |> (<<< 1uy)
and that should give you 8, assuming it's valid F# syntax.
There is one thing which I don't understand about reference modification in Cobol.
The example goes like this:
MOVE VARIABLE(VARIABLE2 +4:2) TO VARIABLE3
Now I do not qutie understand what the "+4:2" references to. Does it mean that the first two signs 4 signs after the target are moved? Meaning if for example VARIABLE (the 1st) is filled with "123456789" and VARIABLE2 contains the 2nd and 3rd position within that variable (so"23"), the target is "23 +4" meaning "789". Then the first two positions in the target (indicated by the ":2") are moved to VARIABLE3. So in the end VARIABLE3 would contain "78".
Am I understanding this right or am I making a false assumption about that instruction?
(VARIABLE2 +4:2) is a syntax error, because the starting position must be an arithmetic expression. There must be a space after the + for this reference modification to be valid. And, VARIABLE2 must be numeric and the expression shall evaluate to an integer.
Once corrected, then 4 is added to the content of VARIABLE2. That is the left-most (or starting position) within VARIABLE1 for the move. 2 characters are moved to VARIABLE3. If VARIABLE3 is longer than two characters, the remaining positions are filled with spaces.
From the 2002 COBOL standard:
8.7.1 Arithmetic operators
There are five binary arithmetic operators and two unary arithmetic operators that may be used in arithmetic expressions. They are represented by specific COBOL characters that shall be preceded by a space and followed by a space except that no space is required between a left parenthesis and a unary operator or between a unary operator and a left parenthesis.
Emphasis added.
I have a set of chars which I define in the TYPE section as:
TAmpls = set of '1'..'9'';
In my function I declare a new variable, in the var section, with type Tampls using:
myAmpls : Tampls;
I then un-assign everything in myAmpls using:
myAMpls := [];
I then find an integer (I'll call it n). If this number is not assigned in my set variable, I want to assign it, for this I have tried using:
if not chr(n) in myAmpls then include(myAmpls,chr(n));
But the compiler throws an error saying:
'Operator not applicable to this operand type'
If I remove the 'not', the code compiles fine, why is this?
I would have thought that whether or not n was already in myAmpls was boolean, so why can't I use 'not'?
Delphi operator precedence is detailed in the documentation. There you will find a table of the operators listing their precedence. I won't reproduce the table here, no least because it's hard to lay out in markdown!
You will also find this text:
An operator with higher precedence is evaluated before an operator with lower precedence, while operators of equal precedence associate to the left.
Your expression is:
not chr(n) in myAmpls
Now, not has higher precedence than in. Which means that not is evaluated first. So the expression is parsed as
(not chr(n)) in myAmpls
And that is a syntax error because not cannot be used with a character operand. You need to apply parens to give the desired meaning to your expression:
not (chr(n) in myAmpls)
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I may have made some syntax mistakes, but I can't understand why my code isn't working:
In top of .m file I wrote:
#define kCountry "Country";
In this case I got red warning from xCode - expected ]
Then in function body:
floatCountries = 74,2;
[[NSUserDefaults standardUserDefaults]setFloat:floatCountries forKey:kCountry];
float test= [[NSUserDefaults standardUserDefaults]floatForKey:kCountry];
NSLog(#"%f", test);
In that one - expected expression.
That may sound a bit stupid, but I want to simplify my code and use this, please help me! :)
Remove the semi-colon from the end of the define and add the '#':
#define kCountry #"Country"
Use:
#define kCountry #"Country"
You added a semicolon at the end.
And as this will be replaced for string value, you need to put #
To explain why this didn't work:
The semicolon
#define kCountry "Country";
In this case i got red warning from xCode - expected ]
There's no such thing as a “red warning”. Warnings are yellow; errors are red.
(Unless you turn on “Treat Warnings as Errors”; then, in a sense, all the warnings are red—because then they're errors.)
Anyway.
Preprocessor directives such as #define do not require a semicolon. If you include one, it becomes part of the directive.
The preprocessor replaces any macro with whatever you defined it as. In this case, you defined a macro named “kCountry” with the value “"Country;”. Note that the semicolon is part of the value—the directive ends at the end of the line, not at a semicolon.
Thus, when you go to use the macro:
[[NSUserDefaults standardUserDefaults]setFloat:floatCountries forKey:kCountry];
float test= [[NSUserDefaults standardUserDefaults]floatForKey:kCountry];
The preprocessor replaces the macro as follows:
[[NSUserDefaults standardUserDefaults]setFloat:floatCountries forKey:"Country";];
float test= [[NSUserDefaults standardUserDefaults]floatForKey:"Country";];
A semicolon can't go inside a statement; it must come after. Thus, the above statements are invalid.
The fix is to remove the semicolon from the line where you #defined the macro, so that the semicolon does not appear in the output:
[[NSUserDefaults standardUserDefaults]setFloat:floatCountries forKey:"Country"];
float test= [[NSUserDefaults standardUserDefaults]floatForKey:"Country"];
By the way, Xcode has an option in its Jump Bar to show you the complete preprocessed version of the code, as the compiler will see it. That can be handy when investigating macro problems.
So, that's one of the problems. The other one was…
The kind of string you used
"Country" is a C string. It's only usable with the C string and stdio libraries (including the functions printf, strcat, etc.) and various other APIs that require C strings (such as +[NSString stringWithUTF8String:] and +[NSString stringWithCString:encoding:]).
NSUserDefaults, like everything else in Cocoa that requires a string, requires a Cocoa string object—an NSString. The syntax for an NSString literal is the same, but with an # in front of it: #"Country".
Hence the version that works:
#define kCountry #"Country"
Which produces the preprocessed output:
[[NSUserDefaults standardUserDefaults]setFloat:floatCountries forKey:#"Country"];
float test= [[NSUserDefaults standardUserDefaults]floatForKey:#"Country"];
With no syntax errors and the right kind of string in both places, this is the version that will work.
Oh, and, as Anoop Vaidya already pointed out:
The number syntax
You tried to assign a number to a variable, but I think you'll find a different number there than you were expecting.
floatCountries = 74,2;
If you print the value of this variable with a statement such as:
NSLog(#"%f", floatCountries);
You'll find that the output is 2.0.
C has an operator called the comma operator, and it is simply x, y, where x and y can be any expression (ideally of types that are compatible with each other—e.g., both numbers).
The comma operator evaluates first the left-side expression, then the right-side expression, and itself evaluates to the right-side expression.
74,2 evaluates first the expression 74, and then the expression 2, and then evaluates to 2. Thus, you assign 2 (an int, which is converted automatically as needed) to the variable.
It may seem kind of silly to use this with literal numbers, and it is. The comma operator exists to be used with expressions that have side effects, such as expressions involving the ++ and -- operators.
Use of the comma operator is generally discouraged, because the resulting code is unclear: as a rule, each line should do one thing, but a line such as x = ++y, --z; does three things.
Nonetheless, it is valid, as you found. You should get a warning, though, if you have the “unused value” warning turned on (as you should), because half of the expression is, in fact, unused—you drop the 74 on the floor. Harmless, but a symptom that this isn't what you meant to do.
What you want is:
floatCountries = 74.2;
I've just seen this in another question and thought the comma must be a typo
[controller release], controller = nil;
I'm using ARC so didn't use release, but I tested this myself the following code and found that it compiled and ran fine.
NSObject *a = [NSObject new];
[a copy], a=nil;
I was under the impression that the comma was only used for separating lists and multiple assignments of the same type:
NSArray *a = #[#"1", #"two", /*etc*/];
int a, b, c, d;
Actual Question:
Is it as simple as: The comma can be used to separate commands? Are there any other rules?
The comma operator is a C-language construct.
From Wikipedia:
In the C and C++ programming languages, the comma operator
(represented by the token ,) is a binary operator that evaluates its
first operand and discards the result, and then evaluates the second
operand and returns this value (and type). The comma operator has the
lowest precedence of any C operator, and acts as a sequence point. The
use of the comma token as an operator is distinct from its use in
function calls and definitions, variable declarations, enum
declarations, and similar constructs, where it acts as a separator.
In your code the comma is used as a replacement for the semi-colon. It doesn't make a difference if you use , or ; in your examples.
Refer to this question for details: Effect of using a comma instead of a semi-colon in C and C++