Hi all, Rust was recently mentioned on reddit again (http://www.reddit.com/r/programming/comments/n4zsy/rust_a_safe_concurrent_practical_language_made/) so I decided to check in on its development by reading the tutorial. In general Rust looks to be progressing very nicely, and I had a few thoughts. I haven't searched the archives, so apologies if some of these suggestions have already been considered.
1. Supporting the ternary operator "?:" when "if" is already an expression seems redundant. "?:" causes confusion for C beginners, so I think it would in rust as well. If there is a behavior difference between the two that merits them both existing it would probably be worth mentioning this in the tutorial. If there is no difference I'd strongly suggest just sticking to "if"; operators are a rare commodity and there are lots of semantics "?" could be intuitive for (e.g. builtin optional<T>) 2. Inferring the type of 'x' in "let x = []" is neat, but is this type of inference a privilege restricted to the builtin types? (i.e. are you pulling a Go with generics inference instead of generics? ;) Can a user define a generic data structure where the type arguments can be inferred based on the structure's usage? If not I'd consider making it mandatory that the type is obvious from the constructor (you could still come up with ways that it needn't be explicitly specified, like passing the 'default' value and inferring on that). 3. The subject says semantics but this is really a syntax objection. I think "3 as float" will ultimately be a language wart, because 'as' will be the only operator that operates on a runtime value (3) and a compile time type (float) with the same infix syntax as regular operators that only operate on runtime values. For generics you've already established the C++/Java style Foo<T> syntax, so why not use this for 'as' as well: "as<float>(3)" . As an added bonus the syntax becomes more intuitive for C++ users accustomed to static_cast, etc. 4. target_os and similar attributes may seem convenient but I suspect will have Rust biting off more than it can chew. What version of win32 does target_os="win32" mean? It's typical for projects to have separate builds for Win95, Vista, etc. Generally speaking the whole approach of toggling things based on the OS target is frowned upon compared to testing for features with configure tests. Getting results of configure tests into the compiler and having them affect the code in a more robust way than the C preprocessor's text snipping and find-replace hackery (e.g. config.h and #ifdefs) seems like a better problem to solve. If you could make the inclusion of a function definition dependent on looking up a value in a dictionary file, something like "#get_config_result(has_pthreads)", that might be sufficient. The idea of an attributes mechanism in general though is a good one. 5. bind as described (using only _ to indicate a missing argument) doesn't let you change argument order, which you can do with boost::bind. I don't whether or not this is an essential feature, I'm just pointing it out. With boost::bind you can do "auto print_args_reverse = boost::boost_bind(&print_args, _3, _2, _1);" Looks like you guys are already considering removing bind, just using lambdas instead would solve this, but I haven't thought the memory management implications through so I'm holding back from suggesting bind be removed. 6. Having curly braces after a function act as an implicit block parameter is sweet. If I'm not mistaken though, you can use them to build python like context handlers. Instead of using a resource, you can write a function that takes a block, allocates some resource, executes the block, then frees the resource. Though maybe this is frowned on due to exceptions (if the block throws the free will never run)? The tutorial didn't mention whether Rust is going to have them. Anyway, if it is useful for inserting before/after behavior (e.g. glBegin/glEnd) that seems worth mentioning. 7. Not sure if this is intentional or an oversight: but it looks like there's no way to extend a polymorphic data type while maintaining independent compilation. Tags let you make an abstract type with several concrete subtypes, but all possible subtypes have to be declared where the tag is declared. This is the trade off between variants and abstract bases with virtual functions -- the former you can know if you've covered all types when destructuring, but the latter you can extend outside of the original declaration. 8. Having a 'cycle collector' for shared box types seems as bad as having a garbage collector. The advantage of having reference counting is supposed to be determinism -- if you're going to have something nondeterministically freeing some objects (or is there a predictable semantics for when cycle detection will run?) you may as well go whole hog. I'm not sure if Rust's semantics make it possible to statically detect if cycles are possible, though that would be nice. The compiler could check for cycles in the types, so that a shared Foo couldn't directly or indirectly point to other shared Foo's, or at least only weakly to them (adding a concept of weak references), but that could be tricky depending on your compilation model and you could be forced to use weak references in instances where you know a cycle will really never occur. 9. I'm curious as to the justification for making log a builtin keyword rather than a builtin library. What is gained by giving the compiler direct awareness of logging? Having a mechanism for converting types and expressions to pretty string representations is definitely worthwhile (I've contributed code to the Toast C++ library to add this capability to C++ and it was invaluable for serialization and log messages when doing policy based programming where the type can totally describe a class's behavior), but seems oddly conflated with logging. Unless you have plans for the compiler to say, patch the code at runtime based on log level to overwrite log calls with nop instructions (like the Linux kernel) to avoid the performance hit of branching, then this seems like an odd choice (and even then it'd be cooler to provide a non-logging specific mechanism for patching away branches). Most heavy duty apps will need fairly customized logging and you don't want the compiler to have to support all the possible output types (file, syslog, zeromq, database, etc.). _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
