-
-
Notifications
You must be signed in to change notification settings - Fork 399
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
Leap 48in24 approaches #1401
Leap 48in24 approaches #1401
Conversation
Thank you for contributing to Based on the files changed in this PR, it would be good to pay attention to the following details when reviewing the PR:
Automated comment created by PR Commenter 🤖. |
This looks great, I'm not sure if explaining the difference between Kernel.rem/2 and Integer.mod/2 will be that interesting for the purpose of this challenge. Besides these approaches we could also add an if expression (translated from a Go solution):
Really super small pet peeve: Elixir is usually indented using 2 spaces, not 4 ;) |
I was holding off any reviews on this as it's still marked a draft, but let me just address:
I'm unhappy that the snippets have to be |
@michalporeba I pushed a commit with a script |
Thanks for the feedback. Please don't wait. There is little time and there is still a lot to do. This is why I created a draft PR to ask for early feedback. I still have specific approaches to write up, and the snippets may change slightly once the approaches are written up. At the moment, I'm mostly interested in what you think about the structure of the introduction selections of the approaches. I'll start on the individual approaches tomorrow. |
Hi @angelikatyborska. The scrip appears to be causing issues with checks. Considering that there will be more code in the .md files in the discussion than there will be in the snippets, perhaps we need to depend on manual code formatting? Snippets also often contain partial code, that's my experience from other tracks. The idea is to illustrate briefly what will be discussed on the approach page. Won't that be a problem for the formatted? |
That's on purpose, I want CI checks to fail if the code in snippets is not formatted. This will also require that the snippets are formally valid Elixir code, but it doesn't need to actually compile. It would be nice if I could do the same for the code in |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this! I personally don't have the motivation to write any approaches myself, but if do, I promise to review all your PRs on time 😇.
For the future it's better to tell me explicitly that you want a draft PR reviewed when you open it. I usually wait until it's marked as "ready for review" because, well... that's the name of the feature 😂 and some people are shy about having their work in progress judged.
The two functions differ in how they work with negative numbers, but since, in this exercise, | ||
all the numbers are non-negative, both could work, depending on the approach. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick: I think there are no test cases for the year 0
, so we could also say:
The two functions differ in how they work with negative numbers, but since, in this exercise, | |
all the numbers are non-negative, both could work, depending on the approach. | |
The two functions differ in how they work with negative numbers, but since, in this exercise, | |
all the input numbers are positive, both could work, depending on the approach. |
(I'm specifying "input numbers" instead of just "numbers" to avoid people complaining that technically there is a zero in this exercise, in rem(year, n) == 0
😛 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used the "non-negative" here very intentionally. Positives start at 1, non-negative start at 0, so the zero is included. Probably a better name for the n
parameter and for the description would be to say 'divisor' as this is technically what it is, and where the behaviour of the two functions differ.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
alright, no problem, we can keep it
Over all, I think the approaches you've identified so far are the right ones to describe. I browsed some of the community solutions and most of them qualify as one of those approaches or a mix of two. I found one extra approach that I would call "I love nesting", but I wouldn't recommend it to anyone 😁 def leap_year?(year) do
if rem(year, 4) == 0 do
if rem(year, 100) == 0 do
if rem(year, 400) == 0 do
true
else
false
end
else
true
end
else
false
end
end |
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Thanks. I think I'm the opposite. I like the approaches and writing about ways to solve problems with code. I don't know for how long I will have enough energy to do so, but I'll approach this problem a week at the time. My objective is to finish this by the end of the week with all the detailed approaches. I know there is no reverse exercise for the second week, so it will give us (me) some time to prepare approaches for the following week.
I have requested this on the forum, but I will make it more explicit in the PRs, too. Generally, here I'm also the opposite. "ready for review" for me is "ready for the final review and merge", while the "draft" is for early feedback that can lead to changes in direction. I'm not shy in that regard. I love early feedback and for my work in progress to be judged. Many comments you provided today will be very helpful as I write more text in the approaches to reduce, hopefully, the number of corrections required. Dzięki! |
At the core of this approach, three checks are returning three boolean values. | ||
We can use [Boolean logic](https://en.wikipedia.org/wiki/Boolean_algebra) to combine the results. | ||
|
||
When using this approach, it is essential to consider short-circuiting of boolean operators. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say short-circuiting does not matter at all in this exercise. Short-circuiting is important to consider when we want to avoid or ensure some side effects, for example:
iex()> 40 / x
** (ArithmeticError) bad argument in arithmetic expression: 40 / 0
:erlang./(40, 0)
iex:3: (file)
iex()> x != 0 && 40 / x
false
In this exercise, all inputs are valid, all the checks on either side of the boolean operator are pure functions with no side effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are the reasons why I think it is still relevant, even if all inputs are valid, all the checks are pure functions.
- In the approach I'm showing different variations of the code. The option with the custom
divides?/2
function is not necessarily guaranteed to be pure. - The approach at the end I'm showing an option to capture the results in variables. Perhaps I should make it more explicit, but in this case, all checks are performed because the short-circuiting applies only to checking the value of the variables.
- In every exercise instructions, at the bottom, there instructions on how to use
IO.inspect/1
for debugging your solutions. It is possible, that somebody less experienced will be surprised that inspect added to a custom function, or perhaps directly to one of the checks. Consider this code
rem(year, 4) == 0 and not IO.inspect(rem(year, 100) == 0) or rem(year, 400) == 0
When rem(year, 4) != 0
the IO.inspect/1
will not show anything because it will not be evaluated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I'm convinced 🙂
I have no idea! What do other tracks do?
Are you asking if it's too many or not enough? Or are you asking about their quality?
Agreed |
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
Co-authored-by: Angelika Tyborska <[email protected]>
The approach to approaches the tracks take are not very consistent. In that sense, the approaches are similar to concepts and exercise introductions. Some tracks are very detailed to the point of becoming a language tutorial. Other tracks are much more dry. Concepts can be lengthy and detailed, but they can only be more or less code examples. Personally, I like the approaches, because they offer more than what can be seen in the community solutions. They offer an opportunity to explain language features in context and how they apply to a problem. You can help somebody expand their knowledge and understanding. I hope they can help people like siraj-samsudeen, who wrote on the forum:
What I'm trying to do when I decide what to include and what not to do is go back to this explanation of the idea by Jeremy. But, as I said, each track is different. As you are leading the Elixir one, I wonder what you think about it. If you don't normally look at approaches, the question might be more what you think about what I'm proposing here. If it works, I'll try to stay consistent from now on.
Yes, both. I'm trying to be informative but not to explain everything that can be linked. I am also trying to limit the links to exercism and hexdocs. |
I have adjusted the text to make it clear that while there are many ways to use a case statement, the case on the tuple is the most idiomatic one.
@angelikatyborska, it's been a long thread. Thanks for all the feedback. To help finalise this PR I think we are down to four things to decide on / adjust.
I'd like to finish this before the end of the weekend if you are available. I'll be available from time to time until about 20:00 today (your time). Tomorrow I will be available much less, mostly in the evening. |
If you want to take the detailed approach, I'm perfectly fine with that. I will just make sure that all the information in there is correct and consistent with the other docs 🙂
To answer shortly:
I'm fine with keeping it short as long it's accurate, "clauses" is short and accurate, so go for that!
It was just a nitpick, not a problem, can stay!
also can stay
alright I'll try to double-check the links later today and I'll make sure that the PR gets merged until the end of the weekend 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed two tiny commits with some reformatting and grammar fixes so that it's faster than leaving comments about them.
I have no thoughts about the links 😅 looks fine to me.
Let's merge and see how it looks on the website, maybe people will have some feedback.
I'm approving and you can press the merge button when you're ready 🚀
Hmm, or maybe not, let's see those CI failures 🙃 |
Right, the link checker is going to fail because there are links to the new content that's not online yet:
We can ignore that and merge anyway |
@angelikatyborska I cannot merge, you'll have to do the button pushing. |
Ah shit, sorry, I keep forgetting how it works with permissions 😬 |
It is live: https://exercism.org/tracks/elixir/exercises/leap/dig_deeper thanks again! first ever Elixir approaches :) |
[boolean-operators]: https://hexdocs.pm/elixir/operators.html#general-operators | ||
[operators-approach]: https://exercism.org/tracks/elixir/exercises/leap/approaches/operators | ||
[clause-approach]: https://exercism.org/tracks/elixir/exercises/leap/approaches/clauses | ||
[flow-approach]: https://exercism.org/tracks/elixir/exercises/leap/approaches/cond |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one broken link snuck in to main
. Could you open a PR with a fix? If you do it, I can just merge, but if I do it, I will need to wait for another person with write rights to review because I can't approve my own PRs 😇
This resolves #1400
I propose an introduction to the approaches and specific approaches to the problem.
Considering the time until 48in24 I welcome early feedback on the text and the selection of the approaches.
I will work on specific approaches in subsequent commits.
The difference between
rem/2
andInteger.mod/2
might be an interesting article to enrich the deep dive, however, due to time constraints and the need to write up approaches in other languages, I consider it out of scope for this PR.