Mindblowing features are basically, by definition, a result of bad language design. They blow your mind, since they are totally unexpected behaviours. They may still be cool, but they are unexpected and hence unintuitive.
A language that are full of these is Perl. And one simple one is that you can take the string “AAAAA” and use addition on that, like “AAAAA”++ and you will get the result “AAAAB”. Cool you may think, but is it really? Addition is normally used to increase the value of a number, that is a completely different operation than modifying a String. The string “AAAAA” cannot be said to be greater or less than “AAAAB”, besides the very special case when we order it. But in general the name “John” is not considered to be higher/lower than “Mark”, they are just different. So, even if it is cool to manipulate strings by using addition/subtraction, it is still bad language design and very unintuitive. Also, since perl is so loosely typed, it may also cause very unexpected bugs.
strcmp() returns an integer indicating the result of the comparison, as follows:
0, if the s1 and s2 are equal;
a negative value if s1 is less than s2;
a positive value if s1 is greater than s2.
So basically, if C had higher level constructs, it would be identical to Rust here.
So, even if it is cool to manipulate strings by using addition/subtraction, it is still bad language design and very unintuitive.
Rust has implAdd<&str> forString and implAddAssign<&str> forString. Both append as expected.
But maybe you meant numeric addition specifically.
In that case, yes, Rust doesn’t have that, although it’s an impl<'a> Step for &'astr away from having something similar (it would be ("AAAAA"..).next()).
implStepforchar already exists of course, but shouldn’t if we take your argument to its logical conclusion.
Oh, and C would most definitely have this feature if it could. Numerical manipulation of chars is commonplace there.
Rust has impl Add<&str> for String and impl AddAssign<&str> for String. Both append as expected.
I wouldn’t go so far and say “as expected”: “Addition” implies that we’re dealing with a ring, that there’s also multiplication, and that really doesn’t make sense for strings (unless you indeed consider them numbers). It’s why Haskell’s Monoid typeclass comes with the function mappend, not madd.
In Rust’s defence though std::ops traits aren’t meant to carry any semantics they’re about syntax: It’s called Add because it’s +, not because it means something. I do think it would’ve been worth it to introduce ++ for general appending (also vectors, sets, maps, etc), though, to keep things clean. Also ++= for the mutating case.
I do think it would’ve been worth it to introduce ++ for general appending.
I already mentioned (val..).next() which is both safe* and explicit about it being a generic stepping operation instead of possibly being sugar for {x = x + 1; x}.
Also, calling it “appending” is weird for us folks coming from languages like C 😉
* you don’t have to worry about what i32::MAX++ would/should return.
Pre- and post-increment are only really useful when you’re doing C-style looping and there’s a good reason we don’t do that in Rust.
I actually honestly can’t recall ever making an off by one error in Rust, I’m sure when implementing specific data structures or when doing pointer manipulation it’s still a possibility but you can write a gazillion lines of code without ever running risk of that particular annoyance. Also while C folks may have an argument regarding operator semantics, C++ folks don’t they’re doing unspeakable things to <<.
Also, FWIW Haskell uses ++ to append lists and therefore also strings. It’s not like it’s an odd-ball usage of the symbols, that’d be .. which I vaguely remember some language using. Would cause a whole new class of confusion regarding 'a'..'z' vs. "a".."z". Not to mention that "aa".."zz" actually makes sense as a range all that’s missing is &str: Step. Probably not a good idea to have built-in because do we mean printable ASCII? Whole unicode range? Just the alphabet? Not an issue when you’re doing it to single chars but strings get ambiguous fast. Does Rust even guarantee stuff about Char ordering C certainly doesn’t really do that, short of I think 0..9 being contiguous.
I try not to and if I have to I’d use string interpolation. I’m not even sure whether you’re pulling my leg right know, I literally don’t remember whether they have a string append operator.
Like 99.999% of the sh I ever wrote was in Makefiles and short wrapper scripts which could just as well be aliases. No argument handling past $@, no nothing the language is just too fickle for me to bother dealing with. The likes of zsh are make-up on a pig, I think I had a quick run-in with fish but never really got the hang. Nushell is different, it’s actually bold enough in its changes to get rid of all the crufty nonsense.
Sorry, I thought you meant the use of .. in Rust is odd. So I pointed out that {0..9} and{a..z}is also used at least in bash and zsh. That’s at least 10s of millions of users!
I know of .. being used for appending by lua at least. So still not odd-ball I would argue, since the people who interacted with lua code in their life probably outnumber those who interacted with all functional languages combined.
Now that you mention it yes Lua is probably the one that I remember. It’s an incredibly well-designed language from start to finish but also culturally an odd-ball. .. isn’t even the biggest offender: Their indices start at 1. Haskell accosts you with zygohistomorphic prepromorphisms but at least [1,2,3] !! 1 is 2.
Mindblowing features are basically, by definition, a result of bad language design. They blow your mind, since they are totally unexpected behaviours. They may still be cool, but they are unexpected and hence unintuitive.
A language that are full of these is Perl. And one simple one is that you can take the string “AAAAA” and use addition on that, like “AAAAA”++ and you will get the result “AAAAB”. Cool you may think, but is it really? Addition is normally used to increase the value of a number, that is a completely different operation than modifying a String. The string “AAAAA” cannot be said to be greater or less than “AAAAB”, besides the very special case when we order it. But in general the name “John” is not considered to be higher/lower than “Mark”, they are just different. So, even if it is cool to manipulate strings by using addition/subtraction, it is still bad language design and very unintuitive. Also, since perl is so loosely typed, it may also cause very unexpected bugs.
I hate it to break it to you but it’s the same with numbers.
Ok, I then have some business proposals…
The general theme of your comment is good, but the example is…
// rust eprintln!("{}", "AAAAB" > "AAAAA") // true eprintln!("{}", "Mark" > "John") // true
// C printf("%d\n", strcmp("AAAAB", "AAAAA")); // 1 printf("%d\n", strcmp("Mark", "John")); // 1
strcmp()
docs:So basically, if C had higher level constructs, it would be identical to Rust here.
Rust has
impl Add<&str> for String
andimpl AddAssign<&str> for String
. Both append as expected.But maybe you meant numeric addition specifically.
In that case, yes, Rust doesn’t have that, although it’s an
impl<'a> Step for &'a str
away from having something similar (it would be("AAAAA"..).next()
).impl Step for char
already exists of course, but shouldn’t if we take your argument to its logical conclusion.Oh, and C would most definitely have this feature if it could. Numerical manipulation of
char
s is commonplace there.I wouldn’t go so far and say “as expected”: “Addition” implies that we’re dealing with a ring, that there’s also multiplication, and that really doesn’t make sense for strings (unless you indeed consider them numbers). It’s why Haskell’s
Monoid
typeclass comes with the functionmappend
, notmadd
.In Rust’s defence though
std::ops
traits aren’t meant to carry any semantics they’re about syntax: It’s calledAdd
because it’s+
, not because it means something. I do think it would’ve been worth it to introduce++
for general appending (also vectors, sets, maps, etc), though, to keep things clean. Also++=
for the mutating case.I already mentioned
(val..).next()
which is both safe* and explicit about it being a generic stepping operation instead of possibly being sugar for{x = x + 1; x}
.Also, calling it “appending” is weird for us folks coming from languages like C 😉
* you don’t have to worry about what
i32::MAX++
would/should return.Pre- and post-increment are only really useful when you’re doing C-style looping and there’s a good reason we don’t do that in Rust.
I actually honestly can’t recall ever making an off by one error in Rust, I’m sure when implementing specific data structures or when doing pointer manipulation it’s still a possibility but you can write a gazillion lines of code without ever running risk of that particular annoyance. Also while C folks may have an argument regarding operator semantics, C++ folks don’t they’re doing unspeakable things to
<<
.Also, FWIW Haskell uses
++
to append lists and therefore also strings. It’s not like it’s an odd-ball usage of the symbols, that’d be..
which I vaguely remember some language using. Would cause a whole new class of confusion regarding'a'..'z'
vs."a".."z"
. Not to mention that"aa".."zz"
actually makes sense as a range all that’s missing is&str: Step
. Probably not a good idea to have built-in because do we mean printable ASCII? Whole unicode range? Just the alphabet? Not an issue when you’re doing it to single chars but strings get ambiguous fast. Does Rust even guarantee stuff about Char ordering C certainly doesn’t really do that, short of I think0..9
being contiguous.I take it, you don’t bash/zsh/…?
I try not to and if I have to I’d use string interpolation. I’m not even sure whether you’re pulling my leg right know, I literally don’t remember whether they have a string append operator.
Like 99.999% of the
sh
I ever wrote was in Makefiles and short wrapper scripts which could just as well be aliases. No argument handling past$@
, no nothing the language is just too fickle for me to bother dealing with. The likes of zsh are make-up on a pig, I think I had a quick run-in with fish but never really got the hang. Nushell is different, it’s actually bold enough in its changes to get rid of all the crufty nonsense.Sorry, I thought you meant the use of
..
in Rust is odd. So I pointed out that{0..9}
and{a..z}
is also used at least in bash and zsh. That’s at least 10s of millions of users!I know of
..
being used for appending by lua at least. So still not odd-ball I would argue, since the people who interacted with lua code in their life probably outnumber those who interacted with all functional languages combined.Now that you mention it yes Lua is probably the one that I remember. It’s an incredibly well-designed language from start to finish but also culturally an odd-ball.
..
isn’t even the biggest offender: Their indices start at 1. Haskell accosts you with zygohistomorphic prepromorphisms but at least[1,2,3] !! 1
is2
.