Rust for C++ programmers – part 3: primitive types and operators
featherweightmusings.blogspot.com
featherweightmusings.blogspot.com
I think C99's way of handling that is fine, if you want to use whatever native width happens to be on your hardware you just use int/unsigned, otherwise you have stdint.h.
Like C, rust could mandate a minimal range for each type in the standard, but setting the type width in stone seems dangerous to me, both for backwards and forwards compatibility.
Or it could just forget 32bit hardware altogether. Even mobile phones are going 64bit already -- and the language will be ready for production in 1-2 years, where even more platforms will be 64bit.
It's not like they have to compromise just to be able to run on some embedded stuff.
The idea was in fact to reduce correctness gotchas; ints are often used for indexing into arrays, and you want the size of the integer to reflect the maximum size of an array on your platform.
What kind of security issues did you have in mind? Integer overflow can be a problem, but it is usually a memory safety issue, which Rust doesn't have due to bounds checks and iterators.
When a new language comes and the programmer is already having an intention to learn something new, probably is working on a new project, this state is the best opportunity for the cleanup. Once the language matures, legacy codebases become rampant, that opportunity is gone forever with that language.
Did you consider naming the type something like 'index' itself, if that is the predominant good use-case for the type?
If they're intended for indexing arrays, I would have given then a name to reflect that, and discouraged people from mixing them with normal integers for doing arithmetic with. Perhaps forcing people to convert integers to array indices would be good. I try to use size_t and friends when programming C++.
Turns out the package expected numbers, but sometimes a bug meant the data source would give arrays (of a single number each), the package's own max (using <) would perform a lexical comparison (comparison would coerce to string and a graph with a value at 800 and one at 1800 would pick a y-scale for 800 and cut off 1800) but further operations would coerce to number, so there was no error anywhere and most graphs looked correct.
return 10000 if x > 10000 else x
and it wasn't working because x was a string. Instead of raising an exception, though, Python decided that all strings are "greater than" all integers, and code was essentially equivalent to return xYep. That's one of the things they changed/fixed in Python 3, comparisons are not defined across and between any and all types:
>>> "foo" > 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unorderable types: str() > int()Also, having "<" and ">" also work for strings is another semantic abomination. You need different operators or just functions for doing this on strings (and if you treat strings as collections they can also be your collections operators).
These problems are not cause by "type coercion" itself (even if lots of people agree that "type coercion" in general is a bad idea...), they are caused by mixing scalar operators and vector operators and converting one way or another when doing this. The only solution out of this is to either throw and error for these coercion cases, or, when it actually makes sense, like in Matlab you have scalars and matrixes, have a new separate set of operators for these cases (like ".+" and friends family of operators).
"string" + 5
throws an exception.
if some_bool == 1
or if isinstance(some_bool, int)
written before the bool type was added (which only happened 2.3)I have powerful dislike for code like the future version of the above, i.e.
if some_bool == True
since that, in my mind's machine, just generates a bool result, which then (in the logic of the code) must be compared to True. If the result of == doesn't have to be compared, then why does some_bool? It's brutally inconsistent and fantastically annoying.Unfortunately, to many programmers it's also second nature to write such comparisons. Gaah. :(
You could try removing Eq, Ord and TotalOrd from Rust's bool and see what breaks.
Sounds like a way to make XOR be a big pain.
Or do you only want to ban comparing to literals? It can make things clearer to write something like "if bool==false" rather than "if not bool", especially when double negatives get involved.
Only ban comparing to literal true? Sure, go for it. But then the language is more complex for no real benefit.
Python 2.7.5 (default, Feb 19 2014, 13:47:28)
[GCC 4.8.2 20131212 (Red Hat 4.8.2-7)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "0" + 5
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objectsIt seems also that using the "as" syntax for both upward and downward casts makes code a little harder to read. Either allowing implicit upcasting or having separate syntaxes for safe vs. unsafe numeric casts would make more sense to me.
With Chris Morgan's rust-http library (which I think is also used by Servo), you should have the base on which to build a web framework. Somebody apparently wrote (and still maintains) a pure Rust Postgresql driver ([2]), so you could in theory write a simple CRUD webapp, if you're willing to write the routing yourself.
Having said that, I'm not confident yet that you want to be coding a web site in rust. In the name of safety, rust's compiler can be very difficult to please and in the name of speed it doesn't compile blazingly fast as well. Some people may have a different opinion from me, but besides writing a web app to learn the rust language, what advantages for the web does rust give you that go or haskell doesn't? When you are writing a web app, developer productivity is priority number one (in my opinion), and having to fight the borrow/lifetime checker and trying to find out why your struct doesn't fulfil `Send` are not things I would like to have to do when I'm making a web site. The tradeoff will be that hopefully a web site written in rust will be both fast and concurrently safe, but you will be sacrificing developer productivity for the reasons mentioned above. Irregardless of those issues, I'm still very determined to make a rust web framework that is both fast and easy to develop for (probably by providing examples of common web idioms in oxidize so people can see how to do it), just, I want people that use my framework to be aware of the tradeoffs that they will make. In short, I consider oxidize an experiment in trying to make a powerful, expressive, and extensible web framework in rust, and along the way I've started to question whether this will have any practical applications, but in spite of that, I still am trying to achieve the previous listed goals.
fn (context: Context, req: FromRequest) -> ToResponse
trait FromRequest {
fn from_request<'a>(req: &'a Request) -> &'a Self;
}
impl FromRequest for Request {
fn from_request<'a>(req: &'a Request) -> &'a Request {
req
}
}
This would remove a lot of boilerplate for well-behaved applications. You'll also need a notion of middleware, which I guess would take a Request and return either a ToResponse or a request (eg, an authentication handler ought to return the response immediately in case of authentication failure), and similarly on the way out, something taking a Response and returning a Response.The language isn't stable enough yet and there are still a few pieces that need writing, anyway.
How does it prevent index out of bounds errors and division by zero? No, not even in theory. What a ridiculous claim.
Had one the other day when renormalising a Cumulative distribution function wasn't taking into account a possible empty set, and the lookup of the index was invalid due to the division by zero.
i.e. a crash.
(Yes I know you can install signal handlers for segv, but that is not isolated at a language level like a task failure is with Rust.)
Granted, it is very rare that you can/should recover from nullpointer or OOB exceptions anyway. What you can do though is try to clean up things, show a polite message and shut down the application in a semi-controlled way.
"Preventing crashes" isn't the best description of Rust's novel protection systems. In my opinion, the best part is providing guarantees about data integrity and security, e.g. preventing heartbleed type read-overruns and preventing data races in concurrent code due to shared mutable state.
Actually it can be quite common, especially in complex web / network programs with many components. In Java such errors do not corrupt memory like in C, and since they are isolated, no reason not to continue the operation of the overall program. The error could just be due to a resource not being found, or faulty input coming from outside -- that is, nothing that prevents you from continuing to work on other requests.
That's somewhat like Erlang handles the case, if I am not mistaken.
But it seems you have your mind set, and wont accept any other answer.
Probably better to handle all out-of-bounds errors the same way.