Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Luminous
May 19, 2004

Girls
Games
Gains

That Turkey Story posted:

So what? Hypothetically, if && and || didn't short-circuit in C++ (as is the case for logical or and logical and in plenty of other languages), then would you consider these to be acceptable overloads? I don't see how that matters at all in theory nor in practice. When you see || and && in places that don't deal with bool you don't freak out about short-circuiting. It simply doesn't apply to those types.

Not that I disagree with your point, but I thought C++ does short-circuit bools. A cursory glance over google seems to agree. Edit: completely misread what you wrote.

That said, those that think the entire point of && and || is short-circuiting are in way too narrow of a mindset.

Adbot
ADBOT LOVES YOU

shrughes
Oct 11, 2008

(call/cc call/cc)

That Turkey Story posted:

Hypothetically, if && and || didn't short-circuit in C++ (as is the case for logical or and logical and in plenty of other languages), then would you consider these to be acceptable overloads?

Yes.

That Turkey Story posted:

I don't see how that matters at all in theory nor in practice.

It matters in practice because people will use them expecting them to short-circuit, and there are plenty of fine alternatives to overloading && and || that have less probability of fuckups.

That Turkey Story posted:

When you see || and && in places that don't deal with bool you don't freak out about short-circuiting.

You don't necessarily know what the types are by looking at the code, and somebody coming in trying to fix your code, or read your code, might expect the operator to short-circuit. This increases the probability of bugs.

Slanderer
May 6, 2007

That Turkey Story posted:

It's exactly as acceptable as it is for overloading of functions in general. Perhaps, though, you think that general function overloading isn't a good idea because it "makes something do something else." All an operator is is a function with a fancy name/syntax.

It is from your black womb that all coding horrors clawed their way into the light, screaming.

qntm
Jun 17, 2009

yaoi prophet posted:

You shouldn't operate + for strings because strings don't form a group under concatenation :colbert:

I've overloaded - for strings before now. If ABCD + EF = ABCDEF, then obviously ABCDEF - EF = ABCD, right? :v:

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

qntm posted:

I've overloaded - for strings before now. If ABCD + EF = ABCDEF, then obviously ABCDEF - EF = ABCD, right? :v:

In the case of string A minus string B, do you throw an exception if B is not a suffix to A or only if B does not appear in A at all?

qntm
Jun 17, 2009

Otto Skorzeny posted:

In the case of string A minus string B, do you throw an exception if B is not a suffix to A or only if B does not appear in A at all?

The former.

That Turkey Story
Mar 30, 2003

shrughes posted:

It matters in practice because people will use them expecting them to short-circuit...
No, it doesn't. "Short-circuiting" doesn't even mean anything in most of these domains. "Don't do the second part when the first part is true" doesn't apply when the left-hand operand isn't a "true" or "false" value. What would you even expect short-circuiting to mean there? The fact that you haven't produced a single example of where it is confusing is indicative of how weak your argument is. The only "example" so far is of somebody making an arbitrary "foo" type without any specified semantics nor a reason why he would expect short-circuiting or why he didn't use "bool" instead of his TrueBool type. Never in my life have I seen someone confused about short-circuiting behavior of an overloaded && or ||.

shrughes posted:

You don't necessarily know what the types are by looking at the code, and somebody coming in trying to fix your code, or read your code, might expect the operator to short-circuit. This increases the probability of bugs.
Again, you could say the exact same thing about overloading of any function, not just operators. "I don't know what this does" applies whether or not short-circuiting is involved.

E: To stress this -- if you don't know what the operands to the && and || are doing in the code that you are editing, how on earth would you be able to make proper changes to begin with? Short-circuiting or no short-circuiting you're completely missing what the problem is here...

That Turkey Story fucked around with this message at 21:33 on May 7, 2013

shrughes
Oct 11, 2008

(call/cc call/cc)

That Turkey Story posted:

