I have a proposal for string literals; I’ve found myself needing to embed some binary data into the code occasionally (e.g. a cryptographic key into the config), plus in want of a decent way to serialize binaries that’s relatively human-readable (or at least: copyable into other tools).
The “usual” way to do this is to make it <<249,151,173,246,...>> — which isn’t ideal, as binary data is commonly represented via hex or base64, decimal is more or less an Erlang-specific rarity; or a string that’s then decoded at runtime (I guess on launch), e.g. "f997adf6" (hex) or "+Zet9g==" (base64).
There is sort-of a way, in doing <<"\xf9\x97...">>, but that’s awkward for pasting from other tools, plus it adds syntactic noise, making it harder to read.
Thus, I have two proposals, ostensibly ortogonal; the former of which I’m more certain about:
1. Add a ~x"..." sigil for hex strings
I’d imagine this would mostly be used for binaries, something like ~bx, unless we make ~x itself give us a binary. My examples will assume the latter (~x is binary), for brevity.
Above example would then become ~x"f997adf6", which would be exactly equivalent to <<"\xf9\x97\xad\xf6">> or <<249,151,173,246>>.
I think it makes sense for such strings to ignore whitespace (including newlines), but enforce an even number of hex digits. And for it to be case-insensitive.
So the following examples are valid (and equivalent):
~x"f997adf6"
~x"F997ADF6"
~x"f 99 7aD F6"
~x"""
F99 7
adf
6
"""
… and the following are invalid: (N.B.: I could see an argument for allowing ‘-’ in these for the sake of UUIDs, but I think it’s better off if it’s not allowed; YMMV).
~x"f99" % ERROR: un-even number of hex digits
~x"f997-ad" % ERROR: stray '-' in hex string/binary literal
~x"\xf9" % same as above, but with a stray '\' (there is no escaping of these strings)
A big part of the motivation for me is being able to serialize (non-text) binaries in a way that’s relatively human-readable and also a valid Erlang term. E.g. UUIDs as ~x"26b85f7a ea9c 4a2f a495 1f79c6e92ff5" (basically the ISO format with spaces instead of dashes); or hashed passwords as (say) {argon2,<...params...>,~x"<...salt...>",~x"<...hash...>"}.
2. Add a ~b64 sigil for base64 data
Same idea as above, except base64. I think it makes even more sense to support whitespace/newlines here (think pasting a .pem’s multi-line certificate contents or similar, directly).
I’d allow, but not require, padding characters (=); though if present, I’d enforce the correct number of them (so: either no padding or the correct padding for the length).
In terms of dialect, it’d be pretty easy to support both the “classic” Base64 as well as the URL variant (via aliasing of the symbols for digits 62 & 63), though I’d disallow “mixing” of them in the same string in this case. If we’re only doing one, I think the classic one makes more sense.
A few examples (the valid ones are equivalent):
~b64"L6/va06PT1Srjg1lu+nXWg==" % OK, have padding, and it's valid
~b64"L6/va06PT1Srjg1lu+nXWg" % OK, no padding
~b64"L6_va06PT1Srjg1lu-nXWg==" % OK, URL dialect, have padding
~b64"L6_va06PT1Srjg1lu-nXWg" % OK, URL dialect, no padding
~b64"""
L6/v a06P
T1Sr jg1l
u+nX Wg
""" % OK, multi-line + whitesppace
~b64"L6/va06PT1Srjg1lu+nXWg=" % ERROR, invalid padding
~b64"L6/va06PT1Srjg1lu-nXWg" % ERROR, mixing non-URL and URL dialects
~b64"L6/?a06PT1Srjg1lu-nXWg" % ERROR, stray '?' in base64 value
Admittedly, I need this one less, but I figured I’d bring it up since it’s closely related to the hex proposal, and it makes a lot of sense for some use-cases.