Els blocs són una extensió no estàndard afegida per Apple Inc. a les implementacions de Clang dels llenguatges de programació C, C++ i Objective-C que utilitza una sintaxi semblant a una expressió lambda per crear tancaments dins d'aquests llenguatges. Els blocs són compatibles amb programes desenvolupats per a Mac OS X 10.6+ i iOS 4.0+,[1] encara que els temps d'execució de tercers permeten l'ús en Mac OS X 10.5 i iOS 2.2+ [2] i sistemes que no siguin d'Apple.
Apple va dissenyar blocs amb l'objectiu explícit de facilitar l'escriptura de programes per a l'arquitectura de threading de Grand Central Dispatch,[3][4] encara que és independent d'aquesta arquitectura i es pot utilitzar de la mateixa manera que els tancaments en altres idiomes. Apple ha implementat blocs tant a la seva pròpia branca de la col·lecció de compiladors GNU [5] com al front-end del compilador Clang LLVM amunt. El suport de la biblioteca de temps d'execució d'idiomes per als blocs també està disponible com a part del projecte LLVM. El grup Khronos utilitza la sintaxi de blocs per posar en cua els nuclis dins dels nuclis a partir de la versió 2.0 d' OpenCL.[6]
Igual que les definicions de funcions, els blocs poden prendre arguments i declarar les seves pròpies variables internament. A diferència de les definicions de funcions C ordinàries, el seu valor pot capturar l'estat del seu context circumdant. Una definició de bloc produeix un valor opac que conté tant una referència al codi dins del bloc com una instantània de l'estat actual de les variables de la pila local en el moment de la seva definició. El bloc es pot invocar més tard de la mateixa manera que un punter de funció. El bloc es pot assignar a variables, passar a funcions i, d'una altra manera, tractar-se com un punter de funció normal, encara que el programador de l'aplicació (o l'API) ha de marcar el bloc amb un operador especial (Block_copy) si s'ha d'utilitzar fora de l'abast a que es va definir.
Donat un valor de bloc, el codi dins del bloc es pot executar en qualsevol moment posterior cridant-lo, utilitzant la mateixa sintaxi que s'utilitzaria per cridar una funció.
Exemples
Un exemple senzill que captura l'estat mutable a l'àmbit circumdant és un iterador d'intervals enters: [7]
/* blocks-test.c */
#include <stdio.h>
#include <Block.h>
/* Type of block taking nothing returning an int */
typedef int (^IntBlock)();
IntBlock MakeCounter(int start, int increment) {
__block int i = start;
return Block_copy( ^(void) {
int ret = i;
i += increment;
return ret;
});
}
int main(void) {
IntBlock mycounter = MakeCounter(5, 2);
printf("First call: %d\n", mycounter());
printf("Second call: %d\n", mycounter());
printf("Third call: %d\n", mycounter());
/* because it was copied, it must also be released */
Block_release(mycounter);
return 0;
}
Referències