Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Quirks of code

This thread is locked; no one can reply to it. rss feed Print
 1   2 
Quirks of code
Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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
Member #1,881
January 2002
avatar

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

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

torhu
Member #2,727
September 2002
avatar

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
Member #7,536
July 2006
avatar

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
Major Reynaldo
May 2007
avatar

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
Member #1,146
March 2001
avatar

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.

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

bamccaig
Member #7,536
July 2006
avatar

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
Major Reynaldo
May 2007
avatar

Chris Katko
Member #1,881
January 2002
avatar

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.

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

Mark Oates
Member #1,146
March 2001
avatar

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? >:(

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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
Member #7,536
July 2006
avatar

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
Member #1,136
March 2001

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
Member #7,536
July 2006
avatar

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
Member #1,146
March 2001
avatar

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! :'(

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

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
Member #1,136
March 2001

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
Member #7,536
July 2006
avatar

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
Member #12,293
October 2010

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
Member #7,537
July 2006
avatar

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.

---
ItsyRealm, a quirky 2D/3D RPG where you fight, skill, and explore in a medieval world with horrors unimaginable.
they / she

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Chris Katko
Member #1,881
January 2002
avatar

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

-----sig:
“Programs should be written for people to read, and only incidentally for machines to execute.” - Structure and Interpretation of Computer Programs
"Political Correctness is fascism disguised as manners" --George Carlin

bamccaig
Member #7,536
July 2006
avatar

Edgar Reynaldo
Major Reynaldo
May 2007
avatar

Mark Oates
Member #1,146
March 2001
avatar

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

--
Visit CLUBCATT.com for cat shirts, cat mugs, puzzles, art and more <-- coupon code ALLEGRO4LIFE at checkout and get $3 off any order of 3 or more items!

AllegroFlareAllegroFlare DocsAllegroFlare GitHub

 1   2 


Go to: