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

Overhaul structuring and examples #1235

Open
wants to merge 1 commit into
base: master
from

Conversation

Projects
None yet
2 participants
@yawaramin
Copy link

yawaramin commented Dec 3, 2018

Since for-comprehensions are an important syntax sugar for Scala, I felt they deserve a bit of an overhaul and simpler but still motivating examples.

@som-snytt

This comment has been minimized.

Copy link
Contributor

som-snytt commented Jan 6, 2019

I'd caution that the tour is for "bite-sized introductions" and not detailed specs. I would show each example first, then describe the parts.

I don't know how folks teach this, but I'd suggest showing a for loop first, because everyone knows what that must mean. Add that it's really sugar for foreach, and everyone also knows what that means.

Then say a for comprehension collects the results computed by the yield. Then add that it's sugar for other method calls.

Then show for () versus for {} on multiple lines using multiple generators. The difference is only nl inference, right?

Then throw in a filter.

Finally add the bit about how semantics depend on the underlying type. Add a Future example, which is sort of whiz-bang.

```

Note that comprehensions are not restricted to lists. Every datatype that supports the operations `withFilter`, `map`, and `flatMap` (with the proper types) can be used in sequence comprehensions.
The filter after the second generator ensures that we don't generate redundant triples like (3, 4, 5) and (4, 3, 5) by forcing the second number in the triple to be larger than the first. The filter after the third generator enforces that only valid Pythagorean triples will be generated, i.e. that they will follow [Pythagoras' theorem](https://en.wikipedia.org/wiki/Pythagorean_theorem).

This comment has been minimized.

@som-snytt

som-snytt Jan 6, 2019

Contributor

That is a fun example, with not too much explanation.


* Sequence types like `List[A]` implement comprehensions in terms of a *cartesian product* between different lists
* `Option[A]` implements comprehensions in terms of *short-circuiting* the overall operation to `None` if any of the generators binds to a `None` input value
* Concurrency handlers like `Future[A]` implement comprehensions as making sure asynchronous actions happen in the *order* in which they are generated.

This comment has been minimized.

@som-snytt

som-snytt Jan 6, 2019

Contributor

This is confusing to me. "Concurrency handler" is not a meaningful expression to me. I think a short example would work well, however, because everyone loves futures in for comprehensions, whether or not they work the way they expected. This is just a tour example.


foo(10, 10)
## Comprehensions Without `yield`

This comment has been minimized.

@som-snytt

som-snytt Jan 6, 2019

Contributor

As noted, I'd start here. It's called a for loop as opposed to a for comprehension. Hey, I can guess what a for loop does.

Scala offers a lightweight notation for expressing *sequence comprehensions*. Comprehensions have the form `for (enumerators) yield e`, where `enumerators` refers to a semicolon-separated list of enumerators. An *enumerator* is either a generator which introduces new variables, or it is a filter. A comprehension evaluates the body `e` for each binding generated by the enumerators and returns a sequence of these values.

Here's an example:
Scala offers a lightweight notation for expressing *sequence comprehensions*. For-comprehensions have two basic syntaxes:

This comment has been minimized.

@som-snytt

som-snytt Jan 6, 2019

Contributor

I would avoid starting with the general. Also, the two basic syntaxes are for loops and comprehensions, depending on the presence of yield. Whether to use braces is better to show by example, with parens for the simplest one-generator for loop, braces for two-generator comprehension example. Don't even bother to explain why here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment