A type-safe string formatting library. It fulfils the need for
string-interpolation or a printf
function, without sacrificing Elm's
runtime guarantees or requiring any language-level changes. It also
composes well, to make building up complex formatters easy.
From your top-level directory - the one with elm-package.json
in - call:
$ elm package install krisajenkins/formatting
See the Elm package for full documentation.
We want to display something like "Hello <name>!"
. It consist of:
- A boilerplate string,
"Hello "
- A "hole" for a
String
- Another boilerplate string,
"!"
To create that, we'll build up a formatter using s
for boilerplate
strings, string
for the hole, and <>
to join them together:
import Formatting exposing (..)
greeting =
s "Hello " <> string <> s "!"
Now we print with that formatter, and its arguments:
print greeting "Kris"
--> "Hello Kris!"
Now let's try to call that formatter with bad arguments:
print greeting 5
-- TYPE MISMATCH ---------------------------------------------
The 2nd argument to function `print` is causing a mismatch.
4| print greeting 5
^
Function `print` is expecting the 2nd argument to be:
String
But it is:
number
Woo - it's like printf
, but it can't blow up at runtime.
If you want to compose CSS3 transforms, it's a bit of a pain of string interpolation. For example, to translate and rotate a div, we'd need something like:
translate(50px, 100px) rotate3d(0, 0, 1, 60deg)
Filling in all those holes gets messy:
"translate(" ++ toString x ++ "px, " ++ toString y ++ "px) rotate3d(0, 0, 1, " ++ toString r "deg)"
This is exactly the mess that makes me want a printf
function. With
Formatting
we can break it down into more readable,
easily-composable pieces:
transform =
let
px =
int <> s "px"
deg =
float <> s "deg"
translate =
s "translate(" <> px <> s ", " <> px <> s ")"
rotate =
s "rotate3d(0, 0, 1, " <> deg <> ")"
in
translate <> s " " <> rotate
Actually, this is better than printf
- you can just compose small
pieces together freely. Elm will keep track of which arguments you
need in which order, and infer the final type of transform
automatically.
A. I don't believe you can, in a type-safe way, without core language changes. You'd need to parse the formatting string at compile time to generate a function with the right type. That either needs built-in language support, or a macro system.
And even when you've done all that work - or waited for the Elm team to do it - you end up with something that's hard to compose and hard to extend.
This library gives you the same utility as printf
, but it doesn't
need any changes to the language, it's freely composable, and it's
entirely extensible - you can make your own formatters on-the-fly.
make
...will run the whole build and test suite.
In active development. The hard part is done, but we need more utility functions like string width and alignment helpers.
API subject to change.
This package is a port of Chris Done's Formatting library for Haskell. When I saw Evan & Noah's url-parser library, I realised it could be ported across.
Thanks to Glen Mailer for suggesting the function
name premap
.
Thanks to Folkert de Vries for splitting the tests out of the main published package.
Thanks to Ian Mackenzie for roundTo
bugfixes.
Copyright © 2016 Kris Jenkins
Distributed under the MIT license.