-
Notifications
You must be signed in to change notification settings - Fork 192
Ch4 - Is it possible to solve the countEven exercise without pattern matching? #303
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Comments
I think we can implement countEven without pattern matching by using the same patterns as in the examples just before that exercise. I think we should also avoid making it tail-recursive at least until the reader has reached the section about tail recursion. For example: isEven :: Int -> Boolean
isEven n =
if n == 0 then
true
else if n == 1 then
false
else
isEven (n - (2 * (n / abs n)))
countEven :: Array Int -> Int
countEven arr =
if null arr
then 0
else oneIfEven (fromMaybe 1 $ head arr) + countEven (fromMaybe [] $ tail arr)
where
oneIfEven x = if isEven x then 1 else 0 However, it does suck to have to do |
Edit: This message posted simultaneously with the previous one, so it doesn't make much sense as a direct reply.
isEven :: Int -> Boolean
isEven n = if n == 0 then
true
else not $ isEven $ n - 1 But with pattern matching, we can do: isEven :: Int -> Boolean
isEven 0 = true
isEven n = not $ isEven $ n - 1 Wondering if we should modify the exercise and tests to handle negative inputs. And for reference, here's the best countEven :: Array Int -> Int
countEven arr = case uncons arr of
Nothing -> 0
Just {head: x, tail: xs} -> (if isEven x then 1 else 0) + countEven xs But for these situations, I propose we note that future chapters will show how to rewrite these solutions elegantly, then follow-up. Otherwise, having readers only write the clunky implementations reflects poorly on the language. Here's an example of a nicer countEven :: Array Int -> Int
countEven = length <<< filter isEven Should we even be including these introductory exercises that ask readers to write non-idomatic code? I think we could provide better exercises. |
I think asking the reader to do at least one or two exercises with explicit recursion is probably good, because you do occasionally see it in the wild even if in most cases you ought to be using maps, filters, folds, and so on. If we ask them to rewrite |
I think an implementation which doesn't handle negative inputs is arguably wrong, as the exercise does ask for a function which returns true if and only if its input is an even integer, since negative even integers are still even integers. |
Here's what I'm thinking for next steps:
|
Just to add my solution, without pattern matching, but preserving Maybe, which IMHO feels too complicated for a beginner - I had to search externally for what is countEven :: Array Int -> Int
countEven arr = if null arr then 0 else evenInc (fromMaybe (-1) (head arr)) $ countEven (fromMaybe [] (tail arr))
where
evenInc :: Int -> Int -> Int
evenInc n = if isEven n then (+) 1 else (+) 0 |
The solution for the
countEven
exercise relies on pattern matching, but that isn't covered until the next chapter. Should we remove that exercise, or reorganize content in the book?purescript-book/exercises/chapter4/test/no-peeking/Solutions.purs
Lines 24 to 30 in 4346bb2
Even if we do want to use pattern matching, this solution can be cleaned-up a bit.
The text was updated successfully, but these errors were encountered: