Comma in Objective-C - ios

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++

Related

How to use infix notation in Android properly (Kotlin language)?

I have read Kotlin docs as well as the wikipedia links (https://en.wikipedia.org/wiki/Infix_notation#:~:text=Infix%20notation%20is%20the%20notation,plus%20sign%20in%202%20%2B%202), but unfortunately I am still unable to make use of this notation in my code.
Could someone please let me know, how can I use it?
Before jumping on to the code, let’s look at the rules of it’s usage (From the docs: https://kotlinlang.org/docs/functions.html#infix-notation):
Infix notation must be used with member functions or extension functions
They must have a single parameter
The parameter must not accept variable number of arguments and must have no default value.
Keeping these pointers in mind, you can achieve the following:
fun Int.add(x: Int) = this.plus(x) //This is a simple Extension function without infix notation
infix fun Int.subtract(x: Int) = this.minus(x) //Added infix notation here
fun main() {
val sum = 10.add(20)
println(sum) //prints 30
val sub = 100 subtract 30 //Notice that there is no dot(.) and parenthesis
println(sub) //prints 70
}
This is how we can use infix notations and get rid of the dots(.) and parenthesis and they will work the same.
This increases code readability.

Why are redundant parenthesis not allowed in syntax definitions?

This syntax module is syntactically valid:
module mod1
syntax Empty =
;
And so is this one, which should be an equivalent grammar to the previous one:
module mod2
syntax Empty =
( )
;
(The resulting parser accepts only empty strings.)
Which means that you can make grammars such as this one:
module mod3
syntax EmptyOrKitchen =
( ) | "kitchen"
;
But, the following is not allowed (nested parenthesis):
module mod4
syntax Empty =
(( ))
;
I would have guessed that redundant parenthesis are allowed, since they are allowed in things like expressions, e.g. ((2)) + 2.
This problem came up when working with the data types for internal representation of rascal syntax definitions. The following code will create the same module as in the last example, namely mod4 (modulo some whitespace):
import Grammar;
import lang::rascal::format::Grammar;
str sm1 = definition2rascal(\definition("unknown_main",("the-module":\module("unknown",{},{},grammar({sort("Empty")},(sort("Empty"):prod(sort("Empty"),[
alt({seq([])})
],{})))))));
The problematic part of the data is on its own line - alt({seq([])}). If this code is changed to seq([]), then you get the same syntax module as mod2. If you further delete this whole expression, i.e. so that you get this:
str sm3 =
definition2rascal(\definition("unknown_main",("the-module":\module("unknown",{},{},grammar({sort("Empty")},(sort("Empty"):prod(sort("Empty"),[
], {})))))));
Then you get mod1.
So should such redundant parenthesis by printed by the definition2rascal(...) function? And should it matter with regards to making the resulting module valid or not?
Why they are not allowed is basically we wanted to see if we could do without. There is currently no priority relation between the symbol kinds, so in general there is no need to have a bracket syntax (like you do need to + and * in expressions).
Already the brackets have two different semantics, one () being the epsilon symbol and two (Sym1 Sym2 ...) being a nested sequence. This nested sequence is defined (syntactically) to expect at least two symbols. Now we could without ambiguity introduce a third semantics for the brackets with a single symbol or relax the requirement for sequence... But we reckoned it would be confusing that in one case you would get an extra layer in the resulting parse tree (sequence), while in the other case you would not (ignored superfluous bracket).
More detailed wise, the problem of printing seq([]) is not so much a problem of the meta syntax but rather that the backing abstract notation is more relaxed than the concrete notation (i.e. it is a bigger language or an over-approximation). The parser generator will generate a working parser for seq([]). But, there is no Rascal notation for an empty sequence and I guess the pretty printer should throw an exception.

?: in Objective-C [duplicate]

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.

Can't use #define for convenience [closed]

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;

What can you NOT use an identifier for?

I'm trying to understand what identifiers represent and what they don't represent.
As I understand it, an identifier is a name for a method, a constant, a variable, a class, a package/module. It covers a lot. But what can you not use it for?
Every language differs in terms of what entities/abstractions can or cannot be named and reused in that language.
In most languages, you can't use an identifier for infix arithmetic operations.
For example, plus is an identifier and you can make a function named plus. But write you can write a = b + c;, there's no way to define an operator named plus to make a = b plus c; work because the language grammar simply does not allow an identifier there.
An identifier allows you to assign a name to some data, so that you can reference it later. That is the limit of what identifiers do; you cannot "use" it for anything other than a reference to some data.
That said, there are a lot of implications that come from this, some subtle. For example, in most languages functions are, to some degree or another, considered to be data, and so a function name is an identifier. In languages where functions are values, but not "first-class" values, you can't use an identifier for a function in an place you could use an identifier for something else. In some languages, there will even be separate namespaces for functions and other data, and so what is textually the same identifier might refer to two different things, and they would be distinguished by the context in which they are used.
An example of what you usually (i.e., in most languages) cannot use an identifier for is as a reference to a language keyword. For example, this sort of thing generally can't be done:
let during = while;
during (true) { print("Hello, world."); }
You could say it's used for everything that you'll want to refer to multiple times, or maybe even once (but use it to clarify the referent's purpose).
What can/can't be named differs per language, it's often quite intuitive, IMHO.
An "Anonymous" entity is something which is not named, although referred to somehow.
#!/usr/bin/perl
$subroutine = sub { return "Anonymous subroutine returning this text"; }
In Perl-speak, this is anonymous - the subroutine is not named, but it is referred to by the reference variable $subroutine.
PS: In Perl, the subroutine would be named like this:
sub NAME_HERE {
# some code...
}
Say, in Java your cannot write something like:
Object myIf = if;
myIf (a == b) {
System.out.println("True!");
}
So, you cannot name some code statement, giving it an alias. While in REBOL it is perfectly possible:
myIf: if
myIf a = b [print "True!"]
What can and what can't be named depends on language, as you see.
as its name implifies, an identifier is used to identify something. so for everything that can be identified uniquely, you can use an identifier. But for example a literal (e.g. string literal) is not unique so you can't use an identifier for it. However you can create a variable and assign a string literal to it.
Making soup out them is rather foul.
In languages such as Lisp, an identifier exists in its own right as an symbol, whereas in languages which are not introspective identifiers don't exist in the runtime.
You write a literal identifier/symbol by putting a single quote in front of it:
[1]> 'a
A
You can create a variable and assign a symbol literal to it:
[2]> (setf a 'Hello)
HELLO
[3]> a
HELLO
[4]> (print a)
HELLO
HELLO
You can set two variables to the same symbol
[10]> (setf b a)
HELLO
[11]> b
HELLO
[12]> a
HELLO
[13]> (eq b a)
T
[14]> (eq b 'Hello)
T
Note that the values bound to b and a are the same, and the value is the literal symbol 'Hello
You can bind a function to the symbol
[15]> (defun hello () (print 'hello))
HELLO
and call it:
[16]> (hello)
HELLO
HELLO
In common lisp, the variable binding and the function binding are distinct
[19]> (setf hello 'goodbye)
GOODBYE
[20]> hello
GOODBYE
[21]> (hello)
HELLO
HELLO
but in Scheme or JavaScript the bindings are in the same namespace.
There are many other things you can do with identifiers, if they are reified as symbols. I suspect that someone more knowledgable than me in Lisp will be able to demonstrate any of the things that you 'can't do with identifiers' exist.
But even Lisp can not make identifier soup.
Sort of a left-field thought, but JSON has all those quotations in it to eliminate the danger of a JavaScript keyword messing up the parsing.

Resources