Advanced Usage
There are a few other things to consider when working with λtext -
type checking, partial application, and... debugging! *gasp*
To inspect the type of a file or an expression, just use the
-t option during invocation:
$ ltext --type "foo"
Text -> Text
You can read this as "foo takes in Text and returns Text", or "foo is a
function from Text to Text". This is useful if you are getting
type matching errors, or want to get a description of a file. We
can also check the type signature of expressions directly:
$ ltext --type "\x -> x"
a0 -> a0
This is a little technical, but we are creating a polymorphic
function \x -> x, which has a type from for all
a0 to a0 (you may see these cryptic type variables
instead of Text
from time to time). This would happen if, for instance, you made an "apply"-like
template:
%% f x %%
asdf
%% f x %%
If you check the type of apply, you can see it's...
$ ltext --type "apply"
(a0 -> Text) -> a0 -> Text
Meaning that x can be content of any type, so long
as it's the same input as f.
Just like lambda calculus, we can partially apply templates to each other.
Take our apply template from before - that's a good example
to work though. If we apply our foo file from before to
apply, we should get a template from Text -> Text -
the parameter to foo being unified with the x parameter
in apply:
$ ltext --type "apply foo"
Text -> Text
It turns out, we can actually render this partially applied template, but only if
we explicitly supply new delimiters for the result's header
and parameters - without them, λtext refuses:
$ ltext "apply foo"
[Print Error] Can't render a document with arity without explicit --left and --right delimiters
With delimiters, the result is itself a template, ready to be applied later:
$ ltext "apply foo" --left "{{" --right "}}"
{{ x }}
asdf
Woo hoo! I'm a Text File!
{{ x }}
If you toyed around with the apply function from earlier, you
may have seen a daunting error:
$ ltext "\f -> apply f bar"
[Print Error] Can't print textual data while inside an expression:
f [text from "bar"]
...cannot be rendered to a file.
This is intended! This makes sure that the templates we render are actually
renderable.
In layman's terms, a template can only be rendered if all of
its text ends up concatenated at the "top level". Here, after reducing the
expression, the text of bar is still waiting to be passed to
f - a function we don't know yet - so there's no way to write it
out as a file.
We can still check the type of such an expression with --type,
but to render it, we have to apply whatever is still missing first.
Other mistakes are caught before anything is rendered, too. Applying a file to
the wrong kind of argument is a type error, a misspelled file name is an
unbound variable, and a malformed expression - in a file's header or on the
command line - is a parse error that names the file, line and expression at
fault. Add --verbose to see how λtext reads each file.