Just a theory.
1,566 karma · joined August 5, 2019
Just a theory.
After all the polarism in "reality show politics", my diehard liberal friends seem less liberal to me, but they'll state which team they're on more fervently than ever.
int handle_untrusted_numbers(int a, int b) {
if (a < 0) return ERROR_EXPECTED_NON_NEGATIVE;
if (b < 0) return ERROR_EXPECTED_NON_NEGATIVE;
int sum = a + b;
if (sum < 0) {
return ERROR_INTEGER_OVERFLOW;
}
return do_something_important_with(sum);
}
Every computer you will ever use has two's complement for signed integers, and the standard recently recognized and codified this fact. However, the UB fanatics (heretics) insisted that not allowing signed overflow is an important opportunity for optimizations, so that last if-statement can be deleted by the compiler and your code quietly doesn't check for overflow any more.There are plenty more examples, but I think this is one of the simplest.
They should've just used Python 2's strings as UTF-8. No need to break every existing program, just deprecate and discourage the old Python Unicode type. The new Unicode type (Python 3's string) is a complicated mess, and anyone who thinks it is simple and clean isn't aware of what's going on under the hood.
Having your strings be a simple array of bytes, which might be UTF-8 or WTF-8, seems to be working out pretty well for Go.
It's a function you could write for yourself and give it whatever semantics you feel is best. No changes to the language required for this one.
It's not my obligation to evangelize for your pet language. I've spent enough time and written enough code in Rust to have a defensible viewpoint. This is public forum - I'll share my opinion if I want to.
Writing servers? Sure, go grab the crate that solves your problem and get on with it. Basically what I said above.
If I thought you would bother to do them, I could give you a list of concrete problems which ought to be super easy but are in fact really hard or ugly to do in Rust.
Phrases like "systems programming" have become so diluted that I'm not even sure what you mean. Once upon a time, that was something like writing a device driver. Now people use the phrase for things like parsing a log file or providing a web server.
I wanted to use Rust for numerical methods and data visualization. I didn't like the existing solutions, so I was willing to write my own Rust libraries from scratch. It was pretty painful, and the learning curve was steep.
> Why say that? It's not even remotely true
I didn't write the thing you quoted. Using a straw man argument like this is a lame tactic.
// nice and clean
let a = Generic[T, A > B]::new();
// gross curlies needed because of poor choices
let a = Generic::<T, {A > B}>::new();I think this depends a LOT on what you're trying to do and what you need to learn to do it. If you can get by with the std/core types and are happy with various third party crates, then you don't really need to learn the language very deeply.
However, if you want to implement new data structures or generic algorithms, it gets very deep very quickly.
The compiler knows when the `A` in `A[B]` is a type vs a variable.
// I don't think this flies in C or C++,
// even with "designated initializers":
f({ .flag = true, .value = 123, .stuff=0.456});
// Both of these "probably" do work:
f((some_struct){ .flag = true, ... });
f(some_struct{ .flag = true, ... });
// So this should work too:
auto a = (some_struct){ .flag = true, ... };
Take all that with a grain of salt. I didn't try to compile any of it for this reply.Anyways, I only touched SML briefly 30 some years ago, and my reaction to this level of type inference sophistication in Rust went through phases of initial astonishment, quickly embracing it, and eventually being annoyed at it. Just like data flows from expressions calculating values, I like it when the type inference flows in similarly obvious ways.
It's really not. Only one of my examples has the equivalent of superfluous parens, and none are dereferencing anything. And I'm not defending C or C++ anyways.
When I was trying to learn Rust (the second time), I wanted to know how to make my own types. As such, the macro `vec!` mentioned elsewhere isn't really relevant. I was using `Vec` to figure things out so I could make a `FingerTree`:
let v: Vec<u32> = Vec::new(); // Awfully Java-like in repeating myself
let v = Vec::new(); // Crap, I want to specify the type of Vec
let v = Vec<u32>::new(); // Crap, that doesn't compile.
And so on... let i = 1;
let j = 1;
print!("i: {:?}\n", !i);
print!("j: {:?}\n", !j);
let v = vec![1, 2, 3];
v[i];
There are definitely times you want to specify a type.It's practically your job to defend Rust, so I don't expect you to budge even one inch. However, I hate the idea of letting you mislead the casual reader that this is somehow equivalent and "just how languages work".
The grammar could've used `Generic[Specific]` with square brackets and avoided the need for the turbo fish.
The first version I got working was `d`, and my first thought was, "you're kidding me - the right hand side is inferring it's type from the left?!?" I didn't learn about "turbo fish" until some time later.
There are people who program with a "fake it till you make it" approach, cutting and pasting from Stack Overflow, and hoping the compiler errors are enough to fix their mess. Historically, these are the ones your pages/books cater to, and the ones who think the borrow checker is the hard part. It doesn't surprise me that you only see code from that kind of beginner and experts on some rust-dev forum and nothing in between.
let mut a = Vec::<u32>::new();
let mut b = <Vec::<u32>>::new();
let mut c = <Vec<u32>>::new();
let mut d: Vec<u32> = Vec::new();
Which one will your coworker choose? What will your other corworkers choose?This is day one stuff for declaring a dynamic array. What you really want is something like:
let mut z = Vec<u32>::new();
However, the grammar is problematic here because of using less-than and greater-than as brackets in a type "context". You can explain that as either not learning from C++'s mistakes or trying to appeal to a C++ audience I guess.Yes, I know there is a `vec!` macro. Will you require your coworkers to declare a similar macro when they start to implement their own generic types?
There are lots of other examples when you get to what traits are required to satisfy generics ("where clauses" vs "bounds"), or the lifetime signature stuff and so on...
You can argue that strong typing has some intrinsic complexity, but it's tougher to defend the multiple ways to do things, and that WAS one of Perl's mantras.
Even in science though, the pros are happy to switch to electron volts or units where the speed of light and years are both 1.
Imagine going to the library and the card catalog had been purged of any references to books that weren't government approved.
const encoder = new TextEncoder();
function csi(text, ... args) {
const filt = args.filter(xx => xx !== null);
const output = "\x1b[" + filt.join(";") + "m" + text;
Deno.stdout.writeSync(encoder.encode(output));
}
csi("True Color RGB:\n");
for (let ii = 0; ii<32; ++ii) {
for (let jj = 0; jj<64; ++jj) {
const fg_rr = jj*4;
const fg_bb = ii*8;
const fg_gg = (fg_rr + 3*fg_bb)>>2;
const bg_rr = 255 - ii*8;
const bg_gg = 127;
const bg_bb = 255 - jj*4;
csi("+",
38, 2, fg_rr, fg_gg, fg_bb,
48, 2, bg_rr, bg_gg, bg_bb,
);
}
csi("\n");
}