Quirks of code
Edgar Reynaldo

I've spent the last 6 hours trying to figure out why my freaking javascript wasn't working. It turns out any DOM elements it refers to must be declared in the HTML /BEFORE/ you reference them. This means if your script is in your <head> section, it WON"T SEE ANY OF YOUR DOM objects. AAAAHRHHRHRHGHGGGGGG. And on top of that I can't remember that javascript functions start with a lowercase letter. $%#@^@#$!.

Anyone else have any quirks of code to share? Can be any language you want.

As an aside, perl makes my eyes bleed.

Chris Katko

D has some oldschool stupidity.

Array.remove?

Doesn't remove elements.

That's right.

It returns an modified array with the element remove. So you're supposed to do:

my_array = my_array.remove(15); //remove index 15.

WTF.

And while this one isn't a big deal, it's kind of a headscratcher. The d module for stdio like printf, etc? Is... stdio. But all standard modules are in... std. So you import:

import std.algorithm;
import std.math;
import std.stdio; //not std.io

It's just... I guess it's one of those "tabs vs spaces" doesn't-really-matter kind of things. It just feels strange. But I guess it'd feel strange if it was std.io.

And it's NOT stdio because "it has C functions" like #include<cmath>. It's full of all your normal standard output functions like writefln (write formatted line).

torhu

And it's NOT stdio because "it has C functions" like #include<cmath>.

It's stdio because it's based on C's stdio :-*

bamccaig

I've spent the last 6 hours trying to figure out why my freaking javascript wasn't working. It turns out any DOM elements it refers to must be declared in the HTML BEFORE you reference them. This means if your script is in your <head> section, it WON"T SEE ANY OF YOUR DOM objects. AAAAHRHHRHRHGHGGGGGG.

I highly recommend you use a library to manipulate the DOM. jQuery is a very popular favorite. In jQuery, you typically always wrap DOM code in a "ready" event handler, which is a magical "load" event that works properly. Your code will execute as soon as the document has fully loaded without any surprises. A shortcut for that is to pass a function directly to the jQuery constructor/function:

jQuery(function() {
    // Everything has loaded. Go for it.
});

Otherwise, the constructor function accepts a "selector" (i.e., query) for elements, among various other things, including raw elements. So you can easily find elements by complex patterns.

The resulting object has methods to access and manipulate the elements in a cross-platform way so you never trip over idiosyncrasies from certain browsers.

jQuery("form fieldset.address input.city .error").show();

As an aside, browsers typically will stop reading the document while they process JavaScript code synchronously with the rendering pipeline so it's generally advisable to define your scripts at the bottom of the <body> just before the closing tag. This way the rest of the document is rendered and the user can immediately start reading the page and figure out what they're doing while the supporting JavaScript executes.

Long running JavaScript programs in the <head> can cause the screen to remain white for a long period of time making the loading time feel worse than it has to.

Quote:

And on top of that I can't remember that javascript functions start with a lowercase letter. $%#@^@#$!.

Which is odd because C and C++ functions also start with lowercase letters. :-X

my_array = my_array.remove(15); //remove index 15.

That's basically functional programming. It has its merits. It's not as fast having to create a copy of array obviously, but there's also few surprises from passing an array into something and having it suddenly changed. Not sure if D solves that in a different way though.

Edgar Reynaldo
bamccaig said:

And on top of that I can't remember that javascript functions start with a lowercase letter. $%#@^@#$!.

Which is odd because C and C++ functions also start with lowercase letters. :-X

I don't follow that convention though. All enums and global constants are UPPERCASE, variables are lowercase, and classes and functions are capitalized. No h_ungarian garbage. If you can't figure out which namespace a symbol is in you're hopeless.

Mark Oates

Ruby's srand, unlike C's srand is based on a Mersenne Twister algorithm. This means that the random number generation should be consistent across all platforms, while in C, it is not.

bamccaig

I don't follow that convention though.

