Expect non_neg_integer instead of pos_integer#1571
Expect non_neg_integer instead of pos_integer#1571RemiBardon wants to merge 1 commit intoexercism:mainfrom RemiBardon:patch-1
non_neg_integer instead of pos_integer#1571Conversation
As [String — Elixir v1.18.3](https://hexdocs.pm/elixir/String.html#length/1) states, `String.length/1` returns a `non_neg_integer()`, not a `pos_integer()`.
|
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 PR touches files which potentially affect the outcome of the tests of an exercise. This will cause all students' solutions to affected exercises to be re-tested. If this PR does not affect the result of the test (or, for example, adds an edge case that is not worth rerunning all tests for), please add the following to the merge-commit message which will stops student's tests from re-running. Please copy-paste to avoid typos. For more information, refer to the documentation. If you are unsure whether to add the message or not, please ping |
| {:check_length, 2}, | ||
| ["word :: String.t(), length :: non_neg_integer()", "String.t(), non_neg_integer()"], | ||
| ":ok | {:error, pos_integer()}" | ||
| ":ok | {:error, non_neg_integer()}" |
There was a problem hiding this comment.
This task instructs a student to define a typespec for this function:
This is needed to check that the values of fields do not exceed the maximum allowed length.
It also tells you by how much the value exceeds the maximum.
A string can't exceed the maximum length by 0 and still be an error. So it was correct for the typespec to be a positive integer to exclude 0 from valid responses.
There was a problem hiding this comment.
If we look at implementation details, you’re correct, but in terms of types diff is a non_neg_integer(), per the spec of String.length/1. I was purely reasoning in types here.
There was a problem hiding this comment.
Coming from a Rust background, the tests didn’t behave as I was expecting, but maybe I’m wrong and it’s just not how it works in Elixir 🤷🏻♂️
There was a problem hiding this comment.
I’m not the experienced one here so I’ll be fine with whatever you find more correct.
There was a problem hiding this comment.
I don't think pos_integer() or non_neg_integer() is a type in the same sense as it is in rust. It's not a different data format, and pos_ and non_neg_ are communicating something about the expected value of the integer when it is part of the returned value. At this point there's no strict connection between the value returned and the type specified in the typespec attribute.
if we have non_neg_integer, we would have to cover the possibility of a {:error, 0} response when that's not an expected response from check_length/2
I think this will be more obvious in the future as set theoretic types are further fleshed out in future releases of the language, but for now this is is used as information for dialyzer, which performs static analysis on these types, function constructs, etc.
For now, I think it makes most sense to stick with pos_integer since 0 is excluded by the implementation.
There was a problem hiding this comment.
if we have non_neg_integer, we would have to cover the possibility of a {:error, 0} response when that's not an expected response from check_length/2
Good point. Makes sense why use pos_integer. Sorry for the disturbance and thank you for the links!
There was a problem hiding this comment.
No problem, no disturbance, thanks for the discussion!
neenjaw
left a comment
There was a problem hiding this comment.
See above comment.
There may be some uncertainty around the task which has prompted this PR, so I'm hesitant to close it without discussion. If there is something else in the wording of this task that might improve the task's clarity, I'm open to it.
As String — Elixir v1.18.3 states,
String.length/1returns anon_neg_integer(), not apos_integer().