Horrible Software

code like you give a damn

PHP: Execution Operator

PHP has a shorthand form to execute shell commands and get their result.

<?php
$contents = `ls -a`;
echo $contents;

The manual says:

Use of the backtick operator is identical to shell_exec().

Why is it an operator?

You can even use backticks with interpolation to get bugs for free:

<?php
$files = "";
echo `rm -rf {$files}/*`;

PHP: String Increment

In PHP, what do you expect the following to output?

<?php
$x = "12a";
$x++;
echo $x;

If you guessed “error” or 12a, then you’re still sane, but sadly wrong.

The answer is 12b, due to PHP’s hybrid base-26/base-10 numeric system in strings.

Let’s try another one:

<?php
$x = "12z";
$x++;
echo $x;

Any guesses?

The answer is 13a. z wraps over to a (base 26), and then carries over to change 2 to 3. Of course!

Last one:

<?php
$x = "0d9";
$x++;
$x++;

echo $x;
echo gettype($x);

The answer is 1, and the type is double.

The first increment operator wraps 0d9 into 0e0 by the rules above. This happens to be the scientific notation for 0, unfortunately.

When we increment a string that looks like a number in scientific notation, PHP instead juggles it to be a number, then performs the operation on that!

This isn’t likely to come up in any real code, but that doesn’t stop this from being one of those bizarre features in PHP.

Blu-ray: oh no

To implement a conformant Blu-ray player, you need to implement something called BDJ, or Blu-ray Disc Java. This means that Blu-ray menu systems and special features are implemented as Java ME Xlets.

The specification requires that players provide local storage and network access to the content, alongside a standard UI toolkit and BDJ process management routines. This is intended to be used for optional content, like subtitles in obscure languages and advertising.

This is a physical media format that requires an implementation of Java ME and network access. Let that sink in.

PHP and ==: it gets worse

I found a Security StackExchange comment today that shows how PHP’s == operator can be legitimately dangerous.

It says:

md5('aabg7XSs') == md5('aabC9RqS') (-> true) is a good example why using == is a bad idea.

Another comment then goes on to explain in more detail:

For others’ benefit, this failure case occurs because the first byte of the resultant hash for each is 0e, which is considered to be a “float number format string” by PHP, and type coercion causes them to be compared as numbers.

Are there any cases where "0e04" == "0e08" makes sense to be true?

PHP: fputcsv

PHP has a function to format some input as a comma-separated sequence of values and write it to an open file handle.

It’s called fputcsv.

PHP does not have a function to perform this same operation without writing it to a file handle.

Python: Division

Python 2

5 / 2  # 2
5 // 2 # 2
5 / 2. # 2.5

Python 2 has integer division by default. That’s fine, if not a little bit odd for a dynamic language. Ruby does this too.

Python 3

5 / 2  # 2.5
5 // 2 # 2
5 / 2. # 2.5

Python 3 breaks compatibility with Python 2 by having floating-point division by default. This is also fine. Lua does this too.

Python 2 (again)

from __future__ import division

5 / 2  # 2.5
5 // 2 # 2
5 / 2. # 2.5

Python 2 can change the semantics of the division operator with an import.

Yes, this is for writing code that runs on both Python 2 and 3.

Yes, this is still kind of a scary prospect.

That word you're using: ES7

I don’t think you know what it means.

ES2016 (ES7) has a very well-defined set of features. The edition is shipped! Finalized! Implemented, even!

These features are not part of ES2016:

  • async/await
  • decorators
  • object spread
  • bind operator

The widespread labeling of these features as “ES7 features” is strange.

PHP: == is always wrong

JavaScript has some niche uses for ==, like checking for null or undefined in one check:

undefined == null; // true

It handles plenty of other cases with == just like you’d expect:

5 == true; // false
0 == null; // false
5 == "5 maids milking"; // false

A few other cases are kind of strange due to type juggling, which is why === is almost always better:

0 == false; // true
1 == true; // true! What is this, C?
1 == "1"; // true

PHP, however, takes the idea of type juggling a step further:

<?php

// Same as JS above
0 == false; // true
1 == true; // true
1 == "1"; // true

// ???
0 == null; // true
5 == true; // true
0 == "hello"; // true
5 == "5 jacks jumping"; // true

PHP’s == operator is never the correct choice. There’s no undefined vs nil to work with, and the comparisons that pass are nonsensical!

PHP: Variable Variables

PHP has a unique and (hopefully) seldom-used feature: variable variables.

<?php

$x = "Hello, world!";
$y = "x";

echo $$y; // Hello, world!

I hope never to find a design pattern where this makes sense as such a concise language-level feature. Some other languages have similar features, but all of them are either much more clunky or more explicit as to what’s happening.

Lua’s version only works on global variables, and is more explicit:

x = "Hello, world!"
y = "x"

print(_G[y]) -- Hello, world!

Python has a similar capability with dynamically-generated globals, but it’s still not a good idea:

globals()["x"] = "Hello, world!"
y = "x"

print(x) # Hello, world!
print(globals()[y]) # Hello, world!

Stay safe, stay statically-named.

PHP: Function Chaining

PHP has no notion of function chaining like most other languages, which nukes the idea of having clean function currying.

An idiomatic, but contrived Lua example:

local function add(x)
	return function(y)
		return x + y
	end
end

print(add(2)(2)) // 4

In PHP (5.6), this is a syntax error:

<?php

function add($x) {
	return function($y) use ($x) {
		return $x + $y;
	};
}

echo add(2)(2); // Error: parse error

There’s an RFC open from 2009 that has no activity. Cool.

PHP: Functions are Strings

PHP function references are just strings.

<?php

function abc() {
	echo "Hello, world!";
}

$myFun = "abc";
$myFun(); // "Hello, world!"

Yes, this is definitely a good idea.

JS: Array.prototype.sort

Sorting arrays of numbers in JavaScript is lexicographic:

const numbers = [20, 1, 100];
numbers.sort();

numbers; // [1, 100, 20]

This is surprising for lists of numbers, but makes some sense for lists of mixed types.

Giving JS a spaceship operator would yield a concise and only mildly hideous solution:

numbers.sort((a, b) => a <=> b);

numbers; // [1, 20, 100]