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
gonadic io
Feb 16, 2011

>>=

Dren posted:

a great flamewar interspersed with math jokes

Pretty sure this is a statement about the field of programming.

Adbot
ADBOT LOVES YOU

That Turkey Story
Mar 30, 2003

Plorkyeran posted:

And ridiculously less verbose in some cases.

Almost all cases, which is really sad. I sort of wish they just made something like argn reserved identifiers and allowed you to form lambda expressions around them, a lot like how the library approaches have to do it, but the language approach would work with function calls and control statements without having to make "lazy" versions.

E: Even in C++14 it's going to be verbose, especially if you want stuff like automatically deduced exception specifications. A library-based approach allows for automatic exception specifications, automatically deduced return types, unspecified parameter types, and more, which in practice you want almost all of the time. Using the argn approach, you need to employ no extra effort to get it.

That Turkey Story fucked around with this message at 00:10 on May 8, 2013

Victor
Jun 18, 2004

That Turkey Story posted:

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
}
I admit that I don't know how they accomplish this and I'm not sure I'm sufficiently interested to find out how. I admit your example has become motivating, but for a single reason: it preserves short-circuiting. There is no surprise with the example code above. I'm not sure anyone here would be unhappy with that instance of overloading || and &&.

shrughes
Oct 11, 2008

(call/cc call/cc)

Victor posted:

I admit that I don't know how they accomplish this and I'm not sure I'm sufficiently interested to find out how. I admit your example has become motivating, but for a single reason: it preserves short-circuiting. There is no surprise with the example code above. I'm not sure anyone here would be unhappy with that instance of overloading || and &&.

Note that (arg1 != 0) && (1 / 0 != 1) would crash. And (arg1 != 0) && my_retarded_expression_builder() would exhibit all the side effects of my_retarded_expression_builder().

Victor
Jun 18, 2004

shrughes posted:

Note that (arg1 != 0) && (1 / 0 != 1) would crash. And (arg1 != 0) && my_retarded_expression_builder() would exhibit all the side effects of my_retarded_expression_builder().
Ahh. Then there isn't as much C++ wizardry as I thought—I was kinda wondering how one could deal with the case you brought up. Thanks for misleading me, TTS! I have concluded that overloading || and && is dumb, if you care about maintainability and/or readability. Some people admittedly don't.

That Turkey Story
Mar 30, 2003

Victor posted:

Ahh. Then there isn't as much C++ wizardry as I thought—I was kinda wondering how one could deal with the case you brought up. Thanks for misleading me, TTS! I have concluded that overloading || and && is dumb, if you care about maintainability and/or readability. Some people admittedly don't.

??? What? How is that misleading? It's exactly what he and I have both been saying repeatedly. We weren't even in disagreement.

That said, if for some reason you did want this [nonsensical] code to work, you could -- just make the offending part dependent on an actor.

That Turkey Story fucked around with this message at 07:39 on May 8, 2013

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!
A minor horror, but I found a data pool that I had mislabeled as "poot" in my code for a bit. It must be how late it is, but the idea of my code having farts in it is making me giggle too much. The code smells!

Hammerite
Mar 9, 2007

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

AlsoD posted:

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 ...

Out of curiosity, what sort of pickiness would say that the set of strings under concatenation isn't a monoid? It appears cut and dried to me.

gonadic io
Feb 16, 2011

>>=

Hammerite posted:

Out of curiosity, what sort of pickiness would say that the set of strings under concatenation isn't a monoid? It appears cut and dried to me.

When reasoning about things like this especially in Haskell it's generally considered in a more 'ideal' world than is actually the case. Just off the top of my head, (++) is O(n) where n is the length of the first argument i.e. the former is slower than the latter:
code:
("123" ++ "456") ++ "789"
"123" ++ ("456" ++ "789")
Does this count as 'different'? I'm pretty sure the former allocates more memory too since the first argument to (++) becomes a new String while the second is just pointed to. It all depends on, as I said, how picky you're being and is also a good example on why you should never use Haskell's default String type for anything serious (use Data.Text instead).

e: and if you consider unsafePerformIO then things get really weird

VVVV: What you need to know about category theory to use monoids in Haskell:
  • You can use (++) or (<>) to concatenate strings
  • If you use the latter your error messages will be more complicated

gonadic io fucked around with this message at 10:37 on May 8, 2013

Captain Capacitor
Jan 21, 2008

The code you say?
Nothing like whatever the last 5 pages was about to make me go crosseyed and feel very, very dumb.

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

Captain Capacitor posted:

Nothing like whatever the last 5 pages was about to make me go crosseyed and feel very, very dumb.

