Skip to content

Conversation

@jiegillet
Copy link
Contributor

@jiegillet jiegillet commented May 16, 2025

Part of #692

I took this concept and exercise combo pretty much straight out of the Elixir track, which itself forked it from the C# track.

Some notes:

  • The original issue include teaching about tail call recursion, but since Elixir was separating the two, I thought it would be easier to do the same, so this PR does not talk about tail call recursion.
  • I usually leave the introduction.md as TODO, but this time, I followed the lead of Elixir that includes more details in the about.md and less in the intro. (it's still missing in the exercise though, so the CI will fail)
  • I again used AI to help me translate from Elixir to Elm, very useful
  • I added a bunch of exercises to practice the concept. There are definitely more that do, but I didn't go through all of them
  • I removed the fields strings and lists from some exercises that practiced those, because we had to many, (bin/configlet lint warns that we should have at most 10, now we are OK)

@jiegillet jiegillet changed the title Add forked concept recursion and concept exercise birdCount Add forked concept recursion and concept exercise bird-count May 16, 2025
Due to immutability, loops in Elm are written differently from imperative languages.
For example, loops commonly look like:

```
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe mark this as c or something?

Copy link
Contributor Author

@jiegillet jiegillet May 17, 2025

Choose a reason for hiding this comment

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

It's not C, because of array.length. I'll mention it's pseudocode.
EDIT: eh, it doesn't matter, I'll mark it as C for the highlighting.

```

A recursive function can have many base cases and/or many recursive cases.
For example [the Fibonacci sequence][fibonacci] is a recursive sequence with two base cases:
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a famously slow way to solve the fibonacci sequence. Probably worth mentioning that or choosing a different example?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't find a different example that was as simple as this one and not terribly slow, so I added a note.


Recursive functions, if implemented incorrectly, might never return their result.
This can be problematic because each time a function is called, a reference is stored in memory where the runtime should return the result (on the [call stack][wiki-call-stack]).
If a recursive function calls itself infinitely, it is possible to run out of memory causing the runtime to crash (a [stack overflow error][wiki-stack-overflow]).
Copy link
Contributor

Choose a reason for hiding this comment

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

This can also happen for large / inefficient cases, but can't happen if tail call elimination happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I reworked the text to mention large cases, but I want to keep tail call elimination for the next concept.
That being said, for infinite recursion, tail call optimization can be a negative thing, because it won't overflow, it'll keep heating up your CPU for no benefit :)


## General

- Read about recursion [here][recursion].
Copy link
Contributor

Choose a reason for hiding this comment

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

Using 'here' for links is an antipattern.

Suggested change
- Read about recursion [here][recursion].
- Read about [recursion from the creator of Elm][recursion].

You have chosen to store the data as a list of integers.
The first number in the list is the number of birds that visited your garden today, the second yesterday, and so on.

```exercism/note
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a shame, is there not an example of using recursion where it would be the idiomatic thing to do?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I agree that it's a shame, however I generally think that it's a good exercise to re-implement core functions to deepen your understanding of them. With the understanding that it's not idiomatic of course, and in that sense, a concept exercise is the right place to do it.

Pretty much all practice exercise that are marked with recursion are examples where recursion is the idiomatic thing to do.

I do realize that I'm biased because I don't really want to come up with a completely new exercise, but I will:

  • tweak the note to emphasize that this is not idiomatic, but for the sake of learning
  • come up with an exercise for tail-call-recursion that uses recursion idiomatically


today : List Int -> Maybe Int
today counts =
case counts of
Copy link
Contributor

Choose a reason for hiding this comment

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

I would use List.head here

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right, but all these are pretty much one liners if you use List, except for incrementDayCount.

today = List.head
hasDayWithoutBirds = List.any ((==) 0)
total = List.sum
busyDays = List.filter ((>=) 5) >> List.length

@jiegillet jiegillet merged commit b839dd2 into main May 17, 2025
6 checks passed
@jiegillet jiegillet deleted the jie-recursion branch May 17, 2025 04:26
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