...and octals, and decs.  Specifically, I refer you to the functions oct() and hex().

Now, consider:  man perlfunc groups oct() and hex() in 'functions for scalars or strings', and also in 'numeric functions' along with sin(), cos(), tan(), sqrt().  So they can be used both for strings and for numeric values.  Considering how we represent octal and hexadecimal values, this is perfectly reasonable.  But let us consider for a few moments some of the other functions with which they are grouped.

crypt(), for instance, returns a crypted version of plaintext input.  reverse() returns a reversed version of its input.  abs() returns the absolute value of input of undeterminate sign, sin() returns the sine of the value it is called on, etc, etc.  In this vein, if I find a function hex(), I normally expect it to be a function which returns a hexadecimal representation of its input, and oct() to return an octal representation.  Just like any of the functions above, I expect its name to be indicative of what it does.

Perl's hex() and oct(), however, violate this convention.   They return, in fact, the decimal value of their input, which hex() assumes is in hexadecimal representation, and oct() is actually quite happy to accept in hexadecimal or binary as well as octal.  They are, in fact, not so much hex() and oct() functions as they are unhex() and unoct() functions.  They could both be replaced, with more clarity and no loss of generality, by a single dec() function which uses logic similar to the following to determine the nature of its input:

/^(0x)?[0-9A-Fa-f]+$/i Assume hexadecimal /^0b[01]+$/i Assume binary /^[0-7]+$/ Assume octal /^\d+$/ Assume decimal Any other input Error

One could then call dec() to obtain decimal representations of binary, octal and hexadecimal input, freeing up oct() and hex() to return octal and hexadecimal representations of their input respectively (which could be trivially be done using the input logic above in a wrapper around sprintf).

Now, I'm not necessarily advocating making this change, because it would break much existing code.  But would anyone care to speculate as to why it might be that hex() and oct(), unlike almost every other predefined function in every programming language I know, are named not for the nature of the output they return, but for the nature of the input they expect?  This is as counter-intuitive as having a "Start" button on the dash of your car which, when pushed, shuts off the engine (and which is labelled "Start" because it assumes it will only ever be pushed when the engine has already been started).  It is, in short, Bad Design.