[rust-dev] How to write Generic traits for enums

Aravinda VK hallimanearavind at gmail.com
Tue Jul 22 10:15:32 PDT 2014


Hi Felix,

Just now got a doubt. Since we know the type of enum during compile time,
is it not possible to get the value from enum. Something like this..

enum MyTypes{
    MyBool(bool),
    MyStr(String),
    MyInt(int)
}

let a = MyBool(true);
a.get_value();  // trait for enum

let b = MyInt(100);
b.get_value();

Do you think it is possible to implement?



On Tue, Jul 22, 2014 at 9:37 PM, Aravinda VK <hallimanearavind at gmail.com>
wrote:

> Hi Felix,
>
> Thanks a lot for the detailed explanation.
>
>
> On Tue, Jul 22, 2014 at 7:08 PM, Felix S. Klock II <pnkfelix at mozilla.com>
> wrote:
>
>> Aravinda (cc’ing rust-dev)-
>>
>> It seems like you are trying to program in Rust as if it were a
>> dynamically-typed language, or one with runtime-type reflection (i.e. like
>> Java).  At least, that is my best guess at where your misunderstanding lies.
>>
>> All functions in Rust, even generic ones, need to have their types
>> resolved at compile-time.  A generic function can have different concrete
>> types substituted in for its type parameters at different call-sites, but
>> in the end, a particular call-site needs to resolve to a single type at
>> compile-time; the type cannot be left for later resolution at program
>> runtime.
>>
>> In a signature like your:
>>
>>     fn get_value(settings:HashMap<String, MyTypes>, key: &'static str) ->
>> T;
>>
>> the particular instance of `MyTypes` that is returned will depend on
>> which `key` is passed in; therefore, the `T` above could only be
>> dynamically determined based on the runtime computation.  It inherently
>> cannot be resolved at compile-time, and therefore it is not statically
>> typed.
>>
>> ----
>>
>> Rust is not alone in offering this kind of generic types; many
>> programming languages use a similar logic for determining types at compile
>> time.  It just gets fuzzy if one is used to languages that maintain types
>> at runtime and do not enforce restrictions like the one I outlined above.
>>
>> These type systems are often said to offer “parametric polymorphism”; I
>> mention that solely to give you some guidance for a term to search for when
>> goggling this subject.  (Though I will say up front that a lot of the
>> results you get on this topic can be very academic and language
>> research-oriented.)
>>
>> Here is a tutorial that may help you get a handle on the concepts here:
>>
>>   http://lucacardelli.name/Papers/BasicTypechecking.pdf
>>
>> (Yes, it is from 1987.  I think that is why it probably one of the better
>> descriptions I was able to find quickly: At that time, these ideas were not
>> as widely popularized as they were today, so Cardelli took his time
>> explaining the notions and assumed little about the audience.)
>>
>> rust-dev members: If others know of freely available introductions to
>> this topic, I’m all ears; I just didn’t see any obvious winners in my
>> searches.
>>
>> Cheers,
>> -Felix
>>
>>
>> On 22 Jul 2014, at 14:24, Aravinda VK <hallimanearavind at gmail.com> wrote:
>>
>> Sorry for the incomplete mail.
>>
>> What I wanted is,
>> get_value(MyStr("Rust".to_str())) returns String,
>> get_value(MyBool(true)) returns bool and,
>> get_value(MyInt(100)) returns int
>>
>> I was trying to store generic value in hashmap, as in the example below,
>>
>> use std::collections::hashmap::HashMap;
>>
>> #[deriving(Show)]
>> enum MyTypes{
>>     MyBool(bool),
>>     MyStr(String),
>>     MyInt(int)
>> }
>>
>> fn main(){
>>     let mut settings:HashMap<String, MyTypes> = HashMap::new();
>>
>>     settings.insert("port".to_str(), MyInt(8000));
>>     settings.insert("name".to_str(), MyStr("Rust".to_str()));
>>     settings.insert("enabled".to_str(), MyBool(true));
>>
>>     println!("{}", settings);
>> }
>>
>> So to get the value out of hashmap, I need a generic function which
>> checks the respective type and returns value. Some thing like
>>
>> fn get_value(settings:HashMap<String, MyTypes>, key: &'static str) -> T{
>>     match settings.get(&key) {
>>         MyBool(x) => x,
>>         MyStr(x) => x,
>>         MyInt(x) => x
>>     }
>> }
>>
>> But I don't know how to make this work.
>>
>> Thanks.
>>
>>
>>
>> On Tue, Jul 22, 2014 at 4:55 PM, Felix S. Klock II <pnkfelix at mozilla.com>
>> wrote:
>>
>>> Aravinda (cc’ing rust-dev)-
>>>
>>> You didn’t show us exactly what you had tried to do to get your code to
>>> work, nor did you really describe what it is you want here.
>>>
>>> E.g. you seem to want `get_value(MyBool(true))` to return a boolean, but
>>> since `MyBool` belongs to the `MyTypes` enum, that implies that `get_value`
>>> when applied to any variant of `MyTypes` (including `MyInt` or `MyStr`)
>>> should also return a boolean … does that seem right to you?
>>>
>>> In any case, I suspect the missing piece of the puzzle for you is that
>>> you need to write an `impl` for the type in question.  I.e. something along
>>> the lines of:
>>>
>>> impl MyTypes {
>>>     fn render(&self) -> String {
>>>         match *self {
>>>             MyBool(x) => format!("{:b}", x),
>>>             MyStr(ref x) => x.clone(),
>>>             MyInt(x) => format!("{:d}", x),
>>>         }
>>>     }
>>> }
>>>
>>> (except revised from an Impl for the type to being an impl of some trait
>>> for the type).
>>>
>>> Here is a link to a playpen with your code, and with a couple of example
>>> `impl`s for enums (like the one above) tossed in, including an impl of one
>>> instance of your `Value<S>` trait.
>>>
>>>   http://is.gd/RofN9R
>>>
>>> There is more discussion of writing implementations that also provides
>>> an example with a simpler enum) in the Rust tutorial, see:
>>>
>>>   http://doc.rust-lang.org/tutorial.html#methods
>>>
>>> Cheers,
>>> -Felix
>>>
>>> On 22 Jul 2014, at 11:45, Aravinda VK <hallimanearavind at gmail.com>
>>> wrote:
>>>
>>> > Hi,
>>> >
>>> > I am trying to create a generic function to return value depending on
>>> the enum passed. But I don't know to create a generic trait for enum.
>>> >
>>> > In following example, print_value works but I don't know how I can
>>> write a generic get_value function to get value from enum.
>>> >
>>> > #[deriving(Show)]
>>> > enum MyTypes{
>>> >     MyBool(bool),
>>> >     MyStr(String),
>>> >     MyInt(int)
>>> > }
>>> >
>>> > fn print_value(arg: MyTypes){
>>> >     match arg{
>>> >         MyBool(x) => println!("Bool: {}", x),
>>> >         MyStr(x) => println!("String: {}", x),
>>> >         MyInt(x) => println!("Int: {}", x),
>>> >     }
>>> > }
>>> >
>>> >
>>> > fn main(){
>>> >     print_value(MyBool(true));
>>> >
>>> >     // Following lines not working, how to write get_value func?
>>> >     // let a: bool = get_value(MyBool(true));
>>> >     // println!("{}", a);
>>> > }
>>> >
>>> >
>>> > In case of struct it is simple,
>>> >
>>> > struct MyInt {
>>> >     value: int
>>> > }
>>> >
>>> > struct MyBool{
>>> >     value: bool
>>> > }
>>> >
>>> > trait Value<S>{
>>> >     fn get(&self) -> S;
>>> > }
>>> >
>>> > impl Value<int> for MyInt{
>>> >     fn get(&self) -> int{
>>> >         self.value
>>> >     }
>>> > }
>>> >
>>> > impl Value<bool> for MyBool{
>>> >     fn get(&self) -> bool{
>>> >         self.value
>>> >     }
>>> > }
>>> >
>>> > fn get_value<S, T: Value<S>>(arg: T) -> S{
>>> >     arg.get()
>>> > }
>>> >
>>> > fn main(){
>>> >     let a: bool = get_value(MyBool{value: true});
>>> >     println!("{}", a);
>>> >
>>> >     let b: int = get_value(MyInt{value: 100});
>>> >     println!("{}", b);
>>> > }
>>> >
>>> > Please help in writing generic function for enum.
>>> >
>>> >
>>> >
>>> > --
>>> > Regards
>>> > Aravinda | ಅರವಿಂದ
>>> > http://aravindavk.in
>>> > _______________________________________________
>>> > Rust-dev mailing list
>>> > Rust-dev at mozilla.org
>>> > https://mail.mozilla.org/listinfo/rust-dev
>>>
>>>
>>
>>
>> --
>> Regards
>> Aravinda | ಅರವಿಂದ
>> http://aravindavk.in
>>
>>
>>
>
>
> --
> Regards
> Aravinda | ಅರವಿಂದ
> http://aravindavk.in
>



-- 
Regards
Aravinda | ಅರವಿಂದ
http://aravindavk.in
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140722/053bc49a/attachment.html>


More information about the Rust-dev mailing list