-
Notifications
You must be signed in to change notification settings - Fork 519
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
Twofer exercise #520
Twofer exercise #520
Conversation
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.
Hi @AvasDream, thanks for contributing this! There are a few points which need some improvement, but overall, this looks pretty good.
exercises/twofer/Cargo.toml
Outdated
@@ -0,0 +1,5 @@ | |||
[package] | |||
name = "twofer" | |||
version = "0.1.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.
This should match the version in canonical-data.json
.
exercises/twofer/example.rs
Outdated
@@ -0,0 +1,6 @@ | |||
pub fn twofer(name: &str)-> String { | |||
return match name { |
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.
return
is unnecessary here.
exercises/twofer/src/lib.rs
Outdated
@@ -0,0 +1,3 @@ | |||
pub fn twofer(_name: &str)-> String { |
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.
Instead of using an underscore prefix for the variable, try to fit it into the unimplemented
statement. It's fine to get cute with it: unimplemented!("One for {}, one for me.", name)
.
config.json
Outdated
"difficulty": 1, | ||
"topics": [ | ||
"Strings", | ||
"match" |
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 suggest using the topic "string interpolation" here instead of "match": solutions will almost certainly use string interpolation, but I'd expect a good portion of implementers to use an if statement to solve this instead of a match.
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 is a suggestion, not a requirement; feel free to ignore if desired.
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 like to make explicit a decision that has been implicitly made here:
Given that this exercise is to be placed early in the track, is it too early of a point to introduce Option?
If it is too early, no change to be taken in response to this comment. (Or maybe a code comment explaining that ""
is not the best way to represent the absence of a string, but better ways will be shown in later exercises?)
If it is not too early, the exercise should use it.
I thought about that. To my mind, using an Option here actually increases
the complexity: given Some(""), what should be returned?
…On Wed, Apr 25, 2018, 22:36 Peter Tseng ***@***.***> wrote:
***@***.**** commented on this pull request.
I'd like to make explicit a decision that has been implicitly made here:
Given that this exercise is to be placed early in the track, is it too
early of a point to introduce Option?
If it is too early, no change to be taken in response to this comment. (Or
maybe a code comment explaining that "" is not the best way to represent
the absence of a string, but better ways will be shown in later exercises?)
If it is not too early, the exercise should use it.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#520 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AHdeTsjz-a1vgH6oOPFJMc5Ro-jWB8Swks5tsN5jgaJpZM4Ti9EV>
.
|
I yield on that point, because while I personally have no qualms with saying that the answer should be I mentioned that I didn't like Some/None in our hello-world in exercism/problem-specifications#290 (comment). I would say the same thing here. Okay, in that case my only request for us keeping this exercise (I'd also like to explicitly call out the option of simply not having this exercise in this track) is one of the two following:
|
Right, that makes sense to me. I think that, were I to write the comment,
I'd structure it as an analogy: for some functions operating on numbers, 0
is outside the domain of the function, and can safely be used as a null
value. For others, 0 is within the domain, so Option _must_ be used if null
values are possible.
Even in the former case, it's still better practice to use an Option to
indicate the null value, but it's common to see this in code translated
from languages which do not possess monadic types. Likewise, there are two
categories of functions operating on strings: those for which the empty
string is within the domain of the function, and those for which it is not.
Twofer is an example of the latter. Even though it's better practice to use
an Option, we are intentionally structuring the API to avoid that
requirement to ease the burden on new learners.
…On Mon, Apr 30, 2018 at 10:34 AM, Peter Tseng ***@***.***> wrote:
given Some(""), what should be returned?
I yield on that point, because while *I personally* have no qualms with
saying that the answer should be "One for , one for me", the point of
your asking that question is to point out that the API incites such
questions, and is not to ask what the exact answer to the question is.
I mentioned that I didn't like Some/None in our hello-world in
exercism/problem-specifications#290 (comment)
<exercism/problem-specifications#290 (comment)>.
I would say the same thing here.
Okay, in that case my only request for us keeping this exercise (I'd also
like to explicitly call out the option of simply not having this exercise
in this track) is one of the two following:
- have a comment along the lines of saying that there are other ways
in Rust to indicate the absence of a value rather than using a sentinel
value, but those ways will not be covered in this exercise for simplicity
- explain to me that such a comment is actually not necessary for
certain reasons (don't confuse the student with unnecessary information,
etc., I'll let the person who explains it to me come up with the reason why
it's not necessary)
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#520 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AHdeTgNb1ibv6xTsTAlyibwHzMA28RNsks5ttsyrgaJpZM4Ti9EV>
.
|
Hi, i made the requested changes. |
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 @AvasDream for submitting this exercise!
I will now let it sit for about a week to ensure that other maintainers have a chance to take a look. If no issues come up in that period, I intend to merge this on 11 May; if on the 12th I still have not, please feel free to ping me a reminder.
I note that there is still no explicit discussion of the design choice to assign special meaning to the empty input string. Given that @petertseng has already specifically requested that, it would not surprise me if that became a blocking issue. However, I do not presume to speak for him.
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'm conflicted. The empty input string as a special case does not feel idiomatic rust for me. Without it there is no reason to use pattern matching though.
I think we can accept this PR in it current form, then later (yeah I know...) re-think the introduction exercise list and make adjustments if we see a bigger picture of how concepts are introduced.
@AvasDream We're performing some track maintenance in #528, and it is likely that this is going to require some action from you through no fault of your own. Sorry about that. There are two possible ways to ensure that this PR still passes Travis once #528 is merged:
|
|
||
#[test] | ||
fn empty_string() { | ||
assert_eq!(twofer(""), "One for you, one for me."); |
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.
explain to me that such a comment is actually not necessary for certain reasons (don't confuse the student with unnecessary information, etc., I'll let the person who explains it to me come up with the reason why it's not necessary)
I will consider the following part of #520 (comment) to comprise this explanation:
thought about this exercise as some kind of second "hello world" and introduction to pattern matching. In my opinion the Result/Some stuff is a more advanced concept and covered in later exercises.
I counter that it is still possible to say as a comment in this test "using the empty string as a sentinel value is not preferred in Rust since we have better ways to express the absence of a value, but we will learn those ways later in the track" without having to specify what those alternative ways are.
I cannot comment on what is the best way to teach students these concepts; I would have to spent time on improving my skills and knowledge before I can effectively spend time to think about and comment on how to teach.
Thus, it does not make sense for me to require any changes before this PR should be merged.
@AvasDream I've jumped in and made the necessary changes to I intend to merge as soon as Travis reports green status. |
Hello, i created my first exercise and would really appreciate your feedback.