Hi! I use F# for most tasks (from websites/JS generation, to packet capture and indexing, call routing and billing processing), and some C where required. Rust looks fantastic, and would give me the memory control I need when I need extra performance. A LOT of it comes down to simply being able to stack-allocate things; in F# I'm essentially forced to use the GC heap for even the most trivial things.
Rust looks fantastic, and I'm very excited about using it. When I found out about it and started reading how it worked, it was almost exactly what I had been wanting, on almost every count. I really wish it had existed a few years ago.
My comments are from someone that's just been playing around with the getting started guide of Rust.
-- Lack of custom operators limits expressiveness. For instance, look at Parsec or FParsec. Why shouldn't they be allowed to exist in Rust? But if custom operators are totally out of the question, then what about user-defined infix functions? (And then, why not functions with nearly arbitrary codepoints as identifiers?)
-- It seems that currying, partial application, and function composition are sorta cumbersome in Rust. Is this a conscious decision, that idiomatic Rust shouldn't be doing such things? Like " add >> inc >> print " being equivalent to "|a,b| -> print(inc(add(a,b)))" ? In F# I use this kind of stuff all the time, especially when processing lists.
-- It seems there's a difference between function types. Like if I do "fn foo(a:int, f:proc(int)->int)", I can call it with foo(1i, inc) if inc is a fn. But if I first do "let f = inc; foo(i1, f)", that's an error. Offhand, I'd assume this is due to lifetime management, but it feels a bit strange. When writing HoFs, do I need to implement a version for each kind of function? Or am I totally misunderstanding things?
-- Sorta related, does Rust allow something like:
let inc =
let x = ~0
|| { let res = *x; *x += 1; res }
The idea is to expose a function that contains some private state. I remember hearing that Rust changed the ownership stuff around a few times, but the basic idea is to create a globally-accessible closure. Is this impossible, requiring us to use statics to store the global state?
-- Why doesn't Rust warn when discarding the result of a function if not unit? Is it idiomatic Rust to return values that are often ignored?
-- Even without higher kinded types, monadic syntax is useful. Is Rust planning any sort of syntax that'd let users implement Option or Async? How does Rust avoid callback hell? Or is this quite possible today with macros and syntax extensions?
-- Has Rust considered Active Patterns (ala F#)? With that, I can define arbitrary patterns and use them with matching syntax. E.g. define a Regex pattern, then "match s { Regex("\d") => ... , Regex("\D") => ... , _ => ... }"
-- Consider allowing trailing commas in declarations; why special-case the last item?
-- And last but not least: Please, please, please, reconsider type inference. It's baffling why "fn" requires type annotations, but a closure does not. What's more, why is there even different function syntax in the first place? I've heard the reason that "top level items should have types documented", but that's a very personal decision to make. It certainly isn't something the Rust compiler should force me to do in all my code. Why do ya gotta limit my expressiveness? (Same argument I'd use for custom operators.) Statics/consts should also have type inference. And note that these items aren't necessarily public or exposed - but a private fn on a module still requires type annotations.