12

I'm having a lot of fun playing around with Rust having been a C# programmer for a long time but I have a question around reflection. Maybe I don't need reflection in this case but given that Rust is strongly typed I suspect I do (I would definitely need it in good ol' C#, bless its cotton socks).

I have this situation:

use std::collections::HashMap;

fn invoke_an_unknown_function(
    hashmap: HashMap<String, String>,
    // Something to denote a function I know nothing about goes here
) {
    // For each key in the hash map, assign the value
    // to the parameter argument whose name is the key
    // and then invoke the function
}

How would I do that? I'm guessing I need to pass in some sort of MethodInfo as the second argument to the function and then poke around with that to get the arguments whose name is the key in the hash map and assign the values but I had a look around for the reflection API and found the following pre-Rust 1.0 documentation:

None of these give me enough to go on to get started. How would I implement the function I describe above?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
kmp
  • 10,535
  • 11
  • 75
  • 125
  • 2
    Rust does not have well-developed reflection capabilities. They are deemed something that should largely not be used, and so regardless of whether or not we have such functionality eventually, it's certainly not a priority. At present, what you are trying to do cannot be done, and I think it's fair to say that 1.0 won't have it either. – Chris Morgan Dec 08 '13 at 10:50
  • Thanks @ChrisMorgan - I'll stop looking for it then and ponder if I can achieve my goal in a slightly different way. – kmp Dec 08 '13 at 13:27
  • (I find that often traits and trait objects can be used to achieve goals similar to what people would use reflection for, though it's certainly not universally true.) – Chris Morgan Dec 08 '13 at 22:05
  • 4
    Using reflection is generally a bad thing, even in languages like C# or Java. Generally, one uses reflection to express things that are beyond the capabilities of the (static) type system, which is why it is mostly popular in dynamic languages. Rust's type system is far richer than either C#'s or Java's (primarily due to the decoupling of structs from traits for them), let alone unityped languages, and, in my experience, reflection would not achieve anything useful that cannot be done using less heavy-handed features. – isekaijin Dec 17 '13 at 03:21
  • 19
    @EduardoLeón: Reflection is a useful tool for generating interfaces, such as serializers, deserializers, foreign code interfaces, web services, plugins. One could equally say that "allocating memory is generally a bad thing", which is true, except for the fact that it's so darn useful. – Dietrich Epp Jan 05 '14 at 09:05

1 Answers1

9

Traits are the expected way to implement a fair amount of what reflection is (ab)used for elsewhere.

trait SomeInterface {
    fn exposed1(&self, a: &str) -> bool;
    fn exposed2(&self, b: i32) -> i32;
}

struct Implementation1 {
    value: i32,
    has_foo: bool,
}

impl SomeInterface for Implementation1 {
    fn exposed1(&self, _a: &str) -> bool {
        self.has_foo
    }

    fn exposed2(&self, b: i32) -> i32 {
        self.value * b
    }
}

fn test_interface(obj: &dyn SomeInterface) {
    println!("{}", obj.exposed2(3));
}

fn main() {
    let impl1 = Implementation1 {
        value: 1,
        has_foo: false,
    };
    test_interface(&impl1);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Sean Perry
  • 3,776
  • 1
  • 19
  • 31