Answer To Challenge: An Anonymous Block

Hi,

Well this seemed simple… too simple to do so I am not sure if I have grasped the question correctly so here it goes:

[code]#import <Foundation/Foundation.h>

typedef void(^ArrayEnumerationBlck)(id, NSUInteger, BOOL *);

int main(int argc, const char * argv[])
{

@autoreleasepool {
    
    // create array of strings and a container for devowelized ones
    NSArray *originalString = @[@"Sauerkraut", @"Raygun", @"Big Nerd Ranch",@"Mississippi"];
    NSLog(@"original string: %@", originalString);
    
    NSMutableArray *devowelizedStrings = [NSMutableArray array];
    
    // create a list of characters to be removed from the string
    NSArray *vowels = @[@"a",@"e",@"i",@"o",@"u"];
    
    // declare the bloack variable
    //void (^devowelizer)(id, NSUInteger, BOOL *);
    // ArrayEnumerationBlck devowelizer;
    
    // compose a bloack and assign it to the variable ( this was done previously prior to answering the challange
    // devowelizer = ^(id string, NSUInteger i, BOOL *stop) {
    
    // passing this block anonymously
    [originalString enumerateObjectsUsingBlock: ^(id string, NSUInteger i, BOOL *stop) {
        
        NSRange yRange = [string rangeOfString:@"y"
                                        options:NSCaseInsensitiveSearch];
        // did I find a y?
        if (yRange.location != NSNotFound) {
            *stop = YES;    // prevent further iterations
            return;         // End this iteration
        }
        NSMutableString *newString = [NSMutableString stringWithString:string];
        
        // iterate over the array of vowels, replacing occurrences of each
        // with an empty string
        
        for (NSString *s in vowels) {
            NSRange fullRange = NSMakeRange(0, [newString length]);
        [newString replaceOccurrencesOfString:s
                                   withString:@""
                                      options:NSCaseInsensitiveSearch
                                        range:fullRange];
        }
        [devowelizedStrings addObject:newString];
    }]; // End of block assignment
    
    //iterate over the array with your bloack
    //[originalString enumerateObjectsUsingBlock:devowelizer];
    
    NSLog(@"devowelizer string: %@", devowelizedStrings);
    
}
return 0;

}[/code]

Your solution is the same as mine. I think it is correct, however, its seems to be an ugly and inefficiant way to write code. So its either correct as a lesson that something IS possible, or we misunderstood the question.

This was very confusing to me. I don’t understand why I would use an anonymous block in this instance.

Maybe I just misunderstood what was going on here but I’ve read and re-read this section and it seems the block makes my code less readable and more complex. Hopefully, this is just a newbie-type thing and as I learn more blocks will become more valuable.

Here is my solution (note I took out the part of the block that looked for the first y to make the code easier to read and achieve the original intention - remove the vowels!)

[code]#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])

{

@autoreleasepool

{
    
    // Create array of strings and a container for devowelized ones
    
    NSArray *originalStrings = @[@"Sauerkraut", @"Raygun", @"Big Nerd Ranch", @"Mississippi"];
    NSLog(@"original strings : %@", originalStrings);
    
    NSMutableArray *devowelizedStrings = [NSMutableArray array];
    
    // Create a list of characters to be removed from the string
    
    NSArray *vowels = @[@"a", @"e", @"i", @"o", @"u"];
    
    // Iterate over the array with an anonymous block
    
    [originalStrings enumerateObjectsUsingBlock:^(id string, NSUInteger i, BOOL *stop)
   
        {
         
         NSMutableString *newString = [NSMutableString stringWithString:string];
         
         // Iterate over the array of vowels, replacing occurences of each with an empty string
         
         for (NSString *s in vowels)
            {
                NSRange fullRange = NSMakeRange(0, [newString length]);
                [newString replaceOccurrencesOfString:s
                                           withString:@""
                                              options:NSCaseInsensitiveSearch
                                                range:fullRange];
            }
         
        [devowelizedStrings addObject:newString];
        }
    ];
    NSLog(@"devowelized strings: %@", devowelizedStrings);
    
}

return 0;

}
[/code]

My understanding of this is as follows: They got us to pass an anonymous block as sometimes there is no point wasting memory creating another variable (the block itself) and it makes it easier for someone else to read. This is because sometimes you only need to use a block once and there is no point in both typedef’ing it and creating a variable for it if you are only going to use it when passing somewhere else once. Is that right?

Why don’t we need the semicolon to mark the end of the block definition when using the anonymous syntax? My guess is that it is because the block is an argument of the method enumerateObjectsUsingBlock, but I’m troubled by the seeming inconsistency.

I think we did the lesson right but I feel like in the real world, we would not be passing such a huge block anonymously. It just makes the code unreadable in my opinion.

I was always taught to encapsulate my functions inside of classes or objects, but at the very least always be working DRYly. (DON’T REPEAT YOURSELF). A function should do one thing, do it well, and be reusable. Anonymous functions always seem to negate this best practice, but I have come to accept them.

I’ve recently been working with Scala a lot which uses anonymous functions almost exclusively. They have always seemed like syntactical sugar to me, but the way they describe it in this book is pretty good. Sometimes readability and terseness trump convention, if you are only using it once why complicate the code with more classes and methods, especially where memory is concerned.

I think the message passing syntax of Objective-C makes this really ugly and unreadable. I probably would never do this in real code. However, I think we are all correct that this was in fact the correct answer to the exercise.