Skip to content

sublist: Added template to the stub file#610

Merged
coriolinus merged 3 commits intoexercism:masterfrom
ZapAnton:sublist_template
Aug 30, 2018
Merged

sublist: Added template to the stub file#610
coriolinus merged 3 commits intoexercism:masterfrom
ZapAnton:sublist_template

Conversation

@ZapAnton
Copy link
Copy Markdown
Contributor

@ZapAnton ZapAnton commented Aug 8, 2018

Contributes to #551

Comment thread exercises/sublist/src/lib.rs Outdated
Unequal,
}

pub fn sublist<T: Debug>(first_list: &[T], second_list: &[T]) -> Comparison {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

it's a little unfortunate - normally it would not be necessary to restrict this to Debug but it is done for the sake of being able to reference it in the unimplemented message

We explicitly made a different choice in c5f7a43 . We chose to use underscore prefix for this

I would find using an underscore prefix acceptable. I'll take some time to think about whether it is preferable over adding the Debug constraint. Input appreciated.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Some points why I think Debug could be preferable:

  • The lists from the test suite contain only primitive types, each of them implements Debug. If the test suite is extended with some custom types (unlikely) it should not be that hard to derive the trait for the new type.
  • It could help students in debugging their solutions in case they want to print the input arguments
  • It increases learning for the students who may have forgotten about the trait bounds

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The axiom that @petertseng and I are working from is that when possible, one should implement one's library with the minimally restrictive trait bounds which enable it to work. In other words, a library should attempt to function for the largest possible range of types. This is because, while a more restrictive trait bound may be fine in the moment, you don't know the circumstances in which the library will be used in the future.

You're right that for the purposes of this exercise, Debug would be fine. However, one of our design goals in the Rust track is to model good engineering principles. Say you write a library which bounds its generics on Debug. A user Alice wants to use your library, but she hasn't written the type she's using; it comes from a third-party library which she doesn't control. By misfortune, it doesn't implement Debug. Alice is out of luck.

I've temporarily added a Debug trait bound for debugging while writing my own code. Sometimes println debugging is a useful technique! However, I always try to remove it before committing; it's not good practice, and it's not what we should be modeling.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. I will remove the trait bound then.

Although I suspect in your example Alice could still implement a trait for third-party type, since that's what the trait system is about, but I think this argument could wait for now.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You can't implement a foreign trait for a foreign type, though. What you could do is write a wrapper, implement Debug for that and painstakingly re-implement the rest of the behaviour to forward to the internal type. The contained type would still be opaque to Debug, but at least it would work.

@lqdee
Copy link
Copy Markdown

lqdee commented Aug 19, 2018

Should the type restriction in sublist include PartialEq? I think I had to add it when solving this one but maybe my solution is not the best :)

@petertseng
Copy link
Copy Markdown
Member

I can confirm two things:

Must a valid solution to this exercise do so?

If so, is it better to include it or leave it off?

@ZapAnton
Copy link
Copy Markdown
Contributor Author

@petertseng, as per @coriolinus comment the amount of trait bounds should be minimized and I think this means we should leave off the PatrialEq trait, so not to restrict potential solutions.

@coriolinus
Copy link
Copy Markdown
Member

I believe that for this exercise, PartialEq is required for a valid solution. Is there more pedagogical value for this exercise in leaving it out, requiring that the student add a minimum viable trait set, or in including it for student convenience?

@ZapAnton
Copy link
Copy Markdown
Contributor Author

I will add the PartialEq then.

There are only two moments of concern for me:

  • Reduced learning. Will the presence of the trait bound reduce the learning for the student (for instance will they learn what is the difference between ParialEq and Eq?).
  • Reduced experimentation. Maybe there is a way to complete the exercise without the use of PartailEq?

For now I think the answers could be:

  • The point of Exercism is for students to become fluent in a language. This means they should quickly find the suitable instruments for the given problem, without delving too much in the language internals.
  • This case is too exotic, and if the student wants to go this way, nothing stops them from editing the template.

@Emerentius
Copy link
Copy Markdown
Contributor

  • Reduced learning. Will the presence of the trait bound reduce the learning for the student (for instance will they learn what is the difference between ParialEq and Eq?).

We could add only the type for the very first test and let the student add the generics bound to make the other tests compile. The issue of the difference between PartialEq and Eq can be forced by one of the later tests by using a non-Eq type.

  • Reduced experimentation. Maybe there is a way to complete the exercise without the use of PartailEq?

I really don't see how

@ZapAnton
Copy link
Copy Markdown
Contributor Author

I really don't see how

Just from top of my head: computing a hash of every object and comparing hash values

@Emerentius
Copy link
Copy Markdown
Contributor

True, that approximates it. It's not quite the same algorithm though, because it's probabilistic and can have false positives.

Copy link
Copy Markdown
Member

@coriolinus coriolinus left a comment

Choose a reason for hiding this comment

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

This PR looks good to me. There is obviously some open discussion (#631) about what trait bounds are appropriate, but this subjectively seems to get the balance right.

I intend to merge within the next 48 hours. I have no objection if another maintainer wants to merge sooner.

@coriolinus coriolinus merged commit 5eeddc5 into exercism:master Aug 30, 2018
@ZapAnton ZapAnton deleted the sublist_template branch August 30, 2018 20:48
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.

5 participants