Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Blocks section to Tutorials #655

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

ftarulla
Copy link
Contributor

@ftarulla ftarulla commented Nov 29, 2022

In this PR we add an intro to Blocks in the Methods section and continue in a Blocks section.

We talked about:

  • Blocks definition
  • Blocks and methods
  • Blocks with parameters
  • Returning keywords
  • Type restrictions
  • Alternative syntaxes
  • Under the hood

@netlify
Copy link

netlify bot commented Nov 29, 2022

Deploy Preview for crystal-book ready!

Name Link
🔨 Latest commit 90637ac
🔍 Latest deploy log https://app.netlify.com/sites/crystal-book/deploys/63b4e3df72fdd3000876c9da
😎 Deploy Preview https://deploy-preview-655--crystal-book.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@ftarulla ftarulla force-pushed the feature/tutorial-methods-blocks branch 3 times, most recently from b5afae2 to 6524049 Compare November 29, 2022 22:19
@ftarulla ftarulla force-pushed the feature/tutorial-methods-blocks branch from 6524049 to 1ae7b88 Compare November 29, 2022 22:21
@ftarulla ftarulla changed the title Add Blocks section to Methods Add Blocks section to Tutorials>Methods Nov 29, 2022
Copy link
Member

@beta-ziliani beta-ziliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't check it entirely because I have a high-level point that probably needs addressing. I find the example a bit convoluted, probably because it's artificial. Maybe consider using the loop toplevel method? This could be good to explain when to skip (next) and when to break.

For instance:

# print even numbers from 0 to 10

i = 0
loop do
	i += 1
  next if i % 2 == 1
	p i
  break if i == 10
end

The example doesn't need to be the same from top to bottom. The important bit is that it can be described easily as I did above, to help understanding that it does (and why is important to learn).

docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
docs/tutorials/basics/60_methods.md Outdated Show resolved Hide resolved
@straight-shoota
Copy link
Member

This content is quite a lot and hardly fits into the Methods lesson (which doubles in size). I'd suggest to introduce it as a separate lesson called Blocks in order to keep every single one at a reasonable length.
I would also separate captures into a later lessen called Procs. The section about capatured blocks is very short and incomplete. There are a lot more aspects as well as a lot more complexity involved with closures and procs. It's an entire topic on its own and should come later in the tutorial after generics are introduced (and possibly some other concepts).

Regarding blocks, there are also some more aspects that need to be addressed. Not all of them are essential to be fully fleshed out right away, but should be covered eventually.
I think a good order of introduction could look like this:

  • Basics: yield + do ... end
    • Explain the purpose and benefit of blocks, plus demonstrate the effect of inlining
    • multiple yield
    • specifics of overloading
  • output values (without keywords)
  • parameters
    • including underscore, omission, splats and unpacking
    • types
  • keywords
    • next
    • break
    • return
  • block type restrictions
  • alternative call syntaxes:
    • curly braces
    • short block notation

The language specification already covers a lot of that and we can copy ideas from there, adapted to a tutorial format.

@ftarulla ftarulla force-pushed the feature/tutorial-methods-blocks branch from 2f2015d to 1f98817 Compare December 30, 2022 17:46
@ftarulla ftarulla changed the title Add Blocks section to Tutorials>Methods Add Blocks section to Tutorials Jan 4, 2023
Copy link
Member

@beta-ziliani beta-ziliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't be alarm by the amount of comments, there are mostly nitpickings :-)

Comment on lines +12 to +18
def with_42
yield
end

with_42 do
puts 42
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's nothing in the method that suggest a 42, what about this name instead?

Suggested change
def with_42
yield
end
with_42 do
puts 42
end
def run
yield
end
run do
puts 42
end

Comment on lines +24 to +32
def three_times
yield
yield
yield
end

three_times do
puts 42
end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just if the previous comment is accepted:

Suggested change
def three_times
yield
yield
yield
end
three_times do
puts 42
end
def run_three_times
yield
yield
yield
end
run_three_times do
puts 42
end


Let's see another examples with a common use scenario for *blocks*: collections.

Here are two examples:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A real nitpick.

Suggested change
Here are two examples:
Consider the following two examples:

NOTE:
We use parentheses to unpack the argument into the different block parameters.