Again, you could say the exact same thing about overloading of any function, not just operators.

Functions and other operators don't short circuit, so I don't see how you could say the same thing of them.

That Turkey Story posted:

No, it doesn't. "Short-ciruiting" doesn't even mean anything in most of these domains. "Don't do the second part when the first part is true" doesn't apply when the left-hand operand isn't a "true" or "false" value.

You seem to be under the misapprehension that I somehow didn't understand this.

That Turkey Story posted:

What would you even expect short-circuiting to mean there? The fact that you haven't produced a single example of where it is confusing is indicative of how weak your argument is.

You're bad at reasoning if you need an example. I'm pretty sure you don't believe the probability of bugs by overloading && is less than alternatives. Therefore it must be greater.

If you want to know what people expect short-circuiting to mean, well, it depends on the situation. People might just look at the code scanning for something other than its meaning, maybe looking for possible kinds of side effects they hope it avoids, and find themselves facing difficulty or confusion when coming across some && with the bad side effect on the right hand side. Suddenly they need to know the types of the expressions, the existence of some overload somewhere, in code they aren't familiar with.

There's a reason why security researchers have a harder time auditing C++ code than C code, and that reason is people like you.

That Turkey Story posted:

The only "example" so far is of somebody making an arbitrary "foo" type without any semantics nor a reason why he would expect short-circuiting or why he didn't use "bool" instead of his TrueBool type. Never in my life have I seen someone confused about short-circuiting behavior of an overloaded && or ||.

You could use it for constructing queries that get evaluated on a different machine than the one you're on. The product I work on does that. I've seen people confusedly expect short-circuiting behavior even when we overloaded the bitwise operators instead of the logical operators.

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender
I might argue that if a type has a well-known cast-to-bool operator with very "expected" semantics for that type, then it should not also have overloads for the short-circuiting operators, because when reading code that used them I would be expecting it to act like a bool and might be surprised that my control flow isn't what I expect.

That said, I don't see anything wrong with using operator overloads for && and || if your type doesn't pretend to be a bool at all. The confusion goes away completely.

Also, now I want C++14 to give me something like "int &&&i" as a parameter which produces a thunk for lazy evaluation.

raminasi
Jan 25, 2005

a last drink with no ice

ShoulderDaemon posted:

That said, I don't see anything wrong with using operator overloads for && and || if your type doesn't pretend to be a bool at all. The confusion goes away completely.

If your type doesn't have an intuitive interpretation as a true or false value than it's a lot harder to justify the overloads in the first place.

hobbesmaster
Jan 28, 2008

shrughes posted:

You could use it for constructing queries that get evaluated on a different machine than the one you're on. The product I work on does that. I've seen people confusedly expect short-circuiting behavior even when we overloaded the bitwise operators instead of the logical operators.

They'd be confused by the behavior of the built in types too; see the entire C programmers don't know what malloc/free do discussion from before.

shrughes
Oct 11, 2008

(call/cc call/cc)

That Turkey Story posted:

The fact that you haven't produced a single example of where it is confusing is indicative of how weak your argument is. The only "example" so far is of somebody making an arbitrary "foo" type without any specified semantics nor a reason why he would expect short-circuiting or why he didn't use "bool" instead of his TrueBool type.

The real problem here is the way you think about things. There's something broken with your thought processes if you go around thinking "there are no ways this could go wrong, I can't think of any" instead of "the benefits of overloading these operators outweigh the probable damage". Any time a software developer says "This won't lead to bugs", they are talking complete nonsense. Two approaches to doing something will alway have a not convincingly negligibly different expected amount of bugginess, unless in both cases it's very very close to zero.

That Turkey Story
Mar 30, 2003

shrughes posted:

Functions and other operators don't short circuit, so I don't see how you could say the same thing of them.
Read. Comprehend. Post.

shrughes posted:

You're bad at reasoning if you need an example. I'm pretty sure you don't believe the probability of bugs by overloading && is less than alternatives. Therefore it must be greater.
No, you're bad at reasoning if your entire premise is flawed (as is your case here). I've explained to you precisely why it is flawed, though you refuse to accept it, so I've moved on to trying to get you to produce an example of your hypothetical problem that would occur in practice (this shouldn't be that difficult to do if it's so clearly a horrible problem as you claim). I don't accept your ideological argument simply on faith, and if you think that it's a bad thing that I don't, then I don't know what to tell you. I'm going to be skeptical of claims that are entirely opposite of my experiences and whose whole premise isn't clear.

shrughes posted:

You could use it for constructing queries that get evaluated on a different machine than the one you're on. The product I work on does that. I've seen people confusedly expect short-circuiting behavior even when we overloaded the bitwise operators instead of the logical operators.
Code example, please. I don't immediately see how using bool operands wouldn't fix the "problem." All I see is a poorly designed API, not a flawed language feature.

ShoulderDaemon posted:

I might argue that if a type has a well-known cast-to-bool operator with very "expected" semantics for that type, then it should not also have overloads for the short-circuiting operators, because when reading code that used them I would be expecting it to act like a bool and might be surprised that my control flow isn't what I expect.

That said, I don't see anything wrong with using operator overloads for && and || if your type doesn't pretend to be a bool at all. The confusion goes away completely.

Exactly, exactly, exactly.

And examples of where, in practice, && and || are overloaded perfectly fine are lambda EDSLs like Boost.Phoenix. I think I'm aware of your stance on expression templates, though, so I assume I'm talking to a wall at this point.

shrughes
Oct 11, 2008

(call/cc call/cc)

That Turkey Story posted:

Code example, please. I don't immediately see how using bool operands wouldn't fix the "problem." All I see is a poorly designed API, not a flawed language feature.

As I said, expressions evaluated on a different machine. You can't use bool operands because they would have to be evaluated on your machine.

That Turkey Story
Mar 30, 2003

shrughes posted:

The real problem here is the way you think about things. There's something broken with your thought processes if you go around thinking "there are no ways this could go wrong, I can't think of any" instead of "the benefits of overloading these operators outweigh the probable damage".
No, the difference between the way you and I think is that I will not swear off a tool because it has the chance of being misused. Any non-trivial tool can be misused. No one is saying that you can't make weird, unintuitive things with a feature like overloading, but that's true of just about any language feature. The way that you seem to look at things is "I can come up with a contrived situation where this might be unintuitive, therefore the entire feature is flawed." It's not.

That Turkey Story
Mar 30, 2003

shrughes posted:

As I said, expressions evaluated on a different machine. You can't use bool operands because they would have to be evaluated on your machine.

If that's the case, then why aren't your operands lazy???

Scaevolus
Apr 16, 2007

Overloaded functions and operators should share similar semantics-- principle of least surprise.

operator&& forces you to have different semantics than the normal operator&&, which can cause confusion.

Confusion leads to inaccurate mental models, which leads to more bugs being produced.

Victor
Jun 18, 2004

That Turkey Story posted:

And examples of where, in practice, && and || are overloaded perfectly fine are lambda EDSLs like Boost.Phoenix. I think I'm aware of your stance on expression templates, though, so I assume I'm talking to a wall at this point.
Perhaps this is ok explicitly because the Boost folks reconstruct the short-circuiting behavior? Search for 'short-circuit' in operators.hpp.

shrughes
Oct 11, 2008

(call/cc call/cc)

Victor posted:

Perhaps this is ok explicitly because the Boost folks reconstruct the short-circuiting behavior? Search for 'short-circuit' in operators.hpp.

The expression that constructs the argument to && isn't short-circuited, though. It might be okay because nobody in their right mind would use that library anyway.

gonadic io
Feb 16, 2011

>>=

Van Kraken posted:

It's settled, we're using * for string concatenation now.

If strings don't form an abelian group they sure as gently caress don't form a ring. Don't you know anything about programming?

shrughes
Oct 11, 2008

(call/cc call/cc)
Clearly we should use the whitespace operator for string concatenation.

Blotto Skorzany
Nov 7, 2008

He's a PSoC, loose and runnin'
came the whisper from each lip
And he's here to do some business with
the bad ADC on his chip
bad ADC on his chiiiiip

shrughes posted:

Clearly we should use the whitespace operator for string concatenation.

http://codepad.org/gte6Qoby :q:

That Turkey Story
Mar 30, 2003

Victor posted:

Perhaps this is ok explicitly because the Boost folks reconstruct the short-circuiting behavior? Search for 'short-circuit' in operators.hpp.
It's only doing short-circuiting of the deferred operation, as you would except. The actual operands aren't short-circuited, nor would the term "short-circuiting" on the top-level really make any sense in this context, as is often the case when overloading these operators.

shrughes posted:

The expression that constructs the argument to && isn't short-circuited, though. It might be okay because nobody in their right mind would use that library anyway.
Yes, just entirely disregard a useful library because it uses a technique you ideologically oppose.

shrughes
Oct 11, 2008

(call/cc call/cc)

That Turkey Story posted:

Yes, let's just entirely disregard a useful library because it uses a technique you ideologically oppose.

That's not the reason to disregard it.

(Why did you believe it was? Weird thoughts that have nothing to do with reality just keep popping out of your mouth [1]!)







[1] hands

facepalmolive
Jan 29, 2009

AlsoD posted:

If strings don't form an abelian group they sure as gently caress don't form a ring. Don't you know anything about programming?

Well clearly the best way is to fix this is to redefine the string class to commute.

hobbesmaster
Jan 28, 2008

shrughes posted:

That's not the reason to disregard it.

(Why did you believe it was? Weird thoughts that have nothing to do with reality just keep popping out of your mouth [1]!)







[1] hands

So what do you have against functional programming?

shrughes posted:

That's not the reason to disregard it.

(Why did you believe it was? Weird thoughts that have nothing to do with reality just keep popping out of your mouth [1]!)







[1] hands

So do you hate functional programming or EDSLs in general or what?

That Turkey Story
Mar 30, 2003

shrughes posted:

That's not the reason to disregard it.

(Why did you believe it was? Weird thoughts that have nothing to do with reality just keep popping out of your mouth [1]!)







[1] hands
:rolleyes:

Because I seem to remember you making pretty broad, negative claims about expression templates in the past. If you don't have a problem with expression templates, then whatever.

Edit: Functional programming libraries are also one of the most fundamental libraries you can develop with expression templates. If you're not against expression templates, just what is it that makes you say that no one in their right mind would use Boost.Phoenix?

That Turkey Story fucked around with this message at 23:38 on May 7, 2013

gonadic io
Feb 16, 2011

>>=

facepalmolive posted:

Well clearly the best way is to fix this is to redefine the string class to commute.

Nah, group elements need an inverse too which strings can't* have. Depending on how picky you are about semantics, strings could be considered to form a monoid however and wouldn't you know it, Haskell has those!**
code:
instance Monoid String where
    mempty = ""
    mappend = (++)

(<>) :: Monoid m => m -> m -> m
(<>) = mappend

"foo" <> "bar" == "foobar"
[1,2,3] <> [4,5] == [1,2,3,4,5]
appEndo (Endo (*3) <> Endo (*2)) 2 == 12
The last example demonstrates how functions (in the Endo wrapper) also form a monoid where mempty is id and mappend is function composition.

*: shouldn't
**: yes I know this isn't the exact definition but it's close enough

gonadic io fucked around with this message at 23:34 on May 7, 2013

raminasi
Jan 25, 2005

a last drink with no ice

hobbesmaster posted:

So what do you have against functional programming?

Oh, come on.