I really wonder how many programmers understand all that without a CS degree. Very, very few I'd imagine.

Opinion Haver
Apr 9, 2007

AlsoD posted:

When reasoning about things like this especially in Haskell it's generally considered in a more 'ideal' world than is actually the case. Just off the top of my head, (++) is O(n) where n is the length of the first argument i.e. the former is slower than the latter:
code:
("123" ++ "456") ++ "789"
"123" ++ ("456" ++ "789")
Does this count as 'different'? I'm pretty sure the former allocates more memory too since the first argument to (++) becomes a new String while the second is just pointed to. It all depends on, as I said, how picky you're being and is also a good example on why you should never use Haskell's default String type for anything serious (use Data.Text instead).

e: and if you consider unsafePerformIO then things get really weird


I can't imagine a single reason to consider performance relevant to the monoid-ness of something; if you do, anything other than 'addition and multiplication of machine-size integers' probably won't be one.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

yaoi prophet posted:

if you do, anything other than 'addition and multiplication of machine-size integers' probably won't be one.

I think you could at least extend it to any operation on a finite group, since those are all constant-time - in the sense that you can pick a constant c such that any operation can be guaranteed to take less than c units of time to complete.

Volmarias
Dec 31, 2002

EMAIL... THE INTERNET... SEARCH ENGINES...

Rocko Bonaparte posted:

A minor horror, but I found a data pool that I had mislabeled as "poot" in my code for a bit. It must be how late it is, but the idea of my code having farts in it is making me giggle too much. The code smells!

On a related note, I smiled when someone marked a code review with "looks good, make sure you blah blah blah then you can poo poo it"

Volte
Oct 4, 2004

woosh woosh
When writing some code for doing MRI simulations I had a process for performing phase-encoding shots and counting them for the current image and cumulatively. Naturally, two accumulator variable names arose: cur_shot_count and cum_shot_count.

Opinion Haver
Apr 9, 2007

I'm personally a big fan of cumtrapz.

Van Kraken
Feb 13, 2012

Captain Capacitor posted:

Nothing like whatever the last 5 pages was about to make me go crosseyed and feel very, very dumb.

People are throwing around a bunch of jargon, but the basic ideas aren't too hard to understand. All the jokes are around the idea of a group in mathematics.

If you have a set G (e.g. strings) and an binary operator * (e.g. concatenation), then they form a group if the following 4 conditions are met:
  • Closure: for any a and b in G, a * b is also in G.
  • Associativity: (a * b) * c = a * (b * c).
  • Identity: there exists some element e in G such that a * e = e * a = a for every a. For strings, this would be "".
  • Inverses: for every element a, there is another element a-1 such that a * a-1 = a-1 * a = e

A monoid is the same thing, except it doesn't require inverses. The set of strings under concatenation meets the first three requirements, but not the fourth, so it is a monoid, but not a group. Also, a group is called abelian if elements commute with each other, a * b = b * a.

zergstain
Dec 15, 2005

Thanks. I only have 3 semesters left in my degree, and I still had no clue what any of that was about.

Hammerite
Mar 9, 2007

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

AlsoD posted:

When reasoning about things like this especially in Haskell it's generally considered in a more 'ideal' world than is actually the case. Just off the top of my head, (++) is O(n) where n is the length of the first argument i.e. the former is slower than the latter:
code:
("123" ++ "456") ++ "789"
"123" ++ ("456" ++ "789")
Does this count as 'different'? I'm pretty sure the former allocates more memory too since the first argument to (++) becomes a new String while the second is just pointed to. It all depends on, as I said, how picky you're being and is also a good example on why you should never use Haskell's default String type for anything serious (use Data.Text instead).

e: and if you consider unsafePerformIO then things get really weird

VVVV: What you need to know about category theory to use monoids in Haskell:
  • You can use (++) or (<>) to concatenate strings
  • If you use the latter your error messages will be more complicated

I don't know anything about Haskell, I was coming at it purely from a maths standpoint. I appreciate that it is more complicated if you have to consider how a computer language actually implements stuff. Hope I didn't annoy you by causing you to effortpost.

Van Kraken posted:

A monoid is the same thing, except it doesn't require inverses. The set of strings under concatenation meets the first three requirements, but not the fourth, so it is a monoid, but not a group. Also, a group is called abelian if elements commute with each other, a * b = b * a.

For didactic purposes: another example of a monoid is the set of real numbers under multiplication, in fact any field under its multiplication operation.

Dren
Jan 5, 2001

Pillbug
I wish SA had a like post button because I lol'd hard at cumtrapz and "Pretty sure this is a statement about the field of programming."

(USER WAS PUT ON PROBATION FOR THIS POST)

Rottbott
Jul 27, 2006
DMC
Found in our old C code:

code:
enum
{
	EL_NORMAL,
	EL_INTERESTING,
	EL_EXCITED,
	EL_CUMMING,
	NB_EXCITEMENT_LEVELS
};

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
When it's on purpose it stops being funny and starts being creepy.

Hughlander
May 11, 2005

Suspicious Dish posted:

When it's on purpose it stops being funny and starts being creepy.

Ever think it's an AI state for a virtual sex simulator? Huh?!

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope
Did you know that PHP is not Javascript? Apparently I did not.

JavaScript code:
var master = {
	'child': {
	},
};

console.log (JSON.stringify(master, null, '\t'));

var current_child = master['child'];

console.log ("\n\ncurrent_child\n");
console.log (JSON.stringify (current_child, null, '\t'));

current_child.some_field = 42;

console.log ("\n\ncurrent_child after setting field\n");
console.log (JSON.stringify (current_child, null, '\t'));
console.log ("\n\nmaster after setting field\n");
console.log (JSON.stringify (master, null, '\t'));
outputs
code:
{
	"child": {}
}

current_child
{}

current_child after setting field
{
	"some_field": 42
}

master after setting field
{
	"child": {
		"some_field": 42
	}
}
While on PHP the equivalent (*
PHP code:
$master = array(
	'child' => array(
	),
);

var_export ($master);

$current_child = $master['child'];

echo "\n\ncurrent_child\n";
var_export ($current_child);

$current_child['some_field'] = 42;

echo "\n\ncurrent_child after setting field\n";
var_export ($current_child);
echo "\n\nmaster after setting field\n";
var_export ($master);
produces
code:
array (
  'child' => 
  array (
  ),
)

current_child
array (
)

current_child after setting field
array (
  'some_field' => 42,
)

master after setting field
array (
  'child' => 
  array (
  ),
)
Changing one line in the PHP code makes them behave the same:
PHP code:
$current_child =& $master['child'];
I'm the coding horror for assuming that PHP behaves the same way as not-PHP.
(* e: "PHP equivalent" meaning of course "What I thought would be the PHP equivalent"

Rottbott
Jul 27, 2006
DMC

Hughlander posted:

Ever think it's an AI state for a virtual sex simulator? Huh?!
In fact it's for a commentator speech thing. Written long before I worked here so don't look at me.

Suspicious Dish
Sep 24, 2011

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

Hughlander posted:

Ever think it's an AI state for a virtual sex simulator? Huh?!

Still not funny and instead creepy.

Look Around You
Jan 19, 2009

zergstain posted:

Thanks. I only have 3 semesters left in my degree, and I still had no clue what any of that was about.

That's not really anything that I've ever seen in a required class for an undergrad CS degree, it's just about pure mathematics that you'll probably only get in an actual math course. You'll probably get combinatorics, logic, some set theory and some strategies for forming proofs, but usually not category theory. Or at least that's how it is in my school.

qntm
Jun 17, 2009

Wheany posted:

Did you know that PHP is not Javascript? Apparently I did not.

JavaScript code:
var master = {
	'child': {
	},
};

console.log (JSON.stringify(master, null, '\t'));

var current_child = master['child'];

console.log ("\n\ncurrent_child\n");
console.log (JSON.stringify (current_child, null, '\t'));

current_child.some_field = 42;

console.log ("\n\ncurrent_child after setting field\n");
console.log (JSON.stringify (current_child, null, '\t'));
console.log ("\n\nmaster after setting field\n");
console.log (JSON.stringify (master, null, '\t'));
outputs
code:
{
	"child": {}
}

current_child
{}

current_child after setting field
{
	"some_field": 42
}

master after setting field
{
	"child": {
		"some_field": 42
	}
}
While on PHP the equivalent (*
PHP code:
$master = array(
	'child' => array(
	),
);

var_export ($master);

$current_child = $master['child'];

echo "\n\ncurrent_child\n";
var_export ($current_child);

$current_child['some_field'] = 42;

echo "\n\ncurrent_child after setting field\n";
var_export ($current_child);
echo "\n\nmaster after setting field\n";
var_export ($master);
produces
code:
array (
  'child' => 
  array (
  ),
)

current_child
array (
)

current_child after setting field
array (
  'some_field' => 42,
)

master after setting field
array (
  'child' => 
  array (
  ),
)
Changing one line in the PHP code makes them behave the same:
PHP code:
$current_child =& $master['child'];
I'm the coding horror for assuming that PHP behaves the same way as not-PHP.
(* e: "PHP equivalent" meaning of course "What I thought would be the PHP equivalent"

I had this exact same problem, but going in the opposite direction, from PHP to Perl, which was much worse. It's a completely straightforward and obvious issue... except I'd never heard of pass-by-value or pass-by-reference, and in fact I came from a mathematical background, so it didn't even occur to me that a "function" would not behave like a mathematical function. Figuring out exactly what was happening the first time was pretty :psyduck:

tractor fanatic
Sep 9, 2005

Pillbug

Look Around You posted:

That's not really anything that I've ever seen in a required class for an undergrad CS degree, it's just about pure mathematics that you'll probably only get in an actual math course. You'll probably get combinatorics, logic, some set theory and some strategies for forming proofs, but usually not category theory. Or at least that's how it is in my school.

Groups are in any abstract algebra class though, so you certainly don't need to go as far as category theory to encounter them.

Victor
Jun 18, 2004

That Turkey Story posted:

??? What? How is that misleading? It's exactly what he and I have both been saying repeatedly. We weren't even in disagreement.

That said, if for some reason you did want this [nonsensical] code to work, you could -- just make the offending part dependent on an actor.
It was misleading to show me an example where the short-circuiting behavior looks like it works as expected, because it has a variable in it that I'm guessing gets lifted to a lambda and therefore execution is both deferred and short-circuited. It's misleading because if you don't have a variable there that gets lifted (or whatever the term is), you lose the short-circuitedness. Whether or not the code is short-circuited depends on whether or not you have a variable in there. Who will automatically know this? Non-overloaded-&& C++ doesn't do this. It seems like the makings for a bug that could take days to track down. Operator overloading is suppose to decrease cognitive load and make code easier to read, not the opposite.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Keep in mind That Turkey Story is the guy who made binary literals in C++ using awful preprocessor hacks and thought that this was a shining beacon of good taste.

That Turkey Story
Mar 30, 2003

Suspicious Dish posted:

Keep in mind That Turkey Story is the guy who made binary literals in C++ using awful preprocessor hacks and thought that this was a shining beacon of good taste.

It's not "good taste," it's the only way to do it. Be thankful that Paul Mensonides did that, otherwise you wouldn't have a lot of the high-level libraries that exist in C++.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
Nah, I'm good.

That Turkey Story
Mar 30, 2003

You really hate me, Suspicious Dish!

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
yung turkistori, did anything ever come of the discussion you had on one of the Golang blogs (I think it was Russ Cox's but I could be mistaken) about generic programming a la Stepanov, and the virtues of pervasive value semantics? It was the first time I had seem any of the Go people be open to an idea they (by which I mean mostly Rob Pike) hadn't come up with or weren't familiar with.

That Turkey Story
Mar 30, 2003

Otto Skorzeny posted:

yung turkistori, did anything ever come of the discussion you had on one of the Golang blogs (I think it was Russ Cox's but I could be mistaken) about generic programming a la Stepanov, and the virtues of pervasive value semantics? It was the first time I had seem any of the Go people be open to an idea they (by which I mean mostly Rob Pike) hadn't come up with or weren't familiar with.

Real life took over. I don't know where they are going at this point.

For some further explanation, I diverted my spare time to writing a new proposal to bring back C++0x style concepts into the next C++ standard but eventually just threw my hands up in the air with that and accepted that the "concepts lite" stuff that Bjarne is trying to get in would either make it into C++14 and likely ruin the chances for proper concepts ever getting in, or we'd be in the same predicament that we were in that caused concepts to be cut from C++11. I just got tired of everything and it's a lot of effort and ultimately just rests on the backs of people pushing conflicting ideologies.

That Turkey Story fucked around with this message at 18:28 on May 8, 2013

Victor
Jun 18, 2004

That Turkey Story posted:

It's not "good taste," it's the only way to do it. Be thankful that Paul Mensonides did that, otherwise you wouldn't have a lot of the high-level libraries that exist in C++.
Would you mind posting a few links that explain how this was the only way to do it? I'm just starting to get into template metaprogramming, mostly by examining code my boss is writing. I do have a bit of experience with Haskell and Scheme.

Suspicious Dish
Sep 24, 2011

2020 is the year of linux on the desktop, bro
Fun Shoe
To be clear, I don't hate you, TTS. I'm just not fond of your type of thinking which I find way too often in the C++ world. I'm sure you're a good programmer and a good API designer in those contexts, but I've honestly been burnt badly by libraries like yours which require me to have a deep knowledge in all the corner cases of C++ in order to use them. C++ is one of those languages is so huge that I've worked in it for years and I'm still discovering features that I never knew existed, and you can't expect most C++ programmers to know everything about it.

Python, for instance, forbids overriding its AND and OR operators simply so it could gain consistency with short-circuiting. And it's of course possible to do something absolutely crazy with it as well, even if it's just a toy. (I worked extensively in LEPL for a project where the guy before me chose it, because it allowed him to make a prototype super fast. It has bad error messages when a thing fails, the DSL embedding doesn't really work for Python and if you don't parenthesize correctly, your poo poo fails in mysterious ways. The debugging for it is "call this method to turn on a debug log, and send that log to a mailing list so Andrew can help you decipher it". It's slow, and the solution is some magic memoization which is supposed to work but breaks in edge cases. It's just not a usable solution.)

As I said in the Game Dev thread, my philosophy is on making clearly understandable and debuggable code at the expense of forbidding clever syntax and increasing verbosity.

Relying on people to know that && will short circuit sometimes and not others, depending on context that might genuinely take people 5 minutes to find isn't furthering that goal.

Relying on complex preprocessor metaprogramming tricks that specify Peano arithmetic as a lookup table because "that's the only way to do it" isn't furthering that goal.

That Turkey Story
Mar 30, 2003

Victor posted:

Would you mind posting a few links that explain how this was the only way to do it? I'm just starting to get into template metaprogramming, mostly by examining code my boss is writing. I do have a bit of experience with Haskell and Scheme.

It's mostly due to the fact that prior to C++11 there was no way to create "variadic templates" (templates that can take any number of parameters). A good example of why this is useful is tuple types. For instance, you often want to be able to do:

code:
tuple< int, float, char > foo; // foo has 3 components of the specified types
tuple< char, user_defined_type, /*a bunch more parameters*/ > bar;
If you don't see the immediate need for types like these, I'm not going to go into that here, but it comes up frequently when dealing with generic code.

Anyway, since templates prior to 2011 couldn't be variadic, you had to do the equivalent of the following:

code:
template< class T0 = no_element, class T1 = no_element, /*etc. until some maximum*/ >
class tuple;
The "size" of the tuple is dependent on how many parameters you explicitly pass, which is figured out in code by when the first "no_element" type is specified. The template then has to be specialized accordingly for the different sizes (or a recursive definition can be specified, depending on your requirements). This implies redundancy in code due to a lack of the ability to do this directly in the language at that point in time (the early 2000s).

The remaining way that you deal with redundancy at compile-time is through the preprocessor. Rather than manually maintaining a bunch of specializations and redundant code in C++, you do some metaprogramming with the preprocessor which results in that redundant code behind the scenes. By doing this, you no longer have to maintain and test a whole bunch of instantations -- you just work with the code that generates those instantiations.

...The issue is that the C and C++ preprocessor is extremely limited. You can't loop, you can't recurse, you can only do basic mathematical operations in certain contexts, etc. Basically, all that you can really do is concatenate tokens and use those concatenated tokens to result in the names of other macros that you can then expand. Remarkably, with this tiny bit of functionality, you can actually create containers and high-order algorithms, lambda functions, etc. but it requires the preprocessor code that's written to have redundancy. So in the end there is redundancy somewhere, but now the redundant code is generic and able to be used by any number of libraries that require variadic templates. It also, perhaps most importantly, is a library that is maintained by someone other than the person creating the library that needs variadic templates. It "just works." Now in C++11 we have direct support for variadic templates so you don't need to do the preprocessor stuff for them, although there are still other places where the preprocessor library is useful.

The point is, in the early 2000s the community was faced with a problem: either you just don't have things like tuple types and wait until the next standard (which came a decade later) or you manually maintain monstrous libraries that have considerable redundancy. The existence of the preprocessor library provided a third option -- have concise, maintainable libraries the remove the top-level redundancy by using the preprocessor.

Of course, this leaves you with people like myself, who would gladly use libraries like the tuple library back in the early 2000s because it's a tool that fits our needs, and people like Suspicious Dish (not meant as an insult) that do not want to use these libraries because of all of the hackiness going on behind the scenes -- What happens if something goes wrong? Do I want to have to trudge through preprocessor code? Is using the tool worth the other potential headaches?

Adbot
ADBOT LOVES YOU

Bunny Cuddlin
Dec 12, 2004

operatorequalguy posted:

It does. List classes become highly useful when loading files (either in text mode or binary mode), because it's a reported problem using ftell may not accurately return the size of the file (the details were a bit sketchy, but what size the file is depends on which mode (text or binary) it's in). Apparently relying on this caused users issues so I wanted to bypass that altogether - just load the characters via fgetc, whilst counting how many there are in a list.

This guy is the best.

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