Unpacking arguments into parameters works only if the argument's type responds to `[i]` (with `i` an `integer`). In our example `Array` inherits [Indexable#[ ]](https://crystal-lang.org/api/Indexable.html#%5B%5D%28index%3AInt%29-instance-method)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Unpacking arguments into parameters works only if the argument's type responds to `[i]` (with `i` an `integer`). In our example `Array` inherits [Indexable#[ ]](https://crystal-lang.org/api/Indexable.html#%5B%5D%28index%3AInt%29-instance-method)
Unpacking arguments into parameters works only if the argument's type responds to `[i]` (with `i` an `integer`). In our example `Array` inherits [Indexable#[ ]](https://crystal-lang.org/api/Indexable.html#%5B%5D%28index%3AInt%29-instance-method). Of course, it will raise an exception if we try to unpack more elements than existing. You can try it yourself, by adding a parameter or by removing an element.

```

NOTE:
`Tuples` also implements [Tuple#[ ]](https://crystal-lang.org/api/Tuple.html#%5B%5D%28index%3AInt%29-instance-method) meaning that we can also use *unpacking*.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
`Tuples` also implements [Tuple#[ ]](https://crystal-lang.org/api/Tuple.html#%5B%5D%28index%3AInt%29-instance-method) meaning that we can also use *unpacking*.
`Tuples` also implements [Tuple#[ ]](https://crystal-lang.org/api/Tuple.html#%5B%5D%28index%3AInt%29-instance-method) meaning that we can also use *unpacking*. But there's a difference in how unpacking or auto-splatting works with tuples when there aren't sufficient elements. Try it, can you spot the difference?


Great! Let's explain it step by step:

First we split the block parameter using the *short one-parameter syntax* `&.split`. Then, we chained the result applying `map` and using again the *short one-parameter syntax* `.map(&.capitalize)`. And finally we join the `array` of `strings` using `join(' ')`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
First we split the block parameter using the *short one-parameter syntax* `&.split`. Then, we chained the result applying `map` and using again the *short one-parameter syntax* `.map(&.capitalize)`. And finally we join the `array` of `strings` using `join(' ')`.
First we split the block parameter using the *short one-parameter syntax* `&.split`. Then, we chained the result applying `map` and using again the short one-parameter syntax `.map(&.capitalize)`. And finally we join the `array` of `strings` using `join(' ')`.


First we split the block parameter using the *short one-parameter syntax* `&.split`. Then, we chained the result applying `map` and using again the *short one-parameter syntax* `.map(&.capitalize)`. And finally we join the `array` of `strings` using `join(' ')`.

Now, what if we want to parameterize the string we transform. Can we still use the *short one-parameter syntax*? The answer is yes! Let's see:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Now, what if we want to parameterize the string we transform. Can we still use the *short one-parameter syntax*? The answer is yes! Let's see:
Now, what if we want to parameterize the string we transform. Can we still use the short one-parameter syntax? The answer is yes! Let's see:


## Under the hood

Before finishing this section of the tutorial, it would be a good idea to see how *blocks* work under the hood.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Before finishing this section of the tutorial, it would be a good idea to see how *blocks* work under the hood.
Before finishing this section of the tutorial, it would be a good idea to see how blocks work under the hood.


Before finishing this section of the tutorial, it would be a good idea to see how *blocks* work under the hood.

First, it's important to note that in this section we have only seen *blocks* that we use with the keyword `yield`. There is [another kind of block](../../syntax_and_semantics/capturing_blocks.md), but we will leave it for later in the tutorial.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
First, it's important to note that in this section we have only seen *blocks* that we use with the keyword `yield`. There is [another kind of block](../../syntax_and_semantics/capturing_blocks.md), but we will leave it for later in the tutorial.
First, it's important to note that in this section we have only seen blocks that we use with the keyword `yield`. There is [another kind of block](../../syntax_and_semantics/capturing_blocks.md), but we will leave it for later in the tutorial.


First, it's important to note that in this section we have only seen *blocks* that we use with the keyword `yield`. There is [another kind of block](../../syntax_and_semantics/capturing_blocks.md), but we will leave it for later in the tutorial.

In a method that receives a *block*, when we write `yield`, the compiler will inline the *block of code*, which means that this:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
In a method that receives a *block*, when we write `yield`, the compiler will inline the *block of code*, which means that this:
In a method that receives a block, when we write `yield`, the compiler will inline the block of code, which means that this:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants