compare blocks and functions in objective C - objective-c

As I am learning objective C, my understanding is new and incomplete. The concept of a block is very similar to a function. They even look almost identical:
FUNCTION named 'multiply'
#import <Foundation/Foundation.h>
int multiply (int x, int y)
{
return x * y;
}
int main(int argc, char *argv[]) {
#autoreleasepool {
int result = multiply(7, 4); // Result is 28.
NSLog(#"this is the result %u",result);
}
}
BLOCK named 'Multiply'
#import <Foundation/Foundation.h>
int (^Multiply)(int, int) = ^(int num1, int num2) {
return num1 * num2;
};
int main(int argc, char *argv[]) {
#autoreleasepool {
int result = Multiply(7, 4); // Result is 28.
NSLog(#"this is the result %u",result);
}
}
I found various statements on the web like:
"Blocks are implemented as Objective-C objects, except they can be put on the stack, so they don't necessarily have to be malloc'd (if you retain a reference to a block, it will be copied onto the heap, though). "
Ray Wenderlich says:
"Blocks are first-class functions"
I have no clue what all this means. My example shows that the same thing is accomplished as a block or a function. Can someone show an example where blocks can do something functions cannot? or vice versa?
Or is it something more subtle, like the way the variable 'result' is handled in memory?
or is one faster/safer?
Can either of them be used as a method in a class definition?
Thank you.

