Форум программистов, компьютерный форум, киберфорум
Наши страницы
Objective-C
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
Dev_Dev
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 72
#1

Отличия блоков от обычных функций

11.11.2014, 17:52. Просмотров 1470. Ответов 4
Метки нет (Все метки)

Здравствуйте, вот пришлось столкнуться с блоками. Вопрос в том, чем они отличаются от обычных функций. Например:

Objective-C
1
2
3
4
5
6
7
8
 
__block CGFloat result = 0;
   NSArray *array = [NSArray init...]      // init with something
    [array enumerateObjectsUsingBlock:^(NSNumber *weight, NSUInteger idx, BOOL *stop) {
        if (idx == inputs.count) {
            *stop = YES;
            return;
        }
В википедии написано, что в "в отличие от обычных функций, значения переменных в блоке могут устанавливаться из окружающего констекста ". Но можно создать обычную функцию, в которую также передать в качестве входных параметров локальные переменные. Тогда в чем разница?????? Может кто-нибудь простым языком объяснить?
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.11.2014, 17:52
Ответы с готовыми решениями:

Отличия методов класса от обычных функций
Что собой представляет метод в классах? Это такое же как и простая функция или...

Отличия процедур и функций
скажите плз что такое процедуры и функции, и чем они отличаются

Отличия в прототипах функций с указателями
Что значит символ указателя в прототипе функции? Например, void *...

Отличия вызова анонимной и именованной функций.
Что то понять не могу, что не так... В общем если так, то работает ...

Написать набор функций, обслуживающих блочно-диагональные матрицы из нескольких нижне-треугольных блоков
Написать набор функций (create,access,destroy), обслуживающих...

4
Vorona
Peace 2 all shining faces
672 / 534 / 84
Регистрация: 05.03.2010
Сообщений: 1,283
11.11.2014, 22:37 #2
блоки в objective-c, грубо говоря, служат в качестве анонимных функций, лямбда выражений или замыканий
если знаете ruby, javascript или например python, то вы уже знаете что это

блоки можно присваивать переменным, передавать в функции и возвращать из функций
в более функциональных языках функции изначально являются функциями высшего порядка или функциями первого класса
В objective-c это немного затянуто и иначе реализовано, потому на помощь приходят блоки, вот и все

намного удобней написать вот так
Objective-C
1
2
3
4
5
6
[array enumerateObjectsUsingBlock:^(NSNumber *weight, NSUInteger idx, BOOL *stop) {
    if (idx == inputs.count) {
        *stop = YES;
        return;
    }
}];
нежели как-то так:
Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@interface MyClass <NSArrayEnumerator>
 
// . . .
 
- (void)myMethod
{
    [array enumerateObjectsWithDelegate:self]
}
 
// . . .
 
- (void)array:(NSArray *)array enumerateNextWithWeight:(NSNumber *)weight index:(NSUInteger)idx stop:(BOOL *)stop
{
    if (idx == inputs.count) {
        *stop = YES;
        return;
    }
}
Конечно, пример не из реальной жизни, но к сожалению очень часто именно так и происходит, и что еще хуже,
так то, что "старые фанаты" делегатов не понимают и не хотят учиться не хотят использовать блоки и пишут подобную ерунду
1
Dev_Dev
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 72
12.11.2014, 01:08  [ТС] #3
Мне Java и Python не знакомы. Я больше С/С++ и Objective-C. Ну вот смотрите, я приведу 2 примера. Перемножаем два одномерных массива:
Objective-C
1
2
3
4
5
6
7
8
9
10
__block NSMutableArray *result = [[NSMutableArray alloc] init];
 NSArray *array1 = [[NSArray alloc] initWithObjects:@1, @1, nil]; 
 NSArray *array2 = [[NSArray alloc] initWithObjects:@2, @3, nil ];
    [array1 enumerateObjectsUsingBlock:^(NSNumber *element, NSUInteger idx, BOOL *stop) {
        if (idx == array1.count) {
            *stop = YES;
            return;
        }
    [result addObject:element*array2[idx]];
}
И вот другой пример перемножения массивов
Objective-C
1
2
3
4
5
6
7
8
NSMutableArray *result = [[NSMutableArray alloc] init];
 NSArray *array1 = [[NSArray alloc] initWithObjects:@1, @1, nil]; 
 NSArray *array2 = [[NSArray alloc] initWithObjects:@2, @3, nil ];
 
for(int i = 0; i < array1.count; i++)
{
[result addObject:array1[i]*array2[i]];
}
В обоих случаях получаем один и тот же массив. Вот в данном примере, где разница? Спасибо большое ! )))
0
Xavier
in god we trust
74 / 74 / 8
Регистрация: 20.04.2012
Сообщений: 201
12.11.2014, 09:45 #4
В данном конкретном примере с массивами все зависит от того что тебе надо. Во первых лучше все же использовать for in loop для коллекций, компилятор немного оптимизирует его и код выполняется чуток быстрее чем простое for. Enumirate в свою очередь выполняется или по крайней мере пытается выполнить итерацию еще быстрее используя для этого NSFastEnumiration. В данном примере можно использовать и тот и тот способ, повторюсь все зависит от того что именно надо.

А реальную помощь блоки приносят в тех же колбеках (complition handler). Например тот же sendAsynchronousRequest:queue:completionHandler: метод у NSURLConnection гораздо удобнее встроить блок "по ходу", чем писать различные функции, так как реквесты могут быть разные и данные соответсвенно отличаются, то и обрабатывать их нужно по разному. Я надеюсь понятно.
Вообще тот же GCD весь основан на блоках.

Блоки мощная штука, но там есть и свои подводные камни, соответсвенно использовать их нужно внимательно и осторожно.
1
Vorona
Peace 2 all shining faces
672 / 534 / 84
Регистрация: 05.03.2010
Сообщений: 1,283
12.11.2014, 23:39 #5
вообще, желательно посмотреть в сторону декларативного и функционального программирования для упрощения жизни и кода
например, вместо, того, чтобы умножать два массива посредством форича, слежением за индексом и размерами обеих массивов, можно было бы использовать простую безопасную функцию zipWith
в Haskell ее можно использовать так
Haskell
1
zipWith (*) [1,2,3] [2,3,4]
в Objective-C это можно было бы легко сделать при помощи блоков
Objective-C
1
2
3
zipWith(array1, array2, ^NSNumber *(NSNumber *obj1, NSNumber *obj2) {
    return @(obj1.integerValue * obj2.integerValue);
});
На выходе получаем массив перемноженных объектов, длина которого будет равна длине более "короткого" массива, потому не стоит ни о чем беспокоиться
плюс насчет безопасности и чистоты этой функции - она не меняет ни один из входных массивов, а наоборот отдает просто результат операций над ними, что позволяет поддержать чистоту кода и убирает проблему путаницы с состояниями.

Вот Underscore.m - отличный пример использования блоков в "бытовухе", ну и конечно, не говоря уже об колбеках ответов с сервера и т.д. как выше упомянул Xavier
1
12.11.2014, 23:39
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
12.11.2014, 23:39

Создать круг разделенный на 6 блоков, в центре логотип, при наведении на один из блоков он увеличивается
Доброго времени суток. Не знаю, как даже искать похожее. В общем нужно создать...

Выделить последовательно пять блоков памяти. Высвободить второй блок, после чего вывести информацию о цепочке блоков
Выделить последовательно пять блоков памяти. Высвободить второй блок, после...

Решение обычных примеров
Написал такой код но выдает ошибку на строке где комментарий. Не могу понять в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru