I was looking at looping through an array and I stumbled across this method --
- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts
usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block
NSEnumerationOptions is defined as -
enum {
NSEnumerationConcurrent = (1UL << 0),
NSEnumerationReverse = (1UL << 1),
};
typedef NSUInteger NSEnumerationOptions;
The description for these are taken from NSHipster's blog post about enumeration --
NSEnumerationConcurrent: Specifies that the Block enumeration should
be concurrent. The order of invocation is nondeterministic and
undefined; this flag is a hint and may be ignored by the
implementation under some circumstances; the code of the Block must be
safe against concurrent invocation.
NSEnumerationReverse: Specifies
that the enumeration should be performed in reverse. This option is
available for NSArray and NSIndexSet classes; its behavior is
undefined for NSDictionary and NSSet classes, or when combined with
the NSEnumerationConcurrent flag.
NOW usually loops are written as -
for ( int i=0 ; i< count; i++ )
{
//stuff
}
My question is, why does NSEnumerationReverse exist and NSEnumerationForward does not. Why did Apple think that looping in reverse would be better than looping from 1st index.
Is there a performance benefit of looping through arrays in reverse? Or do i not understand NSEnumerationReverse properly?
The declared NSEnumerationOptions are for times when you want to use non-standard behaviour — forward iteration is the default behaviour that is automatically used unless you specify a different option.
To iterate forwards, simply pass 0 for the enumeration options parameter.
Note also that, since you're passing zero for the options anyway, you may as well just use the enumerateObjectsUsingBlock: method that does not accept any options, and does exactly the same thing otherwise (and is shorter to type).
Related
I was trying to implement vector algebra with generic algorithms and ended up playing with iterators. I have found two examples of not obvious and unexpected behaviour:
if I have pointer p to a struct (instance) with field fi, I can access the field as simply as p.fi (rather than p.*.fi)
if I have a "member" function fun(this: *Self) (where Self = #This()) and an instance s of the struct, I can call the function as simply as s.fun() (rather than (&s).fun())
My questions are:
is it documented (or in any way mentioned) somewhere? I've looked through both language reference and guide from ziglearn.org and didn't find anything
what is it that we observe in these examples? syntactic sugar for two particular cases or are there more general rules from which such behavior can be deduced?
are there more examples of weird pointers' behaviour?
For 1 and 2, you are correct. In Zig the dot works for both struct values and struct pointers transparently. Similarly, namespaced functions also do the right thing when invoked.
The only other similar behavior that I can think of is [] syntax used on arrays. You can use both directly on an array value and an array pointer interchangeably. This is somewhat equivalent to how the dot operates on structs.
const std = #import("std");
pub fn main() !void {
const arr = [_]u8{1,2,3};
const foo = &arr;
std.debug.print("{}", .{arr[2]});
std.debug.print("{}", .{foo[2]});
}
AFAIK these are the only three instances of this behavior. In all other cases if something asks for a pointer you have to explicitly provide it. Even when you pass an array to a function that accepts a slice, you will have to take the array's pointer explicitly.
The authoritative source of information is the language reference but checking it quickly, it doesn't seem to have a dedicated paragraph. Maybe there's some example that I missed though.
https://ziglang.org/documentation/0.8.0/
I first learned this syntax by going through the ziglings course, which is linked to on ziglang.org.
in exercise 43 (https://github.com/ratfactor/ziglings/blob/main/exercises/043_pointers5.zig)
// Note that you don't need to dereference the "pv" pointer to access
// the struct's fields:
//
// YES: pv.x
// NO: pv.*.x
//
// We can write functions that take pointer arguments:
//
// fn foo(v: *Vertex) void {
// v.x += 2;
// v.y += 3;
// v.z += 7;
// }
//
// And pass references to them:
//
// foo(&v1);
The ziglings course goes quite in-depth on a few language topics, so it's definitely work checking out if you're interested.
With regards to other syntax: as the previous answer mentioned, you don't need to dereference array pointers. I'm not sure about anything else (I thought function pointers worked the same, but I just ran some tests and they do not.)
I am just starting to learn Objective-C. I am confused to see that some types of variables are sometimes declared with an * asterisk, others are not. For example these are delcared with a *:
#property NSString *firstName;
NSString * mainString = #"Hello World!";
NSNumber *longNumber = #42l;
NSArray *unsortedStrings = #[#"gammaString", #"alphaString", #"betaString"];
And these are not:
int someInteger = 42;
NSInteger anInteger = 64;
id firstObject = #"someString";
NSRange substringRange = [mainString rangeOfString:#"long"];
I found this explanation from Apple's documentation: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/WorkingwithObjects/WorkingwithObjects.html#//apple_ref/doc/uid/TP40011210-CH4-SW1
Both these properties are for Objective-C objects, so they use an asterisk to indicate that they are C pointers.
But this explanation is too general and vague for me to understand the concept. I know type * means it is a pointer type, and this type stores pointers of that type. But why some types are declared with *, others are not?
The int type is not object. It is a C language “primitive data type”. You generally interact with primitive C data types directly. E.g.,
int i = 0; // it’s now `0`
i = 42; // it’s now `42`
The NSInteger is just an alias for another primitive data type, long. The NSRange is a struct (thus, also not an object), so the same rule applies. So, for basic interaction with these primitive data types, no * pointer reference is generally needed. (There actually are times you also deal with pointers to primitive data types, but that is beyond the scope of this question.)
But NSString, NSNumber, and NSArray, however, are objects, so you must use pointers when declaring them.
Note, you've included id in the latter list where * is not used:
id firstObject = #"foo";
Be very careful. This actually is a bit misleading, because firstObject actually is a pointer to the #"someString", a NSString object. The id is an exception to the way we generally declare pointers with * and is discussed in Objective-C is a Dynamic Language), “The id type defines a generic object pointer.”
It’s analogous to declaring a NSString pointer, but “you lose compile-time information about the object”. Compare the id pointer to the NSString * to the following syntax:
NSString *secondObject = #"bar";
This latter secondObject is NSString * pointer, but because we explicitly declared it as a NSString * pointer, the compiler knows that you are dealing with a string (thus the compiler can perform greater validation regarding your subsequent use of that pointer). With id, you do not enjoy this compile-time validation.
For example, here are two invalid attempts to call removeObject method on two NSString objects. NSString has no such method. The NSString * reference provides useful compile-time error message that id does not afford us:
Now, if you used the id type and tried to run that code, it would crash when it attempted to call removeObject on firstObject. But, where possible, it is much better to have the compiler tell us about the error during compile-time, rather than at run-time.
So the id pattern should be used sparingly, only when you really need Objective-C’s dynamic type behaviors.
When overriding equality operators in Lua (via the "__eq" metamethod), is there a way to still check for primitive equality (ie. not calling the overridden __eq, but checking if the two table values are referentially the same?) I need to do this from the C API, but I cannot find a suitable function there.
For example:
lua_newtable(L);
lua_newtable(L);
assert(!some_comparison());
lua_pushvalue(L,-1);
assert(some_comparison());
Where some_comparison() does not invoke the __eq metamethod.
(Please note lua_compare() does not satisfy this, in particular. I want a lua_rawcompare(), if you will - or rather a trick or workaround that will give me the equivalent. The idea is to prevent infinite recursion in a __eq implementation...)
If I understand your question correctly, I think you mean to use lua_rawequal:
int lua_rawequal (lua_State *L, int index1, int index2);
Returns 1 if the two values in indices index1 and index2 are
primitively equal (that is, without calling metamethods). Otherwise
returns 0. Also returns 0 if any of the indices are not valid.
Anyone came across this?
I ve got a nice little loop but it seems to get a warning.
for(;;nimages++)
It was proposed and accepted to remove the ++ and -- operators from the Swift language in an upcoming release, therefore the warning you're seeing is to help you avoid these types of constructs in your code before it is removed. (Please reference the link for a full explanation as well as the advantages and disadvantages that they provide.)
Please note that C-Style loops will also be deprecated in the near future according to the following proposal: https://github.com/apple/swift-evolution/blob/master/proposals/0007-remove-c-style-for-loops.md
Not knowing exactly what kind of logic you need to implement I don't feel confident recommending a solution, however in accordance with the above proposals I would recommend that you may want to become familiar with the Swift for-in and stride statements. Or, as another person recommended, using a while loop may also be appropriate.
What's the question? The entire error message is
C-style for statement is deprecated and will be removed in a future version of
Swift
You could replace this with something like
while true {
// loop body
nimages += 1
}
Finally, if you know the number of iterations you want, you can use a for-in loop:
for nimages in 0..<maxImages { /* loop body */ }
C Style For loops are deprecated and incrementing decrementing like these i++ , i-- also deprecated
Therefore couldn't be used this type of loops anymore
let myArray = ["one","two","three","four","five","six"]
for var i = 0; i < myArray.count; i++ {
print(myArray[i])
}
Instead of use above syntax, we can use this
let myArray = ["one","two","three","four","five","six"]
for i in 0..<myArray.count {
print(myArray[i])
}
And also this
for i in 0...myArray.count-1 {
print(myArray[i])
}
If you are not familiar with Range Operators and Half-Open Range Operators this is the time
(Document Link)
Range Operators
The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.
Half-Open Range Operators
The half-open range operator (a..<b) defines a range that runs from a to b, but does not include b.
For index-- style
for index in 10.stride(to: 0, by: -1) {
print(index)//This is 10, 9, 8, ... 1 NOT 0
}
For index++ style
for index in 0..<10 {
}
I would like to create a C array, which stores some objects but would like to declare it as follows:
id array = malloc(sizeof(NSObject * 4));
But this gives an error; it asks me to either:
Fix it - use __bridge to convert directly (No change in ownership).
Or:
Fixe it: use CFBridgeRelease to call to transfer ownership of a +1
'void' into ARC.
I have tried both, but it still gives an error:
Missing )
I remember having done this; but I forgot how since it has been a while.
How can I store ids in C array and retrieve things out of it and then cast them down?
The size of a pointer is the same for all types, including objects, so the following is all you need:
id *myArray = malloc(sizeof(void *) * 4);
Note that the type used on the left in the posted example was also incorrect, since the memory being allocated is expected to be referenced as a C array of pointers to objects, rather than just an object.
If you're compiling with ARC enabled, you'll need to add a lifetime qualifier to the declaration of myArray, and cast the return value of malloc. That's because ARC can only manage the lifetimes of pointers to objects and the array in which you're going to store the objects is a C type. For example, to tell ARC explicitly that the pointers in the array are unmanaged you could modify the previous code as follows:
__unsafe_unretained id *myArray = (__unsafe_unretained id *) malloc(sizeof(void *) * 4);
Note that since ARC can't manage retain counts in C arrays, it will be up to you to ensure that whatever you store in the array can be used safely.
You can't store arrays of objects in Objective-C. It only allow allocating pointers to objects. To do that, the right syntax would be like this:
id *array = malloc(sizeof(*array) * 4);
or possibly
id *array = malloc(sizeof(id) * 4);
but the former is more DRY.