-
Notifications
You must be signed in to change notification settings - Fork 135
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
Why does Zero::zero not take self? #272
Comments
Given the maturity and popularity of this crate, I'm looking forward to learning how to get out of my current train of thought. That said, I'm stuck on suspecting the design of the trait made an assumption that could be flawed. I get how Enums and traits are ways to unify behavior across types. Has the design over-looked how an enum might need an identity element for each variant? |
For any other use case but yours, it seems weird to have to have a value of your numeric type in order to call |
It's meant to be able to manifest a zero out of thin air -- e.g., Does your |
Thank you for thinking through this with me.
Great question: How might an operation between variants enable the implementation? I can imagine starting with a chosen variant then cast? I don't have an answer but in my recent experience with using Notwithstanding, I say compelling because the I was able to find a way to implement So far, my codebase without using the enum is much larger. The design constraint stems from the fact that we don't have access to the context. Maybe it makes sense to include the identity value with the traits that specify a numeric operation? Finally, this is more of an "And", an extra function with a default implementation that uses N::zero()? |
If your |
FWIW, here's a real use of getting zero without any "reference" value: |
I was not intending on it. But, great idea. I guess I could implement the binary operation traits such that they allow a mix of variants in a way that allows me to use the variant that hosts the return value of Zero::zero(). |
You could also have a special |
@cuviper Thank you for identifying a work-around. This experience motivated me augment my intuition for generic code in Rust (and in part by contrasting it with my experience in Haskell). In Haskell there was a bit of a debate of when it made sense to use type classes instead of "regular" types. A respected point of view suggested the over-use of type classes. In Rust, traits take on a whole other level of importance and have a lot more "natural" utility. I'm providing this preamble to contextualize the following which might be a bit clumsy in how I articulate the point, but here goes. Just to level-set, generic code is not inherently better. In other words, it's not a given that it makes a codebase more extensible (it often can, but not always). A bias or reasonable starting point => use concrete types if it does the job. Error messages and many other benefits exist with concrete types - if it does the job. Unifying typesIf the need is to provide a means to unify a collection of types we have enums. The reason not to use an enum is if we can't know all of the possible/potentially useful types a user might want to include. Furthermore, extending an enum requires an update to the code base; something that can be avoided using traits. Enum is a natural choice working with numbers - we know the types ahead of time (primitives don't change much)The punchline: when working with numbers, we know ahead of time what we need to support: Keeping this issue open to allow for future considerationI'm sold on the benefit of the current design; FodderGetting around the need to access a context with
Alternatively, formalize the work-around you proposed using a "dummy type" (e.g., ZERO) where I then have the infrastructure required to specify |
@EdmundsEcho expressing what you want would be natural with variant types, since you could impl Unfortunately, they are only a hypothetical unimplemented feature. |
I agree. This whole thread would be moot if variants were an option. I suspect that this feature won't be coming anytime soon. As long as the implementation requires treating variants as separate types it gets messy mostly b/c it defeats the purpose (type unification). Users of num-traits always have access to Self, at some point - eg fold I wonder if providing an If not doing some sort of generic construction, the user will have access to self. In my case I was instantiating ... this option does not obviate the need for the Iterator. What other use cases exist? |
I have an enum type that wraps various Number like types. I was hoping the return value of Zero::zero would depend on the variant. Because the function does not take self, there is no way to perform a match... This "dead-end" if you will is having me both post this question, and suspect I should be approaching my task differently.
Any comments/suggestions would be appreciated.
The text was updated successfully, but these errors were encountered: