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
rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Xarn posted:

Using ternary operator to assign to a bit field you say? I think I have a new piece of code to scare people with. :v:

Yeah, it’s good for screwing with people who proclaim the “expression has type int &” heresy.

Adbot
ADBOT LOVES YOU

Xarn
Jun 26, 2015
I tested it and MSVC doesn't handle it either, and the error message is really bad.

Xarn
Jun 26, 2015

rjmccall posted:

Assigning to a conditional operator is home to a lovely bit of still-unimplemented behavior in Clang, by the way: note that the operands can be any sort of l-value, including a bit-field.

I swear this is the last time I am bringing this up -> is it actually part of standard c++? I did some research and I am not sure it is.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Xarn posted:

I swear this is the last time I am bringing this up -> is it actually part of standard c++? I did some research and I am not sure it is.

”C++ [expr.cond]p5” posted:

If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.

FlapYoJacks
Feb 12, 2009

Xarn posted:

I swear this is the last time I am bringing this up -> is it actually part of standard c++? I did some research and I am not sure it is.

Yes

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



ratbert90 posted:

1) That’s C.
2) That seems fine.

I'm just imagining the "This is fine" dog but instead of flames it's all C++ horrors. Of course, he still melts in the end.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Thermopyle posted:

That reminds me of the GPS fleet tracker I use on my one company vehicle for my one employee. (not a web dev or technology company)

It's made by TrackmateGPS and it's something like this. They completely redesigned their website 6 months ago and its terrible.

It does all sorts of requests from the frontend that should be done by the backend and aggregated into one request from the frontend. For example, the history report you can do makes this list of all the events...ignition on, ignition off, stops, gps updates, etc. It does multiple requests for each event to their own servers and to Google APIs. So, it's not uncommon for a history report to make several thousand requests from your browser which makes all other tabs unusable while they wait for a free socket to make their own requests on.

Also, the scroll position on this stupid list of events resets on each request so you have to just leave the page alone until it finishes.

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

It works™

Carbon dioxide
Oct 9, 2012

https://www.youtube.com/watch?v=eyH4aXlB1Js

Remulak
Jun 8, 2001
I can't count to four.
Yams Fan

Xarn posted:

Using ternary operator to assign to a bit field you say? I think I have a new piece of code to scare people with. :v:
I'll shake your hand and congratulate you during your exit interview.

FlapYoJacks
Feb 12, 2009

Munkeymon posted:

I'm just imagining the "This is fine" dog but instead of flames it's all C++ horrors. Of course, he still melts in the end.

Except a Ternary is just a compact if else statement, so it really is just fine.

Workaday Wizard
Oct 23, 2009

by Pragmatica

ratbert90 posted:

Except a Ternary is just a compact if else statement, so it really is just fine.

i thought it was an expression. (ie it has a value)

Absurd Alhazred
Mar 27, 2010

by Athanatos

ratbert90 posted:

Except a Ternary is just a compact if else statement, so it really is just fine.

A compact with THE DEVIL!

Ola
Jul 19, 2004

Shinku ABOOKEN posted:

i thought it was an expression. (ie it has a value)

Yeah, you can't put an if else left of the equals sign.

Phobeste
Apr 9, 2006

never, like, count out Touchdown Tom, man
Uhhhhh but how would I do pluralization without ternaries? Ever thing about THAT?

putin is a cunt
Apr 5, 2007

BOY DO I SURE ENJOY TRASH. THERE'S NOTHING MORE I LOVE THAN TO SIT DOWN IN FRONT OF THE BIG SCREEN AND EAT A BIIIIG STEAMY BOWL OF SHIT. WARNER BROS CAN COME OVER TO MY HOUSE AND ASSFUCK MY MOM WHILE I WATCH AND I WOULD CERTIFY IT FRESH, NO QUESTION

ratbert90 posted:

Except a Ternary is just a compact if else statement, so it really is just fine.

Er... What?

FlapYoJacks
Feb 12, 2009

Doesn’t:

return (a == 1) ? 20 : 30

Evaluate to:

code:
if (a == 1){
    return 20;
} else {
    return 30;
}
:confused:

If it doesn’t, I have a good decades worth of code to go fix...

Ola
Jul 19, 2004

ratbert90 posted:

Doesn’t:

return (a == 1) ? 20 : 30

Evaluate to:

code:
if (a == 1){
    return 20;
} else {
    return 30;
}
:confused:

If it doesn’t, I have a good decades worth of code to go fix...

They're not equivalent. Anything can happen in an if else block.

code:
if (a == 1){
    b = 20;
} else {
    c = "I am crazy!";
    goHogWild(c);
}

A ternary has to return evaluate to one of two values of the same type.

Ola fucked around with this message at 14:02 on Sep 14, 2018

FlapYoJacks
Feb 12, 2009

Ola posted:

They're not equivalent. Anything can happen in an if else block.

code:
if (a == 1){
    b = 20;
} else {
    c = "I am crazy!";
    goHogWild(c);
}
A ternary has to return evaluate to one of two values of the same type.

Right?
A ternary is a if else
A if else isn’t necessarily a ternary.

Soricidus
Oct 21, 2010
freedom-hating statist shill

Ola posted:

They're not equivalent. Anything can happen in an if else block.

code:
if (a == 1){
    b = 20;
} else {
    c = "I am crazy!";
    goHogWild(c);
}
A ternary has to return evaluate to one of two values of the same type.

The point is not that they’re the same thing, it’s that the ternary operator is always trivially replaceable with an if/else

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



ratbert90 posted:

Except a Ternary is just a compact if else statement, so it really is just fine.

Played around a bit on codepad and I guess it's not that bad because it does at least make sure the types are sane. It's the assignment of a number to a char in the original example that's probably throwing me because I'm now used to languages where char isn't a funny way to say byte

FlapYoJacks
Feb 12, 2009

Munkeymon posted:

Played around a bit on codepad and I guess it's not that bad because it does at least make sure the types are sane. It's the assignment of a number to a char in the original example that's probably throwing me because I'm now used to languages where char isn't a funny way to say byte

Which is funny because when I go to a higher level language, I have to get used to char not being a byte. :v:

Edit;

The original value has 3 ints? :confused:

code:
#include <stdio.h>

int main(int argc, char **argv){
    int a = 0;
    int b = 0;
    (argc == 2 ? a : b) = 5;
}
In that example, a,b and argc are all ints.

This is equivalent to:
code:
#include <stdio.h>

int main(int argc, char **argv){
    int a = 0;
    int b = 0;
    if (argc == 2){
        a = 5;
    } else {
        b = 5;
    }
}

FlapYoJacks fucked around with this message at 14:38 on Sep 14, 2018

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Oh dang I forgot about the tweet that started the whole thing and was looking at b0lt's example :shrug:

Still one of those things I'd reject in a review because You're Being Too Dang Clever.

Ola
Jul 19, 2004

ratbert90 posted:

Right?
A ternary is a if else
A if else isn’t necessarily a ternary.

Right. A ternary always evaluates to something, an if/else is just a conditional and two paths of code. If you return something there, it's the parent function that is returning, not the if/else block. You can also use a method call to assign, if it's a reference:

code:
int& pickOne(int &a, int &b){
    //big complex if/else goes here
    return a;
}

int dontPickOne(int a, int b){
    return a;
}

int main() {
    int a=1,b=2;
    (randomBool()?a:b) = 5; //ok
    pickOne(a,b) = 5; //ok
    dontPickOne(a,b) = 5; //not ok
}
Why? I don't know. Is it good? I...don't know.

xtal
Jan 9, 2011

by Fluffdaddy
Phrasing it like "a ternary evaluates to an if-statement" makes it sound like it's a macro or syntactic sugar. Their semantics overlap but they aren't equivalent. Maybe this is a time to bust out the word isomorphic.

1337JiveTurkey
Feb 17, 2005

For extra compactness it should be possible to write something along the lines of

code:
(foo? a : b) = (bar? x : y)
I've wanted to be able to do that in the past because otherwise you're writing

code:
if (foo) {
	if (bar) {
		a = x;
	}
	else {
		a = y;
	}
else {
	if (bar) {
		b = x;
	}
	else {
		b = y;
	}
}

xtal
Jan 9, 2011

by Fluffdaddy
That code seems like a problem in its own right

CPColin
Sep 9, 2003

Big ol' smile.
Also, we're talking about the conditional operator, which is a ternary operator, but not all ternary operators are the conditional operator. :v: (But I can't think of another ternary operator that I use ever.)

xtal
Jan 9, 2011

by Fluffdaddy
If you wanted a horrific conditional operator, there's this:

code:
data Cond a = a :? a
 
infixl 0 ?
infixl 1 :?
 
(?) :: Bool -> Cond a -> a
True  ? (x :? _) = x
False ? (_ :? y) = y
 
test = 1 < 2 ? "Yes" :? "No"

Mooey Cow
Jan 27, 2018

by Jeffrey of YOSPOS
Pillbug

Ola posted:

Why? I don't know. Is it good? I...don't know.

Why? These kinds of lvalue expressions are basically what makes the typical iterator range copy look like this
code:
*dst++ = *src++;
(very common idiom in C, so C++ generalizes it for overloadable operators)

operator++ (post) increments the variable, then returns the original value, which is then passed to operator*, which returns a reference so it can be used as an lvalue, and its copy (or move) assignment operator can be invoked (which also returns an lvalue, so assignments can be chained).

Is it good? Yeah it's pretty good. Consider an index operator where you want to be able to modify the thing at the index, so all you have to do is return a different reference based on the input to the operator function.

I don't see why being able to assign to a ternary expression that returns an lvalue is particularly baffling :confused:

VikingofRock
Aug 24, 2008




It's been a while since I looked into it, so this might have changed in C++17 or something, but IIRC there are places where you can use a ternary but can not trivially replace it with an if-else because the syntax demands it evaluates to an expression. For example I believe you can use constexpr ternaries in template parameters, but not if-else.

