Type inference for private functions?


#1

I feel that prototyping is hampered by not being able to quickly move some code to a function to save some repetition.

Once I type out the type signature for the function, it is actually longer to abstract something into a function than to just leave it in-line. Even if I do it twice, the type signature for doing something with 4-5 variables is going to be longer than the actual function body.

I tried to persevere and to actually do it in FizzBuzz:

https://bitbucket.org/iopq/fizzbuzz-in-rust/src/b5e7b36cdb2ac0e88e1802a0b3547f90184f7e09/src/lib.rs?at=master#cl-39

the result is super gross

fn accumulate<'a, T: Monoid>(tuples: &[(&'a str, &Fn(i32) -> bool)], i: i32) -> Option<T> 
        where &'a str: Into<T> {
    tuples.iter().fold(None, |acc, &(concat_str, include_fn)|
        append(acc, concat_str, include_fn(i))
    )
}

these two lines take a monstrosity of a type signature for just two parameters

in fact my entire program written in line is just a few lines of code, most of the characters in my program are types I understand that I should be clear in my pub fns because that’s my contract with the rest of the world, but I feel like my own private functions should give me type inference

this doesn’t just affect toy examples, the Go game AI player I’m working on:

I feel like I’m committing atrocious duplicated code in it because writing a function is actually longer and takes more time and effort and ends up being longer and possibly more difficult to read than just copy pasting two lines of code

This is a bad thing because duplicated code is harder to maintain. I would just write a macro, but macro definitions are also pretty gnarly-looking and they’re not hygienic in some regards.

Is there any other way for me to solve my issue that I’m overlooking?


#2

A good reformatting tool should at least remove the drudgery of writing out all the types, although your program still has them written out (I personally think that’s a good thing, but I appreciate opinions vary).


#4

How would that affect incremental compilation? The self-sufficiency of function definitions looks like an important property for enabling function-level granularity in incremental compilation. (IIRC, it was discussed the incremental compilation RFC)


#5

That’s a good point. I would like to use fn foo from pub fn bar and pub fn baz. Is it possible to incrementally compile just foo, bar, baz instead of compiling the whole mod?


#6

Then my function signature would still be as long as the body of the function. Why does the person reading my code need to know all of these details? They’d know them if they just read the pub fn cowbuzz definition without unnecessary clarifications like &'a str: Into <T> because they already know that Cow impls Into, that’s kind of the point of the type. I would say that most of that information is necessary for the compiler, not the programmer. As a programmer I would be completely satisfied with:

fn accumulate(tuples, i) {
    tuples.iter().fold(None, |acc, &(concat_str, include_fn)|
        append(acc, concat_str, include_fn(i))
    )
}

look how much cleaner that reads


#7

Found the link to the video where the importance of refactorability of closures into the module scope was explored: http://www.reddit.com/r/rust/comments/2nhp3k/jonathan_blow_on_declarations_and_factorability/

Would be nice to have this in Rust.