Blocks are Objective-C objects, and functions aren't. In practice, this means you can pass around a block from one piece of code to another like so:
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(#"Hello, %#", name);
}];
In C, you can achieve similar effects by passing around pointers to functions. The main difference between doing this and using blocks, however, is that blocks can capture values. For instance, in the example above, if we wanted to use a variable greeting:
NSString *greeting = #"Hello";
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingBlock:^(id name, NSUInteger idx, BOOL *stop) {
NSLog(#"%#, %#", greeting, name);
}];
In this example, the compiler can see that the block depends on the local variable greeting and will "capture" the value of greeting and store it along with the block (in this case, that means retaining and storing a pointer to an NSString). Wherever the block ends up getting used (in this case, within the implementation of [NSArray -enumerateObjectsUsingBlock:]), it will have access to the greetings variable as it was at the time the block was declared. This lets you use any local variables in the scope of your block without having to worry about passing them into the block.
To do the same using function pointers in C, greeting would have to be passed in as a variable. However, this can't happen because the caller (in this case, NSArray) can't know (especially at compile time) exactly which arguments it has to pass to your function. Even if it did, you'd need to somehow pass the value of greeting to NSArray, along with every other local variable you wanted to use, which would get hairy really quickly:
void greet(NSString *greeting, NSString *name) {
NSLog(#"%#, %#", greeting, name);
}
// NSArray couldn't actually implement this
NSString *greeting = #"Hello";
NSArray *names = #[#"Bob", #"Alice"];
[names enumerateObjectsUsingFunction:greet withGreeting:greeting];

Blocks are closures -- they can capture local variables from the surrounding scope. This is the big difference between blocks (and anonymous functions in other modern languages) and functions in C.
Here's an example of a higher-order function, makeAdder, which creates and returns an "adder", a function which adds a certain base number to its argument. This base number is set by the argument to makeAdder. So makeAdder can return different "adders" with different behavior:
typedef int (^IntFunc)(int);
IntFunc makeAdder(int x) {
return ^(int y) { return x + y; }
}
IntFunc adder3 = makeAdder(3);
IntFund adder5 = makeAdder(5);
adder3(4); // returns 7
adder5(4); // returns 9
adder3(2); // returns 5
This would not be possible to do with function pointers in C, because each function pointer must point to an actual function in the code, of which there is a finite number fixed at compile time, and each function's behavior is fixed at compile time. So the ability to create a virtually unlimited number of potential "adders" depending on a value at runtime, like makeAdder does, is not possible. You would instead need to create a structure to hold the state.
A block which does not capture local variables from the surrounding scope, like in your example, is not much different from a plain function, aside from the type.

Related

Printing Current Method in Objective-C

How do I print the name of the method I am in, in Objective-C?
In Java/C# I could do this using reflection. Is similar possible with Objective-C?
For just printing method name, use
NSLog(#"%#", NSStringFromSelector(_cmd));
To printing method arguments is a complex task.
every message in ObjectiveC is converted to objMsgSend (id self, SEL, arg0...)
We need to walk through stack, and print them out, as we see after _cmd + sizeof(SEL) will give us address to arg0 (but the size and type for arg0 is unknown).
Method method = class_getInstanceMethod([self class], _cmd);
unsigned nargs = method_getNumberOfArguments(method);
void *start = _cmd;
for(unsigned i = 0; i< nargs ; i++) {
char *argtype = method_copyArgumentType(method, i);
//find arg size from argtype
// walk stack given arg zie
free(argtype);
}
Basic implementations should look like this.
So if the arguments are objects, that will be great (as we know the size of argument are 32/64 bit). Otherwise we need to do type encoding, and move cursor by argument's size. Have look https://github.com/holtwick/HOLog , that does exactly what you want, but it works under Simulator only.

C: Double Pointers and Objective-C NSError Double Pointers Usage

I happened to stumble upon posts here on SO regarding the double star (**) usage with NSError. Decided to dig it a little deeper, which led me revisiting C.
I have already read many posts here (not a duplicate here) on NSError and I understand why they do so.
So, I decided to write a little snippet in the IDE (Xcode) to see it myself in action.
int a = 10;
int b = 20;
int *c = &a;
int *d = &b;
int **e = &d;
NSLog(#"Before: a is: %d b is: %d", a, b);
[self testSingleStar:c];
[self testDoubleStar:e];
NSLog(#"After: a is: %d b is: %d", a, b);
Methods:
- (void)testDoubleStar:(int**)x
{
int anotherValue1 = 22;
**x = anotherValue1;
}
- (void)testSingleStar:(int*)x
{
int anotherValue2 = 33;
*x = anotherValue2;
}
Output:
Before: a is: 10 b is: 20
After: a is: 33 b is: 22
Both values of a (via a single pointer) and b (via a double pointer) did get changed.
So, if we can change the value (of a) using only a single pointer, why would we need to use a pointer to a pointer to NSError so that we could modify the NSError object in method call where NSError object is passed in its parameter (&error)?
In addition:
In regards to the above, passing something to the parameter in C is actually passing a copy to the parameter (even in the case of a single pointer only a copy of it will get passed), so anything change made within the scope of the method will not effect the original value passed to it (that's why they use a double star).
But the above sample, in which only a single pointer is used, seems to contradicts this because the value (namely a pointed to by a single pointer - c) did get changed?
You can modify an external variable of type foo by providing a foo * to a function or method:
+ (void)doJobReturningInt(int *) { ... }
int a;
[MyClass doJobReturningInt:&a]; // may modify the value of the variable a;
So far, so good.
Now how do we declare a variable storing an NSError object? With the NSError * type:
NSError *error;
So if we want to modify it, we need to provide a pointer to its type, that is to say NSError **.
+ (void)doJobReturningError:(NSError **)outError { ... }
NSError *error;
[MyClass doJobReturningError:&error]; // may modify the value of the variable error;
See? This is the same situation: for modifying the type foo, provide a foo*.
This is because you can't just have an NSError object... you can only deal with Objective-C objects by pointer... so while you could theoretically take a pointer to NSError and swap its contents... it would mess up encapsulation (other things could be relying on that data that used to be there.).
also just reassigning the pointer to a new value doesn't work, because it doesn't affect the callers version.
so while it seems tempting to:
-(void)method:(NSError *)errObject
{
//something like
errObject = [NSError errorWithBlah:#"blah"]; // this will only change the local variable errObject, not the callers version, that pointer is just copied by value.
}
or
/// not real code, didn't check to see if my params are in the correct places etc.
-(void)mangler:(NSError *)errObject
{
//something like
errObject = realloc(errObject,sizeof *errorObject);
memcpy(errObject,[NSError new],sizeof NSError);
// you have killed the old version that may be in use.
}

How to return a C-style array of integers in Objective-C?

How to return a C-style array of integers from an Objective-C method? This is what my code looks like so far:
Function call:
maze = [amaze getMaze];
Function:
-(int*) getMaze{
return maze;
}
I just started writing in Objective-C today so this is all new to me.
In C if you need to return an array from a function, you need to allocate memory for it using malloc and then return the pointer pointing to the newly allocated memory.
Once you're done working with this memory you need to free it.
Something like:
#include <stdlib.h> /* need this include at top for malloc and free */
int* foo(int size)
{
int* out = malloc(sizeof(int) * size); /* need to get the size of the int type and multiply it
* by the number of integers we would like to return */
return out; /* returning pointer to the function calling foo().
* Don't forget to free the memory allocated with malloc */
}
int main()
{
... /* some code here */
int* int_ptr = foo(25); /* int_ptr now points to the memory allocated in foo */
... /* some more code */
free(int_ptr); /* we're done with this, let's free it */
...
return 0;
}
This is as C style as it gets :) There are probably other (arguably more suitable) ways to do this in Objective C. However, as Objective C is considered a strict superset of C, this would also work.
If I may further expand on the need to do this by pointers. C-style arrays allocated in a function are considered local, once the function is out of scope they are automatically cleaned up.
As pointed out by another poster, returning a standard array (e.g. int arr[10];) from a function is a bad idea as by the time the array is returned it no longer exists.
In C we get around this problem by allocating memory dynamically using malloc and having a pointer that points to that memory returned.
However unless you free this memory adequately, you may introduce a memory leak or some other nasty behavior (e.g. free-ing a malloc-ed pointer twice will produce unwanted results).
Given you explicitly ask about C-style arrays no suggestions here that you should use NSArray etc.
You cannot return a C-style array directly (see below) as a value in Objective-C (or C or C++), you can return a reference to such an array.
Types such as int, double and struct x can all be passed by value - that is the actual bits representing the value are passed around. Other things; such as C-style arrays, dynamically allocated memory, Objective-C style objects, etc.; are all passed by reference - that is a reference to a location in memory that contains the actual bits the represent the value is passed around.
So to return a C-style array from a function/method you can:
Dynamically (malloc et al) an array and return the reference to the allocated memory;
Pass in a reference to an already existing array and have the function fill it up; or
Wrap the array up as a struct...
The normal choices are (1) or (2) - note you cannot return a reference to a stack allocated array, as in:
int *thisIsInvalid()
{
int myValues[5];
...
return myValues; // will not work, the type is correct but once function
// returns myValues no longer exists.
}
If you really want to return a (small) array by value you can actually do it using (3). Remember that struct values are passed by value. So the following will work:
typedef struct
{
int array[5];
} fiveInts;
fiveInts thisIsValid()
{
fiveInts myValues;
...
myValues.array[3] = ...; // etc.
...
return myValues;
}
(Note that there is no overhead from wrapping the array inside a struct when it comes to reading/writing the array - the cost in the above is copying all the values back - hence only advised for small arrays!)
HTH
- (NSArray *)toArray:(int *)maze {
NSMutableArray *retVal = [[NSMutableArray alloc] init];
for (int c = 0; maze[c] != NULL; c++) {
[retVal addObject:[NSNumber numberWithInt:maze[c]]];
}
return [retVal array];
}
I've never been comfortable passing mutable data in and out of methods and not sure why. If you need to change the values later, send the array a mutableCopy message.
you can do it in this way
- (void)getArray:(int *)array withLength:(NSUInteger)length{
for (int i = 0; i < length; i++)
array[i] = i;
}
int array[3];
[object getArray:array withLength:3];
NSLog(#"%d %d %d", array[0], array[1], array[2]); // 1 2 3

How to check if a variable is an object?

Is there any way to do the following at compile-time?
int anInteger = 0;
__if_object(anInteger) {
// send object some messages
}
__if_primitive(anInteger) {
// do something else
}
An dummy situation where this could be used is to define the __add_macro below.
#define __add_macro(var, val) __something_goes_here__
int i = 1;
MyInteger* num = [[MyNumber alloc] initWithValue:1]
__add_macro(i, 4);
__add_macro(num, 4);
// both should now hold 5
Clarification/Simplification
I guess there is no way to do this with one macro. But I still need it to warn if the macro is being used on the wrong datatype. Those two types are: object and non-object).
To check if it is an object, this works:
#define __warn_if_not_object(var) if(0){[(var) class];}
What I need:
#define _warn_if_object(var) if(0){__something_here__}
Again, I need this to happen at compile-time. And it can either throw an error or warning.
Thanks
When you declare an int variable you can really only put an int value in it.
While this is Objective-C, and hence C, so you can bypass just about every type protection mechanism that exists, this is not to be advised. Indeed there is no guarantee whatsoever that a, say, NSNumber reference will even fit into an int variable - and more than enough chance that if you try, and bypass any warnings, some bits will just get tossed making the reference invalid.
So, no, while you can tell what class an object reference refers to, you cannot in general tell whether a variable has an integer value or an object reference in it - you shouldn't even try to put these two very different things into the same variable.
Answer 2
Patrick, your comments and clarification seem to suggest you are not trying to do what the question starts out by asking (how do you determine if the value in an int is an object - answered above, you don't), but something rather different...
I think what you're after is function overloading, and as you seem to be trying to use macros, maybe inline functions as well. Clang supports function overloading, here is program fragment which may show you how to solve your problem:
// Clang likes prototypes so let's give it some
// The following declares two overloaded inline functions:
NS_INLINE void __attribute__((overloadable)) byType(int x);
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x);
// now some simple definitions:
NS_INLINE void __attribute__((overloadable)) byType(int x)
{
NSLog(#"int version called: %d", x);
}
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x)
{
NSLog(#"NSNumber version called: %#", x);
}
// now call them, automatically selecting the right function
// based on the argument type
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
int x = 5;
NSNumber *y = [NSNumber numberWithInt:42];
byType(x);
byType(y);
}
The above code when run outputs:
int version called: 5
NSNumber version called: 42
Clang 3 compiles the above code inlining the two calls, so you get the same code as using macros.
please don't mix between scalar values and pointers to objects... it will not end well.
if you insist you can do something with Objective-C++
something like
int sum(int,int);
NSNumber * sum(NSNumber *, NSNumber *);

Passing and calling dynamic blocks in Objective C

As part of a unit test framework, I'm writing a function genArray that will generate NSArrays populated by a passed in generator block. So [ObjCheck genArray: genInt] would generate an NSArray of random integers, [ObjCheck genArray: genChar] would generate an NSArray of random characters, etc. In particular, I'm getting compiler errors in my implementation of genArray and genString, a wrapper around [ObjCheck genArray: genChar].
I believe Objective C can manipulate blocks this dynamically, but I don't have the syntax right.
ObjCheck.m
+ (id) genArray: (id) gen {
NSArray* arr = [NSMutableArray array];
int len = [self genInt] % 100;
int i;
for (i = 0; i < len; i++) {
id value = gen();
arr = [arr arrayByAddingObject: value];
}
return arr;
}
+ (id) genString {
NSString* s = #"";
char (^g)() = ^() {
return [ObjCheck genChar];
};
NSArray* arr = [self genArray: g];
s = [arr componentsJoinedByString: #""];
return s;
}
When I try to compile, gcc complains that it can't do gen(), because gen is not a function. This makes sense, since gen is indeed not a function but an id which must be cast to a function.
But when I rewrite the signatures to use id^() instead of id, I also get compiler errors. Can Objective C handle arbitrarily typed blocks (genArray needs this), or is that too dynamic?
Given that blocks are objects, you can cast between block types and id whenever you want, though if you cast the block to the wrong block type and call it, you're going to get unexpected results (since there's no way to dynamically check at runtime what the "real" type of the block is*).
BTW, id^() isn't a type. You're thinking of id(^)(). This may be a source of compiler error for you. You should be able to update +genArray: to use
id value = ((id(^)())(gen))();
Naturally, that's pretty ugly.
*There actually is a way, llvm inserts an obj-c type-encoded string representing the type of the block into the block's internal structure, but this is an implementation detail and would rely on you casting the block to its internal implementation structure in order to extract.
Blocks are a C-level feature, not an ObjC one - you work with them analogously to function pointers. There's an article with a very concise overview of the syntax. (And most everything else.)
In your example, I'd make the gen parameter an id (^gen)(). (Or possibly make it return a void*, using id would imply to me that gen generates ObjC objects and not completely arbitrary types.)
No matter how you declare your variables and parameters, your code won't work. There's a problem that runs through all your compiler errors and it would be a problem even if you weren't doing convoluted things with blocks.
You are trying to add chars to an NSArray. You can't do that. You will have to wrap them them as some kind of Objective C object. Since your only requirement for this example to work is that the objects can be inputs to componentsJoinedByString, you can return single-character NSStrings from g. Then some variety of signature like id^() will work for genArray. I'm not sure how you parenthesize it. Something like this:
+ (id) genArray: (id^()) gen;
+ (id) genString {
...
NSString * (^g)() = ^() {
return [NSString stringWithFormat:#"%c", [ObjCheck genChar]];
};
...
}
NSString * is an id. char is not. You can pass NSString * ^() to id ^(), but you get a compiler error when you try to pass a char ^() to an id ^(). If you gave up some generality of genArray and declared it to accept char ^(), it would compile your call to genArray, but would have an error within genArray when you tried to call arrayByAddingObject and the argument isn't typed as an id.
Somebody who understands the intricacies of block syntax feel free to edit my post if I got some subtle syntax errors.
Btw, use an NSMutableArray as your local variable in genArray. Calling arrayByAddingObject over and over again will have O(n^2) time performance I imagine. You can still declare the return type as NSArray, which is a superclass of NSMutableArray, and the callers of genArray won't know the difference.