Ola
Jul 19, 2004

Mooey Cow posted:


I don't see why being able to assign to a ternary expression that returns an lvalue is particularly baffling :confused:

I didn't mean to sound like I was passing judgement on C++. I'm very new to it, and it was baffling to me to see an expression on the left hand side of an assignment. I think I might fall into a trap where I try to shoehorn it in somewhere.

redleader
Aug 18, 2005

Engage according to operational parameters

1337JiveTurkey posted:

For extra compactness it should be possible to write something along the lines of

code:
(foo? a : b) = (bar? x : y)

I'll allow it on the grounds that it is amusingly symmetrical, which pleases me.

Spatial
Nov 15, 2007

That is kinda useful. I can't wait to break a few brains with that one.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
Just found out that if you want to declare a jagged array in C#, and you want to explicitly size the outer dimension of the array, you have to do it the wrong way around. I don't know what's going on there.

i.e. you have to write "var myArray = new Thing[10][];" instead of "var myArray = new Thing[][10];"

TooMuchAbstraction
Oct 14, 2012

I spent four years making
Waves of Steel
Hell yes I'm going to turn my avatar into an ad for it.
Fun Shoe
That looks right to me? It matches the order in which you'd index into the array. "I have an array of 10 elements, each of which has variable size" should be written as arr[10][]. arr[][10] should be for when you say "I have a variable number of arrays each of which has length 10."

Soricidus
Oct 21, 2010
freedom-hating statist shill

TooMuchAbstraction posted:

That looks right to me? It matches the order in which you'd index into the array. "I have an array of 10 elements, each of which has variable size" should be written as arr[10][]. arr[][10] should be for when you say "I have a variable number of arrays each of which has length 10."

if int[10] is an array of 10 ints, then int[][10] should be an array of 10 int[]s :colbert:

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

TooMuchAbstraction posted:

That looks right to me? It matches the order in which you'd index into the array. "I have an array of 10 elements, each of which has variable size" should be written as arr[10][]. arr[][10] should be for when you say "I have a variable number of arrays each of which has length 10."

When you stick a "[]" on the end of the variable type, that means 'I want an array of the thing to the left of the "[]"'. When you stick a "[n]" on the end, that means 'I want an array, length n, of the thing to the left of the "[n]"'.

Going from Thing to Thing[] to Thing[][n] is an iterative process; I start with a Thing, then I say actually what I want is an array of Things, then I say actually what I really want is an array, length n, of arrays of Things. It's built up by repeatedly sticking "[]" or "[n]" on the right-hand end of the type. That's why the outer dimension ought to be the one with the "n" - it's the dimension added last of all - and it comes as a surprise to me that the language doesn't have it work like that.

Yes, a logical consequence of the arrangement I advocate for is that the order at declaration would have to be the opposite of the order when indexing. It doesn't matter.

1337JiveTurkey
Feb 17, 2005

redleader posted:

I'll allow it on the grounds that it is amusingly symmetrical, which pleases me.

Really the biggest justification I can see for it is based on Bill Lear's old airplane design adage "If it looks good, it will fly good."

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
This is a fundamental tension with nested arrays:

1. It's really nice to just have a simple type-structuring rule like "an array has a bound and an element type" instead of embracing the extra complexity of directly supporting multi-dimensional arrays.
2. It's really nice to use the postfix square-bracket syntax for accessing an array element.
3. Assuming you've settled on using the square-bracket expression syntax, it's really nice to use the same syntax for writing the bound of an array type. It's a natural analogy that reads well and has no problems for non-nested arrays, which are massively more common.
4. In the expression syntax, array[i] accesses the ith element of array.
4a. Therefore, basic decomposition suggests that array[i][j] accesses the jth element of the ith element of array. The major index is written first.
5. In the type syntax, SomeType[N] is an N-bounded array of SomeType.
5a. The obvious recursive grammar rule for this is that SomeType can be any type, including an array type. But this leads to int[M][N] meaning an M-bounded array of N-bounded arrays of int. The major bound is written last, which is backwards from the expression syntax.
5b. This is why C has a crazy definition-follows-use rule where you can have arbitrary nested type-structure that has to be read inside-out, so int (*fn())[N] is a nullary function returning a pointer to an N-array of int. This gives us what we want: in int[M][N], the major bound is written first.
5c. Java and C# don't have arbitrary nested type-structure; they just have arrays. Furthermore, IIRC arrays are always unbounded outside of new expressions, meaning that types always look like int[][], meaning that the parse order is irrelevant. The languages therefore just have a special rule for new expressions which reverses the bounds, so that the major index is written first.

The only reasonable alternatives are to either (a) abandon (1) and provide multi-dimensional arrays, thus heavily discouraging nested arrays (but not technically eliminating the problem), or (b) abandon (3) and use a syntax that places the bound to the left, so that you get e.g. [M x [N x int]].

rjmccall fucked around with this message at 23:41 on Sep 14, 2018

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