Remove the ++ and –- operators
github.com
github.com
Personal opinion, but I definitely miss '++' every time I'm doing '+=' in Python.
I had a very similar conversation with a colleague about UX. This one operation might not happen often, but when it does, it should be intuitive and fast. The technology is here to serve the humans.
That is, if you're optimizing typing, you're optimizing the wrong thing, and if you want to improve your ability to write software, you should instead be getting better at these other things. The typing part is good enough.
Edit: Or if typing really is the bottleneck, you're a much better programmer than me.
Slow, and my fingers have to jump completely over the keyboard.
What is far more annoying, and should be banned, are `these` (I have to press shift+' twice to get one `, otherwise I end up with á' instead of `a`), and {}[], as they are on AltGr+7/8/9/0
I swapped the US out for international because it was important to me to type Pokémon properly. It is an annoyance to have to type ` followed by a space because it is waiting for a vowel to let me type ù. Same with ' which let's me type ç or " which lets me type ü... etc. I disable it when programming for the reason you cited. It can be annoying to deal with. Especially when my IDE tries to autocomplete " and I typed "" instead of " (followed by a space) and I get """".
So I have æ, but not å.
Actually, I’m gonna switch to DE3.
Still doesn’t solve these special characters.
And I seriously couldn’t work without the international layout - using proper Unicode characters in my comments is just non-negotiable.
If developers would have thought more about localization, and made less dumb assumptions...
But there are even minecraft mods that don’t work on QWERTZ, because they are hardcoded to keys that are dead keys on DE layout.
Therefore in EN I can {code} and then alt+shift and {comment with proper Unicode characters}. My suggestion would be to have a setup of T1/EN. Code in EN and comment in T1.
Sorry if I'm not being clear or if I'm being confusing...
>If developers would have thought more about localization, and made less dumb assumptions...
I18N can be time-consuming. Especially to test on every conceivable keyboard layout. Dumb assumption allows the mod to exist. I'm all in favor of I18N (and help translate things when I can!) but honestly it is a lot more work for what is often very little gains.
Would you rather spend 10 hours adding I18N for 100~ players or spend 10 hours improving the rest of the code base and adding new features for 10,000 players? Most devs choose the latter. Which really sucks if you're in the group of 100~ players.
And switch EN and T1 is not very useful. I’d have to relearn blind typing completely again.
When your "increment by 1" is really just in the service of iterating over a set, then the natural, obvious way should be to use a separate idiom that abstracts the concept of iteration over that set, rather than dive into the details of how you get access to the next member. Which is what Python does: "for x in ...".
If the loop is not simply iterating over the set, but tweaking some value unpredictably and periodically checking, then there's nothing special about += 1 relative to += 2.
But retaining x += 1? That one has always annoyed me. Why does '+' (and friends) get this special form, but not my functions? Just because they're built-in.
They are useful; no argument there. Largely because 'x' can be a complex reference, and you don't have to type it twice (and the compiler doesn't have to figure out that its the same expression twice). E.g. x=x+1 is short but (rec)FnRec(iRec) = (rec)FnRec(iRec) + 1; is not short. And the compiler gets some great hints when the '+=' form is used (don't calculate the reference twice).
I just want that for my stuff too! E.g. I may have a transformation method Xform(Foo&, Bar) that returns another Foo&. I want to say foo = Xform(foo, bar); but with 'foo' replaced by a complex reference. I have to say FnFooRef(iFoo, "primary", red) = Xform(FnFooRef(iFoo, "primary", red), bar)
instead of FnFooRef(iFoo, "primary", red) Xform= bar;
I want my own 'operators' with the 'op=' syntax supported.
Probably its not terribly useful any more; languages support immutable data and tuples and so much that don't work this way at all.
Your functions can get that (and other) special form. You need to use a language where you can define your own operators. Have you looked at C++, C#, Haskell, or LISP?
AFAIK, Lisp doesn't have syntactically-distinct operators at all just functions which may have names similar to operators used in other languages, and C# and C++ don't seem to support custom operators at all. [0]
OTOH, Perl 6 has robust support for custom operators.
[0] except that C++ has apparently been hacked to create custom operators with some limitations via macros [1]
[1] http://www.codeproject.com/Articles/31783/Custom-User-Define...
Or, um, Swift. :)
Which is where much of the Swift "language" is defined... in the standard library.
-Chris
x = <LHS> + 1;
It could then get arbitrarily complex. E.g. x = (<LHS> + 1) / atan(<LHS>) - <LHS>;
and no matter how complex 'x' was in practice, the compiler (and the code reader) could keep track of what was happening. y = (x + 1) / atan(x) - x;
x = y; // If you're in a loop and updating some value
If would hope/imagine that a compiler could reduce the two to the same code - and I don't think it reads any worse. Is there a downside beyond the extra line of code? X &x = { complex reference expression for x }
y = (x + 1) / atan(x) - x;
Now the compiler has the clues it needs to write good code.
And with language support I don't have to introduce new names for each occurrence; just one name like <LHS> that readers can quickly learn.Having <LHS> as a name is only useful I think if you don't want to give it another name? I was asking what's the downside of giving it a name.
Because from my point of view, it could be only the case only if the scopes are weak or underused, or names are bad (too short, ect). After SSA is all about one-use names.
z <- copy(x)
z += y
But you're otherwise right, it's annoying that this shorthand syntax isn't more generally available for user functions.In Swift, + and += are just operators. They're two separate operators which happen to do similar things. In Swift, an operator can be defined to mutate its left-hand operand, which += is defined to do. You can create your own operators that do that as well.
If you want to do it for methods, Swift has mutating methods which can change the thing they're sent to. In this case, you'd mark your Xform func as "mutating" and then you can write someComplexThing.Xform(bar) and it will mutate someComplexThing in place.
Of course, if you want to support both forms, you end up with a bit of redundancy as you have to define stuff twice. But the built-in stuff is the same way, and you can at least define one in terms of the other to cut down on duplication.
https://kotlinlang.org/docs/reference/operator-overloading.h...
[0] http://doc.perl6.org/language/functions#Defining_Operators
Especially when doing straightforward data manipulations in R or Python, endless lines of `bla = map(bla, fn)` start to look crufty, so much so that Pandas in Python now allows you to add `inplace=True` to almost any data manipulation method to cut down on the verbosity. But then, sprinkling that keyword argument across every line isn't exactly better. Neither is endless chaining. Looks like we could still use some syntactic improvement.
func += (inout left: Vector2D, right: Vector2D) {
left = left + right
}
https://developer.apple.com/library/ios/documentation/Swift/...http://stackoverflow.com/questions/1047021/overriding-in-pyt...
class Vector2D:
def __iadd__(self, other)
return self + other
No "self mutation" as you suggest. a += b is equivalent to a = a.__iadd__(b)Your example would be the implementation for immutable Vector2Ds, and is implemented for you if you just wrote __add__. (I presume object.__iadd__ falls back to self.__add__.)
The only time you should actually override __iadd__ is for mutable objects, in which case it should look more like
class Vector2D:
def __iadd__(self, other)
for i, x in enumerate(other):
self[i] += x
return self
That's the self mutation I was talking about.Well, strictly that's not OK either, since operators shouldn't be duck-typed. Instead you should do
class Vector2D:
def __iadd__(self, other)
if not isinstance(other, Vector2D):
return NotImplemented
for i, x in enumerate(other):
self[i] += x
return selfWhat would the rationale be for such a rule?
the docs don't mention anything like that https://docs.python.org/2/library/operator.html and I've never heard it before. In Python, neither integers nor strings are mutable and both support the "x += y" syntax.
The __iadd__ method works the same for both mutable and immutable objects AFAIK
Because __iadd__ automatically delegates to __add__. For immutable objects that's the best you can do, so there's no reason to write both.
I'm not saying this is a shining example of brilliant programming, but it is in a semi-working state and something "in a similar style" (that is, a three-pass tokenizer -> LR parser -> LR parser where scope information and other metadata is computed in the second pass and fed into the third) should be able to handle the changes you're talking about.
func +=(inout lhs: Int, rhs: Int)
and you can just implement this.You might object that special forms are still privileged, e.g. foo[idx]+=1. But in fact these are not special: one of the surprising features of Swift is that inouts work on computed properties. For example, say we add a mutable property highHalf on UInt64:
extension UInt64 {
var highHalf : UInt32 {
get { return UInt32(self >> 32) }
set { self = (self & 0xFFFFFFFF) | (UInt64(newValue) << 32) }
}
}
Now you can do this: var x = UInt64.max
x.highHalf -= 1
So complex references can be used for any inout. That's how array indexing works.Swift is the first language I've encountered that works this way; are there others?
Lisp, of course :-) Common Lisp's SETF and related macros work this way. E.g.,
(incf (ldb (byte 3 5) x))
would increment the "byte" (CL's term for an arbitrary bit field) of width 3 at offset 5 of X.INCF is defined in terms of SETF. Of course, the set of macros that can update a place is user-extensible. So if you wanted one that multiplies the value in the place by two, you could just write something like this (the trailing "f" in the name, as you might guess, is the convention for such a macro):
(define-modify-macro doublef () (lambda (x) (* x 2)))
then you could call it like this: (doublef (ldb (byte 3 5) x))
to double the value in the bit field.(EDIT: used lambda expression instead of helper function.)
I have some old code somewhere for images which I'm sure does something to the effect of:
image[x, y] *= scale;
where Image::operator[] returns a Pixel&.Consider the much-hated vector<bool>, implemented as a packed bit array. Since you can't return a reference to a bit, operator[] must create a special wrapper class that holds a reference to the word and the bit offset, and then overload operator= and perform other tricks. It's famously leaky and gross.
In Swift, we can implement this optimization much more cleanly. inout lifetimes are always scoped, and when the scope ends, the new value is written back to the object via its setter. Our `inout boolean` is not backed by a boolean at all: it's backed by a getter and setter which can do arbitrary things, like mask and shift a word.
You are right, take a look at Perl 6 infix operators. You can define your own operator(treat it like a function, as such) and then use it.
https://perl6advent.wordpress.com/2013/12/22/day-22-a-catalo...
The reason is that I don't want to see you escape your strings by writing
input escapequotes= input
That's why. come on. who wants to read that? input +'= input
and the reverse input -'= input
or, alternatively, input \'= input
and input !'= input
If you code does this often enough, that may even be useful (but also, your code would be bad)Then again, my most common use for `++` was `for (;;) {}` index, and we have better in these new languages like Rust and Swift.
There are millions of people in this world trying to learn to code and understand the layers upon layers of cruft and quirks we've added. I don't mind the `++` or `--` operators, but I certainly don't mind them being gone either. They add extra complexity to code which is already arguably too complex.
In any case, I favor understandability over guesswork, and `++` is another odd cornercase which you have to mentally `grep` over.
But no, not only for for(;;). There's also the too common array traversal:
while(something) a[x] = b[x++];
And lots and lots of ugly but useful uses in pointer arithmetics where they make things clear. They have no place in any other language, but I'd really miss both operators in C.
Wait, isn't this an undefined behavior? Is the order of evaluations of `x` in the left side and `x++` in the right side defined? I'm always confused at things like this!
But, well, the specs are another matter entirely.
x++ returns x and then increments it, so yes the spec agrees with your intuition here.
Whereas ++x increments x and then returns the incremented x.
That subtle difference between x++ and ++x has been the debugging nightmare of many a C developer over the years. It's also why there's a fun irony in the C++ name and why people say the actual successor to C will be ++C.
I was talking about my statement at the upper comment. I used x++ there, not ++x. The doubt is about the value of the other x.
The difference you talk is about the main behavior of the operators. You won't find any description of them that does not state it.
My apologies for answering the wrong question, but yes in that case the standard is also mostly clear that you can assume that things are evaluated from left to right in C/C++ and thus the first x in the line should be evaluated prior to the x++ later in the line...
Every compiler seems to act the same way today, but some specs oriented optimizer might play havoc with that line.
The other is ++ and -- also map directly to old school assembly language instructions. Helpful when writing the back end of old school compilers.
Probably doesn't make much sense in a language with foreach() or dictionaries, etc.
And simplicity is an actual goal of computer language design.
array[i++] = this;
array[i++] = that;
array[i++] = the_other;
which also extends nicely when some of those elements are optional. array[postincr(&i)] = ...;
if you're doing enough of those that it's worth it.Most modern languages have an append-to-list method/function, so your example isn't really applicable in those langauges. For example, ArrayList#add() for Java or Vec::push[1] for Rust, etc. (Yes, these are technically dynamically sized arrays, but you can always reserve the necessary amount of space up front if you so desire.)
[1] https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pus...
It looks like they may be trying to make it easier for current tweens that would have otherwise learned PHP.
Don't see the value in this. These operators are terse, well known, and are implemented in a wide array of languages.
This half-reeks of something that a professional/advanced user thinks trips up beginners without actually tripping up beginners. Or they have an anecdotal sample size of n < 10 and decided since it confused 1 person that 10% of people get confused.
"plus plus" doesn't mean anything. It might even be confusing that it doesn't add 2.
for i in 0..<count { print("Person \(i + 1) is called \(names[i])") }
This ..< operator is so much more logical, of course! Not to mention == and ===. Logically, the first one compares twice and the second compares three times (for luck), just in case first two comparisons didn't go through...
zip(names, 1...names.count).forEach { name, index in
print("Person \(index) is called \(name)")
}
Or, in an ideal world: zip(names, 1...names.count)
.map({ name, index in "Person \(index) is called \(name)" })
.forEach(print)
Currently, that isn't valid Swift, "print" can't be used like that, though if you define a closure it works: let printIt = { x in print(x) }
zip(names, 1...names.count)
.map({ name, index in "Person \(index) is called \(name)" })
.forEach(printIt)
I think that Swift could use = for equality, since assignments return Void and comparison returns Bool. Maybe it should.But your argument boils down to "if you can't be clear everywhere, don't be clear anywhere". That's not a good goal.
If you consider readability, then why !a instead of not(a)? Why || instead of or?
I wonder what somebody who had no idea about X++ would guess it meant? Based on my daily conversations, if I didn't know already, I would guess it means "variable X has done a good job and deserves some IRC karma"...
Look, don't get me wrong, I applaud the intent to make the language easy for total beginners. I argue that it's a longer stretch to understand ..< operator than ++.
Arguments like people who never programmed before should be able to use it are great, but one should consider those in the context of the entire grammar, not just one operator.
In my opinion Swift does not shine here, regardless what Apple says.
If readability matters then the rationale that x += 1 is more readable than x++ is very reasonable.
I've always found the idea that the operator complicates things ridiculous
Given that there are interview questions on the behavior of post/pre increment operators shows that there is some subtlety to it which creates ambiguity and complexity. So given that they want the language to be accessible, it makes sense to reduce ambiguity.Being an interview question doesn't really mean anything other than it being an interview question.
maybeNull?.getContent()?.toString()
This would improve my coding sooo much.
Currently I use Optional.fromNullable(maybeNull).orElse(new DummyObjectThatReturnsNullOnAllMethodCalls).getContent(), and then repeat the process.
Edit: I'm only half-joking. Removing postincrement and postdecrement from C++, as some people are suggesting, would be like removing the oil filler cap from a chain saw. The tool would still be dangerous to use, but now it's annoying to use as well.
I could buy the argument if we were dealing with indexes or numbers where you had to read/hunt down occurrences of them to make sure they are what you expect. Like: make sure that a loop with a lot of indexes don't overincrement (out of bounds) or does something else that is wrong. But in this case the space isn't across a method, or a block. The space between the destination (i) and the increment number (1) is literally just 4 characters.
Of course you do, otherwise you wouldn't know it was an increment in the first place.
(No pun intended, but I also didn't edit it out...)
How often do your loops depend on incrementing a variable by one? In _Swift_ code.
Beginner here. Small detail...
`i++` is read as `i = i + 1` and not `i += 1`. A small, but important distinction, especially for a beginner. `i += 1` is also parsed as `i = i + 1`.
However for `i += n` it no longer parses as `i = i + 1` but rather `i = i + n` which is a step more difficult (and more powerful) than i++ which is always `i = i + 1`. However that is additional complexity not found in `i++`.
(This is why I found `i++` easier than `i += 1`)
main.go:6:2: should replace i += 1 with i++
That said, if it were removed, I'd probably be happy because it makes the language a little simpler, but I don't mind having it too much either, because it's a statement rather than an expression.The PDP-7 assembler manual is at http://bitsavers.informatik.uni-stuttgart.de/pdf/dec/pdp7/PD..., but I can't see any reference to this auto-increment hardware, or to an assembler directive using it. What I'm getting at is that there appears not to have been an assembly language construct for auto-increment on the PDP-7 at all, even though its hardware supported it.
The hardware "auto-indexing" is described at page 3-12 of the PDP-7 architecture document, http://bitsavers.informatik.uni-stuttgart.de/pdf/dec/pdp7/F-... . It is enabled only for about 8 special memory addresses in each 8K of address space, so it is weird and handicapped by comparison with the PDP-11.
See Ritchie's history (http://www.bell-labs.com/usr/dmr/www/chist.html) --
"Thompson went a step further by inventing the ++ and -- operators, which increment or decrement; their prefix or postfix position determines whether the alteration occurs before or after noting the value of the operand. They were not in the earliest versions of B, but appeared along the way. People often guess that they were created to use the auto-increment and auto-decrement address modes provided by the DEC PDP-11 on which C and Unix first became popular. This is historically impossible, since there was no PDP-11 when B was developed.
"The PDP-7, however, did have a few `auto-increment' memory cells, with the property that an indirect memory reference through them incremented the cell. This feature probably suggested such operators to Thompson; the generalization to make them both prefix and postfix was his own. Indeed, the auto-increment cells were not used directly in implementation of the operators, and a stronger motivation for the innovation was probably his observation that the translation of ++x was smaller than that of x=x+1."
There were machines with auto increment modes long before the PDP-11 though, e.g. "http://ed-thelen.org/comp-hist/GE-635.html#Indirect Then Tally (IT) Modification"
I see a lot of people complaining that they like ++ and -- who may not realize that they can still have it if they want it. I get that there are legitimate questions over whether it's wise for the community and such, but for your own work, you can still have it if you want it.
Obviously you should be careful not to commit such atrocities in any code that might ever see production.
Funny given the name of the language.
so few people understand its behaviour and it enables some really revolting and difficult to read things. i think a lot of people learned this in the 80s, 90s and 00s even... its not a new revelation.
the pre-increment/decrement though? i think having these is important. there are plenty of contexts away from numbers where they make sense (things can be ordered and not have a concept of addition)
1.advancedBy(1) == 2
This is different than ++, though, because ++ mutates the value, and advancedBy(:) returns a new one.
shortening function names with abbreviations ought to have died when fortran relaxed that restriction. XD
for others, though, it really enables the writing and reading of some very elegant and concise code.
(i'm not 100% sure this means you, but all of my experience tells me this is likely the case, sorry to have to be critical)
i've heard this sort of thing about
*a++ = *b++;
and variants thereof, which is the classic example of this.a lot of the times i have seen this stuff it is in the middle of even more revolting code too... like some 1000 line function (which could be 10 functions and has comments inside of it that delineate the obvious splits) with a gigantic switch statement (which could be a class, or in C a function pointer), containing loops, where there are 20 lines like the above but even more difficult to read in a row (which could have been a nested loop with identical logic referring to some constant data) - to think of the most recent example i faced.
sadly i've seen this sort of stuff so many times for so long that i find it easy to read, but it is intrinsically difficult involving precedence and the post-increment gotcha, and it gets worse if there is even more being done than just a straight copy.
I also contest "++" and "--" operators are seriously tripping up "beginners". In most programming books, it's taught a few chapters in...
I don't see how this is a valid reason to remove the operators completely. Beginners will get it wrong sometimes, so we should remove it?
Beginning users are likely to make all kinds of errors, so the implication would be maybe we should remove the entire language...?
Not to mention, pre-decrement and post-decrement are not complicated concepts. There are many valid reasons to use both, although post-increment/decrement seems to be the more common use.
Swift does include them, but puts a screaming "Unsafe" in front of their type names so that it's clear that unless you really know what you're doing, you're probably doing something wrong.
There's no way to do that with a ++ operator, so it's being removed.
Most people would agree C lets the developer do a lot of terrible things (by design, since some of those terrible things are necessary for low level stuff, which C was targeted at).
Pointers are confusing for a lot of people. Which is why almost no modern language uses them. Comparing "++" with C pointers is not a valid argument.
Even so, I would never argue to remove pointers from C, since you can optionally not use them. If you don't need that language construct in your program, don't use it. But leave it for others who do want/need it.
Confusing C-isms like pointers are what Swift is trying to get away from. This is another case of that.
"We're making a new language, it isn't C, but will share some characteristics. Which should those be?" is the question being asked here.
The problem, Swift is unlikely to be a "beginner's language"... since it's predominantly (at least for now) an Apple language; used almost exclusively for making iOS apps.
To make an iOS app, you have to have an Apple Developer license, be paid up on fees, own a very expensive Mac, and pay Apple to put your app in the store.
None of which is something a beginner, just starting to learn programming, is likely to do.
> be paid up on fees
This isn't true anymore, FWIW. Also, OS X apps exist.
I mean, its predecessor allowed you to mutate your class hierarchy at runtime, and this was a thing that people commonly did!
"You can't do that" is a powerful tool for making code safer.
They also make the tools that consume that language slightly more complex. It doesn't sound like much, but in aggregate it's the difference between writing a parser for Java vs. a parser for C++.
It's literally no different than having to remember what "+=" does... which is what's being proposed as the alternative.
> Reading is more important than writing
I would agree, but "x++" is not difficult to read. It's more concise than having to read "x += 1". Or worse, beginners will think it's clever to define constants for this so now you'll get "x += INCREMENT_VALUE", making you have to go lookup whatever "INCREMENT_VALUE" is, etc...
You already have to remember what "+=" does though. If they kept ++ you'd have to learn both.
"+=" is no better.
If you're going to campaign against "++", might as well go all the way back to BASIC days and only allow "x = x + 1"
long_variable_name = long_variable_name + 1
That's the problem being solved in a modern language. The ++ and -- operators don't add much. They're the perfect a combination of rare, unnecessary, and often ambiguous. Not to mention that their semantics are often different in subtle ways between languages.Autocompletion is a wonderful tool that every developer should use, if only to reduce the possibility of `long_variable_name = long_varable_name + 1` in their code.
And by induction you can use this argument to allow any amount of bullshit in a language.
>"+=" is no better.
"+= x" saves you from "= long_variable_name + x" which is arguably less readable.
"++" saves you from ... "+= 1" which is already entirely clear, and I have no idea why anyone feels the need to shorten it.
Sure it's a relatively small complexity cost, but it's also an even more microscopic advantage.
Because "-" is part of the domain language (mathematics).
> The concept of incrementing or decrementing a value is trivial.
For a normal function (i.e. something that could be implemented as library functionality) then I agree with you. But for a language-level operator, it's a special case. It probably has its own precedence. It definitely complicates the metamodel.
> If you're going to campaign against "++", might as well go all the way back to BASIC days and only allow "x = x + 1"
I would. How many times do you need to add 1 to something anyway?
I remember the day I first saw a '++'. It was a rainy night, and I was inspecting a colleague's for loop, when suddenly a '++' operator appeared. I asked myself, "What in the holy bacon of Zeus is that?" So I looked it up in my book. My head almost exploded, and I asked myself if I should quit programming immediately. It was simply too complicated. After four months of agony and pain I finally recovered and started programming again. And yet... Sometimes, when it's raining outside, the memories come back. Programming... No, my life will never be the same again.
And there is no ++ equivalent of x += 2.
Its not a special syntax for "+1", its a special syntax for the combination of assignment and increment/decrement.
The postfix versions (increment/decrement variable and then return the value that was present before the increment/decrement), particularly, are equivalent to:
_x = x; x += 1; _x
In an environment where that pattern of operations is common, I can see the value of having a concise mechanism for expressing it.OTOH, there's a cost to it, too, and I'm mostly happier without them around.
1 is just another number, the fact that it's useful for enumerating arrays in C isn't relevant as Swift provides more native solutions for that, the use of which should be encouraged.
> Anointing "+ 1" as a thing that needs special syntax is weird.
1 is special.
Why is adding 1 to something special, compared to adding 2 to something? The #1 use case, by far, is C-style for loops, which aren't used in idiomatic Swift code.
For instance, on a 64-bit x86 machine,
ADD RAX,1
is nine bytes long, while INC RAX
is one byte. Maybe not as much a win these days, but back when memory was smaller and more expensive, it was worth it. #include <stdint.h>
uint64_t inc(uint64_t x) { return x + 1; }
With -O0 gives me: 48 83 c0 01 add $0x1,%rax
and with -O2: 48 8d 47 01 lea 0x1(%rdi),%rax
That is, both are four bytes.Likewise, z = (a : 5), means that z gets old value of a, then a gets 5.
This makes for a nice family of operators. For example, to swap the contents of two variables you can say: a:b:a (or a=b:a). Also you can rotate through a bunch of variables: a:b:c:d:a transfers all the contents to the left, and puts the old value of a into d.
The . operator should have an assignment form as well, so that you can say: p .= next instead of p = p.next
Now you can traverse linked lists very concisely: for (p = first; p; p .= next) serialize(p);
Of course .: will have the expected meaning: return old value of left side, then replace it with one of its members. So you can say:
while (p) serialize(p.:next)In fact now that Unicode is universal we should use all of these operators too :-)
for (i=0;i<n;i++) *a++ = *b++;
any more. while (*a++ = *b++);But to try to say that x++ is complicated to understand? It's no more complicated than a lot of operations. I don't think anyone would intuit what x%2 means either. There are things that you can get just by looking at it, and others that you just have to learn once, then you go "oh, that's what it does" and move on.
Come on. There are legitimate reasons not to carry one language's expressions to another, but this isn't a good one. Most people first learn of ++/-- as "By the way, you can use ++ as a shortcut to add one" and leave it at that.
Is this a thing some "new" programmers don't understand what is going on?
Am I taking crazy pills?
To me, ++ is the signature operator of the C language AND the operator in the title of the compiler that Swift is written in: C++
I guess it wasn't just me who liked it quite a bit ;).
After so many years I still see a bit of magic in this strange repetition of a character..
So I think they should definitely stay, even if (because) it's not the most pragmatic thing to do.
Why was this decision made?
a += b -= c;
Don't ask me in which order it executes, I would need to read the C standard again and wrap my head around how this case is described therein.
I'm also not sure wether this is defined or undefined behaviour:
a += b -= c *= a;
thx for the reply @legulere, I can now see the void, why would the language allow syntax that smells so bad? Can you do this in "c"?
I could never really memorise the difference between i++ and ++i because it just seemed like such an obscure thing to have. It's really really weird (and cool) to see someone suggesting removing it.
Increment is the fundamental operation, += is sugar for repeated incrementation, not the other way around.
The optimizations that "var" allows should be the job of the compiler.
It's still needed at the non-local level on reference types, but could possibly be disallowed in structs as well.
?
> ?
That was a subalternative underneath the alternative of changing the operators to return Void like other assignment operators. ++x and x++ differ in that the former returns the value after the increment, the latter the value before; if they return void, all they do is the increment with no difference.
I just taught ++ and -- to 1st semester students last week. There were no problems.
Believe it or not the concept of
x = 5
is harder to understand.
They know that = means equality, because of algebra. I have to retrain prior knowledge, and since humans rely on prior knowledge to learn new things quickly, it's more difficult.
Having to explain == or .eq or, god forbid, === takes way more time to explain than:
"x = 0". x++ adds 1 to x. So when you need to increment by one, you can do x = x + 1, or you can do x++ which is a shorter way."
Boom. Done.
Not exactly a good reason for taking it out of a programming language. That's all I was saying.
Do I care that Swift has it or not? Nope. But I just thought this particular reason was silly.
Advantages: "The primary advantage of these operators is their expressive capability"
Disadvantages: "Their expressive advantage is minimal"
Demand X = X + 1. For clarity/readability/formatting.
A key part of the reason for removing the ++/-- set of operators seems to be that they conflict with Swift's pattern of mutating operators returning void. (An alternative offered was revising them so that they followed that pattern.)
+=/-=, like simple assignment, do not have that problem.
myObject.someVariable = myObject.someVariable + 1
is harder to read than myObject.someVariable += 1
Also it's annoying to type and increases the chance of typos.> These operators increase the burden to learn Swift as a first programming language -
Same could be said about almost any other slightly "advanced" feature. Not to mention the fact that I fail to see the difficulty here. Increment/decrement take literally a few minutes to explain and understand.
Actually, it's more difficult to explain the concept of a function call, so let' propose to remove functions instead and stick with goto and global variables because they are easy to explain to a novice.
> Their expressive advantage is minimal - x++ is not much shorter than x += 1.
Increment/decrement looks visually more compact. (x += 1) looks hideous, has this "magic constant" and has 3 extra chars. Not to mention, x++ does have the expressive advantage, because it has entirely different semantics: "return value THEN increment", while x += 1 doesn't return anything in Swift (which is mentioned right in the next entry).
> Code that actually uses the result value of these operators is often confusing and subtle to a reader/maintainer of code. They encourage "overly tricky" code which may be cute, but difficult to understand.
It is not if you actually understand the semantics of those operators. Writing things like "return currentSize++;" is perfectly clear (assuming you know the meaning of the operator) and more concise and less noisy compared to something like "currentSize += 1; return currentSize;".
> While Swift has well defined order of evaluation, any code that depended on it (like foo(++a, a++)) would be undesirable even if it was well-defined.
By that logic, again, function calls should be banned. foo(bar(a), baz(b)) where bar and baz have side effects is also undesirable.
> These operators are applicable to relatively few types: integer and floating point scalars, and iterator-like concepts. They do not apply to complex numbers, matrices, etc.
I don't see how this is relevant at all. There are lots of operations that are only applicable to certain types. It doesn't mean such operations should be removed. You can't compute the sine of a matrix or a complex number yet you wouldn't remove sin(). You can't compare two complex numbers or two matrices but I don't see operators < and > going anywhere.
> Swift has powerful features that eliminate many of the common reasons you'd use ++i in a C-style for loop in other languages, so these are relatively infrequently used in well-written Swift code. These features include the for-in loop, ranges, enumerate, map, etc.
True, but when it does become necessary I'd rather have that functionality available. I see no need to handicap the language this way.
> Having to support these could add complexity to the potential revised numerics model.
This might be the only valid (and the real) reason for removal... but I don't have enough information to comment on this.
My question involves a sorting function and thus thinking of a problem one step at a time. Start with an inspection, then based on the element perform an action, then marking some bounds with pointers to spots within array.
Since you're doing this one item at a time, you're always just going to be incrementing or decrementing once.
Even if I do a
for a in range(15):
in python. Within that loop, I'm doing an action on one item. If I'm counting I'm most probably counting by 1.We do things all the time in coding by looking at things one at a time, that's why increment and decrement by 1 is so useful to me.
In this case, the candidate couldn't not understand how to increment a "pointer" by one and wanted to solve it with a list. They still figured it out, but it got me thinking of this and maybe we're moving away from really thinking of things one step at a time. To me, its a very useful skill, and the reason I ask the question.