I've noticed. >:( There are many styles though, and many of them are applied to many popular languages, so while I have my personal preferences I'm used to what I'm used to and tolerate what I must. I understand. It's very unnerving when you find yourself in foreign waters. It gets easier when you accept it and learn to embrace it within the contexts that you must.

Quote:

...and classes and functions are capitalized.

I've always done classes as UpperCamelCase and functions as either either lower_underscores or lowerCamelCase. Except in C# and VB.NET typically you use UpperCamelCase for methods too. I embrace that in C# and VB.NET and will frown on anybody that doesn't, but I try to avoid that when outside of .NET. :)

Edgar Reynaldo

@Oates
C++11 has std::mt19937. I use it in skyline and eagle.

Chris Katko

Ruby's srand, unlike C's srand is based on a Mersenne Twister algorithm. This means that the random number generation should be consistent across all platforms, while in C, it is not.

While that's cool, it's also pretty understandable. We care more about cross-platform in user-space these days. I'm sure C had plenty bigger problems to getting adopted than worrying about cross-platform rand--especially when tons of C programs had... assembly code in them--the antithesis of portability. And once it's "standardized" they can't go back and update it without breaking compatibility.

D has a naming convention. I'm not sure I like or hate it. Usually I just use lower_case_underscore for everything. For unit type objects, I just name them a pos2, float, etc. But for objects that are "systems" and not really vectors or floats, I append _t on to them.

So it's just:

auto object = new object_t;

But the popular D linter complains about my lack-of-name-convention on every line which gets annoying. So I'm half tempted to "try" using their naming convention to see if I like it better.

I HAVE noticed that underscores are kind of annoying for fast code writing--especially on my laptop keyboard. While you still have to press shift for myVariableThingy, you don't have to stretch your finger across to the underscore. I've definitely noticed my finger wearing out after long coding sessions using underscores. But I can't remember off-the-top-of-my-head if it's just my netbook keyboard, or also normal full-size keyboards.

Mark Oates

This really bugs the crap out of me:

#SelectExpand
1class vec2i 2{ 3public: 4 int x, y; 5 vec2i(int x=0, int y=0) : x(x), y(y) {} 6}; 7 8int my_function() 9{ 10 return 1234; 11} 12 13int main(int, char**) 14{ 15 vec2i val = my_function(); // no compile error 16 std::cout << val.x << "," << val.y << std::endl; 17 return 0; 18}

Outputs:

1234, 0

How is this not somehow prevented with strong typing? >:(

Edgar Reynaldo

The difference lies in which function is being called when you assign an integer to a newly constructed object. It's not doing what you think it's doing. ;) It's calling the constructor, not the assignment operator.

Saying OBJ o = T; really calls OBJ(T t).

That's why this code calls the copy constructor, and not the assignment operator :

OBJ o1;
OBJ o2 = o1;

The compiler has tricked you. It's really performing construction, not assignment.

#SelectExpand
1 2#include <cstdio> 3 4class OBJ { 5public : 6 int ox,oy; 7 OBJ(int x=0 , int y = 0) : ox(x) , oy(y) { 8 printf("OBJ default constructor called with args X,Y = %d,%d\n" , x , y); 9 } 10}; 11 12int main() { 13 14 OBJ o = 5; 15 return 0; 16}

Outputs "OBJ default constructor called with args X,Y = 5,0".

bamccaig

It stands to reason that it must be calling the constructor, but I think it's fair to complain that this is never what the programmer would mean. I always thought that to call the constructor in C++ without doing a copy you had to invoke it with parens (did this change or would the OP's syntax also work with a standard from the 80s?):

OBJ o(my_function());

Nobody would be surprised by that. It makes sense. It's explicit. Now I could see if the constructor was just OBJ(int) then I could see it being implicit here, but to implicitly fill in a default argument from an assignment where only one possible argument is specified feels wrong. I can't imagine a programmer ever intending to do that. If you intend to do that, you can invoke the constructor as above.

Is this implicitly calling a constructor, instantiating an OBJ, and then invoking a copy-constructor? Or is it directly calling the constructor on the variable instance?

Peter Hull

You can mark the constructor with 'explicit' to stop the compiler doing that, which is a good idea here because converting an int to a vector doesn't make sense. In other cases (e.g. double -> complex) it is helpful to allow the compiler to produce these "converting constructors"

explicit vec2i(int x=0, int y=0) ...

[edit] fixed terminology

bamccaig

Wouldn't implicit make better sense though? Should you really have to tell the compiler all the times you don't want it to guess wrong instead of all the times you do? How often do you really want these kinds of implicit conversions? I've seen it very rarely. I mean, never. The double -> complex may be an interesting area where it makes sense (AKA numbers), but a vast majority of programming types are not numbers.

Mark Oates

Thanks, Peter Hull! :)

explicit might be my newest favorite C++ reserved word! For the longest time it's been override, but I seem to be needing a new high! :'(

Edgar Reynaldo
bamccaig said:

but to implicitly fill in a default argument from an assignment where only one possible argument is specified feels wrong.

Yes, but it's the default constructor, with default arguments. Each unspecified argument is generated from the initializer, so the second int is just filled in to be zero.

If assignment to a new object wasn't construction, how would you know which constructor to call? Just always call the default constructor and then perform assignment?

Peter Hull
bamccaig said:

Wouldn't implicit make better sense though?

Agreed. I think those sort of things means you're less likely to understand a piece of code in isolation.

I've got one quirk to share but it's a bit obscure - Posix threads. Most operations that perform some action on a synchronization object return zero for success or an error code. Consistency is great! ...Apart from the semaphore functions which return zero for success, but if there's an error, they return -1 and put the error code in errno. ??? No reason for this as far as I can see.

bamccaig

If assignment to a new object wasn't construction, how would you know which constructor to call? Just always call the default constructor and then perform assignment?

Like I said, C++ has a syntax for invoking a non-default constructor explicitly: type name(args);

As far as my eyes see it, type name = expression; is potentially construction and an (r-value?) copy.

vec2i val = my_function();

What should ideally happen in this case? A compiler error. Full stop. What this says doesn't make sense. If you showed it to 1000 programmers that didn't know C++ intimately, most would say either error or I don't know. Hell, I imagine a non-negligible number of professional C++ programmers would even get this wrong.

Instead of trying to think what could this mean, the designers should have thought why should this mean anything at all? It's gibberish.

I watched a video suggested here a few weeks ago from a C++ guru whose job it is to go around and train professional C++ programmers about the gotchas of C++ semantics. It was at a D conference and basically saying design your language so I'm out of a job. C++ has a lot of stupid semantics so it's hard to keep them all straight. The only reasonable way is probably to just learn to avoid all of the surprising semantics that you can, and memorize the things you can't.

This is 2018. C++ has its place in the world, but nobody that truly knows it would defend it and say that it's perfect. It has a lot of design mistakes that cannot be undone. Dare I say it, perhaps more than most languages. Probably none are perfect. C++ is probably so far from perfect that it cannot even see it anymore. :) But it's still a fun challenge.

Polybios

I wonder whether there are cases where you want to call

vec2i v(6);

to initialize to (6, 0)?
How is this generally preferable to initializing to (0, 6)? ???

I'd written a 2-value c'tor and a default-ctor, I think, but I do not know in what context this is used.

Erin Maus

I follow GLSL so Vector(n) would do { n, n, n, n } (i.e., n for each component depending on the dimension), Matrix(n) would create an identity matrix if n == 1 otherwise a scaling matrix for values not equal to 1, and so on.

In essence, the only reasonable constructors for a Vector4 (for example) would be: no parameter (all components zero), single parameter n (all components equal n), three parameters (components equal respective parameters and w equals 0, though an argument could be made for w to equal 1 depending on your use case I guess), and four components (no explanation needed).

But at the same time, it's more code to write to handle the cases (4 constructors vs 1). So whatever floats your boat!

As an aside my Vector3 class for ItsyScape is a single constructor that tries to follow the above rules but doesn't always:

function Vector:new(x, y, z)
  self.x = x or 0
  self.y = y or x or 0
  self.z = z or x or 0
end

So technically you could do Vector(1, 2) and it would give you { 1, 2, 1 } instead of the more logical { 1, 2, 0 }. Oh well.

Edgar Reynaldo

Okay, so take away the default constructor and what is it supposed to do with an assignment then?

Chris Katko
bamccaig said:

I watched a video suggested here a few weeks ago from a C++ guru whose job it is to go around and train professional C++ programmers about the gotchas of C++ semantics. It was at a D conference and basically saying design your language so I'm out of a job. C++ has a lot of stupid semantics so it's hard to keep them all straight. The only reasonable way is probably to just learn to avoid all of the surprising semantics that you can, and memorize the things you can't.

You're speaking of mother effin' LEGEND, Scott Meyers:

{"name":"Sdm-big.jpg","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/acdcf7781d4400dc41e893f5289a4e89.jpg","w":339,"h":450,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/a\/c\/acdcf7781d4400dc41e893f5289a4e89"}Sdm-big.jpg

A man so powerful, he rocks the He-Man haircut 40 years after it was cool.

[edit] Omg, he knows:

http://scottmeyers.blogspot.com/2014/09/cppcon-hair-poll.html

bamccaig

Yes, that looks like him (10 years ago). <3

Edgar Reynaldo

Let's just put it this way, he's the only one who had a set of g++ warnings named after him.

Mark Oates

I remember him saying something in that talk... something akin to his job isn't to write code, he doesn't even do that, he just complains about coding and tells people what to do. ;D

bamccaig

{"name":"latest","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/2\/d2775cd8f40e0d5d2fd504b54a2f8c28.jpg","w":620,"h":577,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/2\/d2775cd8f40e0d5d2fd504b54a2f8c28"}latest

Looks just like He-man, am I right? :P

Chris Katko

I remember him saying something in that talk... something akin to his job isn't to write code, he doesn't even do that, he just complains about coding and tells people what to do. ;D

His job is to tell people how to re-architect their API to gain 10/100/1000x performance. For example, he took a multi-million line project (worth millions of $$$) and converted it from virtual calls, to templated calls, and gained that order-of-magnitude benefit for the client.

So yeah, he's basically saying, if languages didn't suck, and programmers did their jobs, he wouldn't have a job.

Peter Hull

I learned something new yesterday! I was familiar with C++ operator overloading (operator+ and whatnot) but since C++11 there's also been operator "" which (not obvious IMO) is for user defined literals. :o

Chris Katko

I like that for decades people tell us stuff like that isn't needed / just complicates the language.

... and then they add it.

Programming language design, in a nutshell. ::) As if all their supposedly good arguments for why it's a terrible idea, magically got satiated by something, so it's okay. When in reality, they were just sticks in the mud who were against change before.

And all the "solutions" people come up with because the LANGUAGE doesn't support it, looks ugly as sin. Like pretty much any units of measure library bolted on-top of a language that doesn't naturally support them.

Polybios

There was this other thread about "exotic" programming languages. I've just learned that the backend/server for the Wire messenger is partly written in Haskell. Quite impressive.

bamccaig

In all fairness, "foo"_bar does in fact look terrible. I cannot imagine the ways this will be abused. I would have expected overloading `""` to be a to-string mechanism, but that's coming from my Perl experience since it does just that. I'll withhold judgment until I've given it a try and we've had some time to witness the abuses. As a rule, I encourage any new features they can throw at us though. If it's abuse in time we will learn to avoid it. As long as it doesn't break existing code (without some kind of declaration) we're good IMO.

Mark Oates

I learned something new yesterday! I was familiar with C++ operator overloading (operator+ and whatnot) but since C++11 there's also been operator "" which (not obvious IMO) is for user defined literals [en.cppreference.com]. :o

Looks like fun to me! Probably not necessary and a bit superfluous.

Look forward to using it and confusing the newbs. 8-)

Thread #617411. Printed from Allegro.cc