e: To be a little more constructive: You really can't think of a reason that someone might recommend against using Boost.Phoenix other than a problem with functional programming? I'm sure even TTS could come up with something someone might say, even if he strenuously disagrees with it.

raminasi fucked around with this message at 23:39 on May 7, 2013

evilentity
Jun 25, 2010

seiken posted:

I stumbled across this thread on another forum that's from a year and a half ago so it's kind of old, but it's too good not to share.

Your opinion on the functionality of a template dynamic list

Basically, a clueless C++ guy ranting for several pages about how terrible the standard library is (while completely misunderstanding it) and showing off his crazy hand-rolled replacement where pretty much every function is called operator=.

Holy loving poo poo this is :psyboom:. Poor person guy.

If you missed it from few pages back its worth a read.

Victor
Jun 18, 2004

That Turkey Story posted:

It's only doing short-circuiting of the deferred operation, as you would except. The actual operands aren't short-circuited, nor would the term "short-circuiting" on the top-level really make any sense in this context, as is often the case when overloading these operators.
Wait a second, so if I take a bunch of code and switch it to the deferred execution model, it silently switches from short-circuiting to not short-circuiting? How is this anything but bad? How many people are going to realize, "oh, since this is a lazy evaluation library, && and || are no longer short-circuited"?

Dren
Jan 5, 2001

Pillbug
This has been a great flamewar interspersed with math jokes, guys. :munch:

PS - shrughes, I like to think of it as the double double quote operator, not the whitespace operator.

Doctor w-rw-rw-
Jun 24, 2008
I don't program C++ (but have dabbled) and a big reason for that is that there are so many ways a codebase can alter the semantics of something innocent-looking.

The excuse that you should be able to alter the semantics of basic operators because all you need to do is be cautious and aware of the consequences is an awful excuse and an ignorant one. There's more to programming than abstraction or analogies to similar structures. There's also maintainability. it is important to avoid cognitive overload, and not have to learn a different sort-of-DSL for each codebase you examine, or worse, learn one that is very nearly identical to another, but different.

When ObjectWithOverload && foo is different from booleanExpression && foo in both short-circuiting and laziness semantics, you have the same token signifying two very different operations with very different semantics. Given how common logical operators are, in any codebase of reasonable size or developer participation, this will cause confusion if used as such. Period. Confusion leads to an incomplete mental model leads to bugs. Period. If it's going to act like a method, just write and call a method instead, for everyone else's sake.

When you overload an operator to make it mean something different, you are changing it for yourself but you're also loving with the expectations of newbie programmer looking at your code. It is a monumentally bad practice to surprise developers like that and if you disagree you are a programmer I would hate to be on a team with, no matter how otherwise talented you may be.

That Turkey Story
Mar 30, 2003

GrumpyDoctor posted:

e: To be a little more constructive: You really can't think of a reason that someone might recommend against using Boost.Phoenix other than a problem with functional programming? I'm sure even TTS could come up with something someone might say, even if he strenuously disagrees with it.

Compile times and error messages are the big ones, although prior to lamdas being in the language, you didn't really have any better alternative, and even now the library approach can be more capable than the language approach in some respects (sadly). The next standard will fix at least a little of that, though. The point is, regardless of these issues, sane people really do use these libraries and the result is very concise and easy to read. It's a trade-off like anything else. You are not insane for using it.


Victor posted:

Wait a second, so if I take a bunch of code and switch it to the deferred execution model, it silently switches from short-circuiting to not short-circuiting? How is this anything but bad? How many people are going to realize, "oh, since this is a lazy evaluation library, && and || are no longer short-circuited"?
No. The deferred operation is still short-circuited, just like you would expect. It's the top-level operation that's not short-circuited. Again, "short-circuiting" doesn't even make sense in this domain other than with respect to the deferred operation.

Edit: An example:

code:
int main()
{
  auto function = ( arg1 != 0 ) && ( 1 / arg1 != 1 );
  function( 0 ); // This will not cause a divide by 0
}

That Turkey Story fucked around with this message at 23:55 on May 7, 2013

Dren
Jan 5, 2001

Pillbug

Doctor w-rw-rw- posted:

and not have to learn a different sort-of-DSL for each codebase you examine

I strongly agree with this sentiment. Operator overloading is a way of making little half-DSLs. E.g. the operator= guy did it all over the place: http://en.sfml-dev.org/forums/index.php?topic=5792.0

C++ is already peppered with the use of operator overloading to create little half-DSLs but just because it's in the STL and boost doesn't mean it's a good idea to do it in your code too.

shrughes
Oct 11, 2008

(call/cc call/cc)

Doctor w-rw-rw- posted:

When ObjectWithOverload && foo is different from booleanExpression && foo in both short-circuiting and laziness semantics, you have the same token signifying two very different operations with very different semantics. Given how common logical operators are, in any codebase of reasonable size or developer participation, this will cause confusion if used as such. Period.

Don't be ridiculous, such an absolute statement has no chance of being correct -- there are positives to overloading the short-circuiting operators, and what if you're in a situation where there are no negatives? [1]

It's a trade-off between convenience 'n lookin' good and understandability [2]. Suppose your library has already overloaded & and | for something. And it's overloaded * and / and + and - and % and ^ and, I don't know, the comma operator (lol). And operator[] and operator(). Then all you gots left is the short-circuiting and operator (&&), the short-circuiting or operator (||), and the short-circuiting xor operator (^^). You have to overload those, because what are you going to do, write a function call? I've written things in terms of regular old functions when making embedded expression grammar libraries and trust me, it's slightly inconvenient. Imagine having to write alt(foo, bar, baz) instead of foo || bar || baz. That would be terrible, because then anybody could grep your code!

[1] For example, suppose nobody wants to maintain your code, so they always rewrite it.

[2] Treat "'n" as a higher-precedence conjunction than "and".

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe

shrughes posted:

and the short-circuiting xor operator (^^)

Is this a thing? I'm quite sure you have to always evaluate both sides for XOR.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

That Turkey Story posted:

Compile times and error messages are the big ones, although prior to lamdas being in the language, you didn't really have any better alternative, and even now the library approach can be more capable than the language approach in some respects (sadly).
And ridiculously less verbose in some cases.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Suspicious Dish posted:

Is this a thing? I'm quite sure you have to always evaluate both sides for XOR.
^^ isn't even a operator at all (it's !=).

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008

shrughes posted:

Don't be ridiculous, such an absolute statement has no chance of being correct -- there are positives to overloading the short-circuiting operators, and what if you're in a situation where there are no negatives? [1]

It's a trade-off between convenience 'n lookin' good and understandability [2]. Suppose your library has already overloaded & and | for something. And it's overloaded * and / and + and - and % and ^ and, I don't know, the comma operator (lol). And operator[] and operator(). Then all you gots left is the short-circuiting and operator (&&), the short-circuiting or operator (||), and the short-circuiting xor operator (^^). You have to overload those, because what are you going to do, write a function call? I've written things in terms of regular old functions when making embedded expression grammar libraries and trust me, it's slightly inconvenient. Imagine having to write alt(foo, bar, baz) instead of foo || bar || baz. That would be terrible, because then anybody could grep your code!

[1] For example, suppose nobody wants to maintain your code, so they always rewrite it.

[2] Treat "'n" as a higher-precedence conjunction than "and".

So what you're saying is that if your library has already overloaded lots of operators, it's not a big deal to modify two more?

I would agree with that, because at that point you've already implemented a mini-DSL and an expectation for weirdness (that is hopefully consistent within itself, at least) is already in place, and newbie confusion (followed by the requisite training) is already a matter of course. Now, I would still avoid it, but if it fits, it fits.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply