JavaScript Nonsense (Part 2 of probably many)

Bit-wise Operators

Hey you remember how in part 1 of me complaining about JavaScript I was quite annoyed with the language’s disregard for different types of number? Hey guess what I’m still quite annoyed. Because reasons, JS includes operators for doing some of my favorite nonsense, bit-twiddling-hackery. I love me some good bit-twiddlin’, but I ended up getting caught in a weird way by this implementation of my favorite operators.

let num = 1 << 4;

Cool this is all fine. num is a number and its 16 now no problems here. Everything in JavaScript is a 64 bit floating point value, so bitwise operators don’t even really make a whole lot of sense. To counter this, all bitwise operations in JS are done after converting the values to 32 bit signed integers. After the work is done, it gets converted back. Some people probably are upset about the data loss here but eh we’re in web land who cares. (Probably people writing networking code, who are honestly probably the only ones trying to bitshift in JavaScript)

void(0)

This isn’t something you’d reasonably expect to encounter in code written by a human, but for some reason the language supports it anyway. In most languages void means “nothing”. You just put it as your return type, your function doesn’t return any value. In C, if your function accepts nothing you should make your function accept void. In JavaScript those things are still true, but void is also a function. You can call it at runtime. It accepts exactly one argument, and returns undefined. Any other number of arguments, unlike any other function in JavaScript, will cause a failure to compile. This is actually in almost any large JS library because void(0) is less characters than undefined and therefore you have to download slightly fewer bytes. This is one of the operations often completed by minifying tools.

“Optional” Semicolons

Look I know programmers are lazy and that’s part of the reason we’re programmers. I get it. Apparently JavaScript gets it too, since we don’t even have to bother typing those pesky semicolons like those ‘oppressive’ languages with all their boring ‘rules’ that limit my ‘creativity’ do. JavaScript lets you be a free spirit unbound from the tyranny of the semicolon.

However.

function foo()
{
  return
  {
    a: 'bar',
    b: 'baz',
    c: 'bam'
  };
}

This is perfectly fine code (according to JavaScript). It will run just fine and when you call foo it will return… nothing. This function returns nothing. It return type, if JS had such an opressive and freedom limiting concept, would be that function that accepts a single argument from earlier. JavaScript is detecting that return on its own is a valid statement, so its helping you out and adding a nice little semicolon in there to help you out. Thanks JavaScript, what I wanted was to return then not reach the code that creates an anonymous object. Perfect. If you are used to programming with a style guide that enforces braces on their own lines (like I was) things like this will bite you.

I guess this is the price of freedom?

Underappreciated C++ Features

C++ is a great language. It has some problems for sure, but it also has some really neat features to help you write some fast code that doesn’t look completely hideous. Here are some of my favorite features that I don’t think get enough love.

Unnamed Types

These are a super nice way to add organization to the members of your class without needing to define a whole bunch of named types cluttering up your IDEs autocomplete. If a type never needs to be passed to a function and is really just there to group parameters together, unnamed type members are great.

 class Sprite 
    {
        ...
        private:
            struct 
            {
                unsigned uint8_t* bytes;
                uint32_t width, height;
            } imageInfo;
    }; 

I don’t really recommend using it for public interface things, but for keeping things internally arranged in a super tidy way.

Kind of an tangentially-related side note please use the explicitly sized integer types from <cstdint> if your code has any chance of ever being compiled for another platform. It will make everyone’s lives so much easier.

The C++ standard states that you can’t define a new type as a return type, but Microsoft’s compiler (MSVC) doesn’t really seem to care about that. The following code will not compile using any other compiler I tried, but using MSVC it compiles and works.

struct {
  bool success;
  int rounded;
  double precise;
} fetchNumber() {
  return { true, 42, 42.0 };
}

int main(char** argv, int argc) {
  auto result = fetchNumber();
  if(result.success) {
    if(result.rounded > 40) {
      std::cout << result.precise << std::endl;
    }
  }
  return 0;
} 

I realize talking about a really cool compiler specific quirk right after preaching about cross platform code is kinda odd, but this is probably the coolest noncompliance I’ve ever encountered.

Variadic Templates + Argument Unrolling

Ok so templates are cool. They’re probably the most powerful feature of C++ with the nonsense they let you figure out at compile time. I’ve also written some absolute garbage code with them, but that’s not what we’re here for.

Say hypothetically you’ve got a templated class that represents an array of constant size. You want to construct a new instance of that class that uses certain indices from that array to make a new array. Graphics programmers probably know this as swizzling but it could be used for other things. My implementation just happens to be called swizzle because I couldn’t think of a better name. Anyway, if you want that behavior, you can combine a few really neat C++ template tricky to make it happen.

template<unsigned int...I, unsigned int N = sizeof...(I)>
Vector<T, N> Vector::swizzle()
{
    return { {data[I]...} };
} 

Cool. You have the code now if you just want to copy paste that out, but if you want to understand it read on. There’s a lot to dissect, lets unpack this one neat trick at a time.

The first argument of the template (that represents every argument the user will actually pass) are unsigned integers that are the indices of the vector you want to use to build the new vector. The second is hidden from the caller calculated from the first, using the unrolling sizeof... operator to count the variadic arguments.

The return type is pretty easy, its going to be a vector of objects of the same type but the number of them is taken from that count parameter that the template calculated.

Ok the return statement, I know this looks weird but its not too bad (just kidding its pretty gross). This class has an initializer list constructor so the outer braces are to invoke that. The inner braces are forming an unrolled indexing into this Vector’s data. It helps me to think of what this is doing as building the comma-separated initializer list of values you’d normally feed to the constructor, where those values are accessed by unrolling the list of variadic arguments that I represents.

This may seem weirdly niche, but I have genuinely used this trick in a professional code base to really clean up the binding of function arguments and member functions.

JavaScript Nonsense (Part 1 of probably many)

Honestly the main reason I started this blog was to have a new outlet for the things that my college game project team called “You Wanna See Some… Stuff”. Without working next to those nerds every day I need a new outlet to either vent frustration or share excitement about the absolutely bizarre ‘features’ I encounter in programming languages and sometimes libraries.

To that end, I present to you…

JavaScript’s Array and the Indexing Operator

Ok so, I don’t want to dunk on JavaScript too much, even though it is absolutely hot garbage. It does somehow drive most of the internet (including this blog), so I’ll be gentle. It’s just… sometimes… this language. This particular ‘feature’ cost me almost a whole day of work to deal with.

Ok so.

const array = [0, 1, 2];

for (const i in array) 
    console.log('Content is ' + array[i]);

Pretty good so far? This all works perfectly and performs exactly as you’d expect. Modern JavaScript does have a cool way of iterating through arrays that tidies it up a little. (For the uninitiated, in defiance of what makes sense for…in loops in JS actually move through all the valid indices on an object. More on that later)

for (const value of array) 
    console.log('Content is ' +  value);

This works the exact same, as you’d expect. I just thought it was worth mentioning. The reason for this will become clear shortly.

So for you poor sweet uncorrupted souls people that haven’t worked in JavaScript: everything is a table, and the generally accepted lie is that all numbers are just numbers (none of that float/integer segregation here). This is the point at which I begin to become annoyed.

So everything is a table. You can access the things in the table just like a table in any other language.

const thing = {};
thing["key"] = "value";

Cool that makes sense you can just use it the same as a table in any other language thats neat. And just like in any other language, its the same operator as an array. No big deal. Except this is JavaScript and we don’t care what types are. So what happens if we do this.

thing[0.23] = 1.0;

Answer: not much different. Now there is another key on the object so if you ask for 0.23, you get 1. Neat.

Sidenote: Because objects in JavaScript are just tables, we can now ask for thing.key and get "value" out. That’s kinda weird but ok just a different syntax that you can use if your key is a string that is legal as a variable name.

So going back to the array from earlier. What happens if we subscript a string onto that array? Its an array right? So indexing with a string should fail? Since everything is at a numeric index? Oh sweet summer child you’re thinking like we’re dealing with a sane language. Everything here is a table. Everything.

So lets try it. We’ll also keep using the neat little for…of syntax because its tidy.

const array = [0, 1, 2];

array["dumb string here"] = "a string";

for (const value of array) 
    console.log(value);

That looks weird but given what I know so far I’d expect to see 0, 1, 2, “a string”, right?. Heres the output:

0
1
2

No string? It almost makes sense. The array is indeed an array. But its also a table. Internally there is a dynamically resizeable array of values, and then also a table. For…of only iterates through the array part, and ignores the table. If we got back to the for…in loop, the output is as we’d expect:

0
1
2
a string

Ok but this raises a question. JavaScript says there is only one type of number, where other languages differentiate between integers and floating point values. So if using indexes 0, 1, 2, etc put things in the array space, what about the other numbers that the standard claims are the same type?

const array = [0, 1, 2];

array[0.5] = 0.5;
array[1.5] = 1.5; 

for (const value of array) 
    console.log('of: ' + value);

 for (const i in array) 
    console.log('in: ' + array[i]); 

OUTPUT:

of: 0
of: 1
of: 2

in: 0
in: 1
in: 2
in: 0.5
in: 1.5

So clearly all numbers aren’t being added to the array part of the object, since they didn’t show up when we iterated through using of. That means that although these numbers are pretending to be the same type, that is a lie. JavaScript standards can say all numbers must only be 64 bit floating point values as much as it wants, but when two values that are supposed to be the same type are fed into the same operator, I would expect consistent behavior, and I don’t think this counts.

Ok I get it you don’t think this is a huge deal, but hear me out.

Lets construct a hypothetical situation where I’m building an API for others to use to store constructed images built in a frontend on my backend. These images have a concept of layering so that people can separate their background/foreground objects or whatever. So you’d expect layer 1 to be in front of layer 0 cool, cool. Easy we just put the content in a 2-dimensional jagged array with the first array being indexed by the layer number and the second being the content for that layer. Problem is we’re in JavaScript land and numbers are just like, numbers man why do we have to segregate the integers from the floating point. The language has no problem with someone asking for their content to be on layer 0.5. This is a public-facing API so I can’t just tell my front end people to please not.

So what? Just iterate using for…in why is this a big deal? But look at what for…in output up there. That’s not in order. If someone really did put this picture of a tree on layer 0.5 they probably expect it to be between layers 0 and 1, but according to that iteration its going to be drawn on top of all the integer layers. That’s not right. Now we have to sort this nonsense and slow everything down. Hope you didn’t need a stable sort for that because there is no requirement for a stable sort in the JavaScript standard. Anyway that was a purely hypothetical scenario that hypothetically wasted a lot of my time to sort out a problem that in typed languages wouldn’t exist.