Форум программистов, компьютерный форум CyberForum.ru

Objective-C

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
Dev_Dev
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 64
#1

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

11.11.2014, 17:52. Просмотров 1261. Ответов 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;
        }
В википедии написано, что в "в отличие от обычных функций, значения переменных в блоке могут устанавливаться из окружающего констекста ". Но можно создать обычную функцию, в которую также передать в качестве входных параметров локальные переменные. Тогда в чем разница?????? Может кто-нибудь простым языком объяснить?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.11.2014, 17:52     Отличия блоков от обычных функций
Посмотрите здесь:

Objective-C Использование функций и процедур
Замена обычных названий C#
Решение обычных примеров C (СИ)
Delphi Отличия процедур и функций
Отличия методов класса от обычных функций C++
Objective-C в чем отличия?
Появились ссылки в обычных текстах
C++ Написать набор функций, обслуживающих блочно-диагональные матрицы из нескольких нижне-треугольных блоков
Отбор в обычных формах 1С
Objective-C Отличия С++ от objC
Сортировка чисел, но не обычных! ->> Delphi
jQuery Отличия вызова анонимной и именованной функций.

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

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Vorona
Peace 2 all shining faces
666 / 528 / 45
Регистрация: 05.03.2010
Сообщений: 1,271
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;
    }
}
Конечно, пример не из реальной жизни, но к сожалению очень часто именно так и происходит, и что еще хуже,
так то, что "старые фанаты" делегатов не понимают и не хотят учиться не хотят использовать блоки и пишут подобную ерунду
Dev_Dev
0 / 0 / 0
Регистрация: 11.11.2012
Сообщений: 64
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]];
}
В обоих случаях получаем один и тот же массив. Вот в данном примере, где разница? Спасибо большое ! )))
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 весь основан на блоках.

Блоки мощная штука, но там есть и свои подводные камни, соответсвенно использовать их нужно внимательно и осторожно.
Vorona
Peace 2 all shining faces
666 / 528 / 45
Регистрация: 05.03.2010
Сообщений: 1,271
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
Yandex
Объявления
12.11.2014, 23:39     Отличия блоков от обычных функций
Ответ Создать тему
Опции темы

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