diff --git a/docs/syntax_and_semantics/block_forwarding.md b/docs/syntax_and_semantics/block_forwarding.md index c3bf63983..7fd91f389 100644 --- a/docs/syntax_and_semantics/block_forwarding.md +++ b/docs/syntax_and_semantics/block_forwarding.md @@ -28,7 +28,7 @@ def capture(&block) block end -def twice +def twice(&) yield yield end @@ -67,11 +67,11 @@ twice &->say_hello To forward non-captured blocks, you must use `yield`: ```crystal -def foo +def foo(&) yield 1 end -def wrap_foo +def wrap_foo(&) puts "Before foo" foo do |x| yield x @@ -92,7 +92,7 @@ end You can also use the `&block` syntax to forward blocks, but then you have to at least specify the input types, and the generated code will involve closures and will be slower: ```crystal -def foo +def foo(&) yield 1 end diff --git a/docs/syntax_and_semantics/blocks_and_procs.md b/docs/syntax_and_semantics/blocks_and_procs.md index 90cbb5395..05e2ee5ba 100644 --- a/docs/syntax_and_semantics/blocks_and_procs.md +++ b/docs/syntax_and_semantics/blocks_and_procs.md @@ -4,7 +4,7 @@ Methods can accept a block of code that is executed with the `yield` keyword. For example: ```crystal -def twice +def twice(&) yield yield end @@ -16,7 +16,7 @@ end The above program prints "Hello!" twice, once for each `yield`. -To define a method that receives a block, simply use `yield` inside it and the compiler will know. You can make this more evident by declaring a dummy block parameter, indicated as a last parameter prefixed with ampersand (`&`): +To define a method that receives a block, simply use `yield` inside it and the compiler will know. You can make this more evident by declaring a dummy block parameter, indicated as a last parameter prefixed with ampersand (`&`). In the example above we did this, making the argument anonymous (writing just the `&`). But it can be given a name: ```crystal def twice(&block) @@ -25,6 +25,8 @@ def twice(&block) end ``` +The block parameter name is irrelevant in this example, but will be relevant in more advanced uses. + To invoke a method and pass a block, you use `do ... end` or `{ ... }`. All of these are equivalent: ```crystal @@ -88,7 +90,7 @@ Two methods, one that yields and another that doesn't, are considered different The `yield` expression is similar to a call and can receive arguments. For example: ```crystal -def twice +def twice(&) yield 1 yield 2 end @@ -109,7 +111,7 @@ twice { |i| puts "Got #{i}" } You can `yield` many values: ```crystal -def many +def many(&) yield 1, 2, 3 end @@ -123,7 +125,7 @@ end A block can specify fewer parameters than the arguments yielded: ```crystal -def many +def many(&) yield 1, 2, 3 end @@ -137,7 +139,7 @@ end It's an error specifying more block parameters than the arguments yielded: ```crystal -def twice +def twice(&) yield yield end @@ -149,7 +151,7 @@ end Each block parameter has the type of every yield expression in that position. For example: ```crystal -def some +def some(&) yield 1, 'a' yield true, "hello" yield 2, nil @@ -164,7 +166,7 @@ end The [underscore](assignment.md#underscore) is also allowed as a block parameter: ```crystal -def pairs +def pairs(&) yield 1, 2 yield 2, 4 yield 3, 6 @@ -239,7 +241,7 @@ method(&.[index]) The `yield` expression itself has a value: the last expression of the block. For example: ```crystal -def twice +def twice(&) v1 = yield 1 puts v1 @@ -265,7 +267,7 @@ ary.select { |x| x % 2 == 1 } # => [1, 3] A dummy transformation method: ```crystal -def transform(value) +def transform(value, &) yield value end @@ -293,7 +295,7 @@ transform_int(3) { |x| "foo" } # Error: expected block to return Int32, not Stri A `break` expression inside a block exits early from the method: ```crystal -def thrice +def thrice(&) puts "Before 1" yield 1 puts "Before 2" @@ -315,7 +317,7 @@ The above prints "Before 1" and "Before 2". The `thrice` method didn't execute t `break` can also accept arguments: these become the method's return value. For example: ```crystal -def twice +def twice(&) yield 1 yield 2 end @@ -357,7 +359,7 @@ value # => nil The `next` expression inside a block exits early from the block (not the method). For example: ```crystal -def twice +def twice(&) yield 1 yield 2 end @@ -379,7 +381,7 @@ end The `next` expression accepts arguments, and these give the value of the `yield` expression that invoked the block: ```crystal -def twice +def twice(&) v1 = yield 1 puts v1 @@ -412,11 +414,11 @@ class Foo 1 end - def yield_with_self + def yield_with_self(&) with self yield end - def yield_normally + def yield_normally(&) yield end end @@ -477,7 +479,7 @@ end When using blocks with `yield`, the blocks are **always** inlined: no closures, calls or function pointers are involved. This means that this: ```crystal -def twice +def twice(&) yield 1 yield 2 end @@ -510,7 +512,7 @@ This is `Int#times` definition: ```crystal struct Int - def times + def times(&) i = 0 while i < self yield i diff --git a/docs/syntax_and_semantics/closures.md b/docs/syntax_and_semantics/closures.md index c7e3106ca..964fc8ff8 100644 --- a/docs/syntax_and_semantics/closures.md +++ b/docs/syntax_and_semantics/closures.md @@ -30,7 +30,7 @@ In the above example, even though `x` is a local variable, it was captured by th The compiler is usually moderately smart about the type of local variables. For example: ```crystal -def foo +def foo(&) yield end diff --git a/docs/syntax_and_semantics/macros/README.md b/docs/syntax_and_semantics/macros/README.md index 92516c7fa..82820cfca 100644 --- a/docs/syntax_and_semantics/macros/README.md +++ b/docs/syntax_and_semantics/macros/README.md @@ -36,7 +36,7 @@ class Foo "***#{ {{value}} }***" end - def yield_with_self + def yield_with_self(&) with self yield end end diff --git a/docs/syntax_and_semantics/next.md b/docs/syntax_and_semantics/next.md index 11ba27869..5b9b208ec 100644 --- a/docs/syntax_and_semantics/next.md +++ b/docs/syntax_and_semantics/next.md @@ -18,7 +18,7 @@ end `next` can also be used to exit from a block, for example: ```crystal -def block +def block(&) yield end @@ -34,7 +34,7 @@ end Similar to [`break`](break.md), `next` can also take an argument which will then be returned by `yield`. ```crystal -def block +def block(&) puts yield end diff --git a/docs/syntax_and_semantics/overloading.md b/docs/syntax_and_semantics/overloading.md index f3826445a..37c664146 100644 --- a/docs/syntax_and_semantics/overloading.md +++ b/docs/syntax_and_semantics/overloading.md @@ -60,7 +60,7 @@ class Person # Yields the current age of this person and increases # its age by the value returned by the block - def become_older + def become_older(&) @age += yield @age end end