Feat/coerce
Here, I am trying to address https://github.com/dgkf/R/issues/69
Overview:
- Add
Comparable,InterpretableAsLogical,CoercibleToNumerictraits (I am not too confident yet in whether I like it how it is) - Add a
typeprimitive, e.g.type(1L)returns"integer" - Add the
r_vec!macro, which is relatively convenient
Open questions:
- do we really want
"1" == 1to returntrue? I think this should throw an error - I am not even sure if we should allow comparing logicals with numerics.
Edit: I think we could understand
doubleas a subtype ofintegerandintegeras a subtype oflogical. This means I think we should allow for comparisons of logicals with numerics. - how to treat
null. In Rnull == nullornull == 1returnslogical(0), which is a footgun I think.
Other comments:
- I think the trait implementation of
Comparable,OrderableandCoercibleToNumericmight be expressed more elegantly if we implemented each primitive type as its own struct and then modelObjas a trait as we have discussed elsewhere. This would then allow acoercionimplementation analogous to the one forvectors here https://github.com/dgkf/R/blob/7b424191218c3512bf8c3f4b78f893526e75df97/src/object/vector/coercion.rs#L143-L148. But maybe I now simply have a hammer and everything looks like a nail :D
Notes to myself:
- ~~I have introduced this:~~
> 2 == true [1] false > 2 != true [1] false - It would be convenient to have
all()andidentical()/equal()primitives for the tests
Would you consider using class in place of type? I know that’s a divergence from R, but I’m continually befuddled by Rs mismatched mode/class - especially for numerics - and have been considering consolidating these all under a single function. Whether it’s class or type, I don’t really have a strong preference, but if like to reduce the dimensions of the class inspection.
Would you consider using
classin place oftype? I know that’s a divergence from R, but I’m continually befuddled by Rs mismatched mode/class - especially for numerics - and have been considering consolidating these all under a single function. Whether it’s class or type, I don’t really have a strong preference, but if like to reduce the dimensions of the class inspection.
This is a great idea! I think I would tend to type instead of class because I think it would really be great if we could eventually implement some simple type system similar to the one suggested by Jan Vitek.
I was exploring the possibility to implement Obj as a trait, but I don't really think it works, at least not easily (for me).
Let's say we haven a trait Obj and then two structs Character and Logical that implement the trait Obj.
If we then want to implement PartialEq for dyn Obj, we can try to downcast Obj to its concrete type using std::any::Any, but this means that the PartialEq implementation already needs to be aware of all the types that implement Obj and we need to cover all cases (I think), which means that there is not such a big advantage over the enum approach. Further, there would be the performance hit that you already mentioned.
Edit: I think I might just have used the wrong approach, but I guess it is still not worth it to invest the time to figure this out, as long as there is no clear need for it.
Out of curiosity, I also searched for other language implementations in rust, and the one that I looked at ("rhai") also represented the primitive types as an enum (https://github.com/rhaiscript/rhai/blob/614f8f004be0509902d2a80fc5b85e16cc6aeac7/src/types/dynamic.rs#L61-L103).
Maybe we can also learn something from their approach of encoding mutability into the language-type: https://github.com/rhaiscript/rhai/blob/614f8f004be0509902d2a80fc5b85e16cc6aeac7/src/types/dynamic.rs#L35-L40
However, I think it would be really cool if we could get rid of these kind of lines https://github.com/dgkf/R/blob/08e0c940c62e3d4ca226e74581473733f37efabc/src/object/vector/core.rs#L612-L620 One way would be to add macros, but I wonder if there is a more elegant way to achieve this, but maybe it is just necessary.
In rhai, they also offer a trait that can be implemented to support custom types: https://github.com/rhaiscript/rhai/blob/614f8f004be0509902d2a80fc5b85e16cc6aeac7/src/types/dynamic.rs#L98
And this method here might also be handy to implement for Obj: https://github.com/rhaiscript/rhai/blob/614f8f004be0509902d2a80fc5b85e16cc6aeac7/src/types/dynamic.rs#L261
Another thing that might help for a cleaner solution to the problem that I am trying to solve here, would maybe be to support iterators as a RepType. Currently, casting an Obj::Vector(Vector::Integer) to a Obj::Vector(Vector::Double) is expensive, because it needs to allocate the double. But if we allow for RepType::Iter, we can directly implement the converson mechanism on Obj.