33

I have question on the syntax of __block variables. I know you can use __block on a variable in scope so it's not read-only inside the block. However in one spot in the apple docs, I saw an alternative:

"Variables in the defining scope are read-only by default when used in a block. If you need to change the value of such a variable, you can use a special syntax:

int count = 0;
float cumulativeValue = 0.0;
UpdateElements( a, N, ^(float element){
    |count, cumulativeValue|
    float value = factor * element;
    ++count;
    cumulativeValue += value;
    return value;
} );

In this example, count and cumulativeValue are modified inside the block, so they are included in comma-separated list of shared variables at the beginning of the block scope.

This syntax seems much cleaner and I assume you could then modify variables you did not declare but are still in scope. However, I haven't seen this anywhere else and the xCode compiler does not like my basic block. Is this legitimate syntax?

pk-nb
  • 2,850
  • 1
  • 18
  • 20

2 Answers2

45

Wow. Haven't seen that syntax in a long time.

That was one of the various syntactic structures explored during the development of blocks. It was eventually rejected because it was too imprecise in declaring intent and the resulting behavior would have been confusing.

Consider a scope with three blocks, two of which declare a variable as readwrite via |a|. There would be no way of knowing from the int a = 5; declaration at the top of the scope that the variable's value is readwrite in some of the block's scope.

As well, it would make the compiler implementation significantly more difficult. The tradition in C is that a variables storage type is fixed at the time of declaration. Supporting this syntax would have broken that expectation.

Thus, it was decided to use a storage type modifier akin to volatile or static. __block was used primarily because the __ prefix greatly reduces the amount of code that would break by adding a bare keyword.

Thanks for asking this. Bug filed and that documentation will be fixed and/or removed eventually.

bbum
  • 162,346
  • 23
  • 271
  • 359
  • Very interesting! Thanks for the history – pk-nb Jun 07 '13 at 16:58
  • So, any idea why the documentation got written before you formalized the syntax? – CodaFi Jun 07 '13 at 23:27
  • 4
    If the documentation folk can't figure out how to explain something coherently, it is a sure sign that the design is seriously flawed, thus they are involved early in the design process. That documentation may have originally been produced for the WWDC where Blocks were first announced. – bbum Jun 07 '13 at 23:38
  • 1
    This isn't so far from the "capture list" syntax of C++ lambda expressions (or at least could have been moved towards that syntax without breaking things). With the kinds of errors that crop up due to implicit block copy behaviors (like implicit self-retain), I've been kind of sad that this syntax didn't carry the day. Do you think it's played out better than the more explicit syntax in C++? Or am I misreading the similarity? In my experience, knowing what the block captures at the point of the block has been more important than knowing at the point of the declaration. – Rob Napier Jun 08 '13 at 22:00
5

The | | syntax was inspired by Smalltalk, as was, of course, the term "block".

As bbum points out, marking the decl site is more honest w.r.t. non-block usage and far more in line with C when modeled, as it ended up, as a new (C) object "duration".

http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1451.pdf

Wizard
  • 51
  • 3