Closed Reisen closed 5 years ago
This isn’t about interpolation, but rather dynamic vs lexical scoping. It’s no different than if you had
-- Foo
let env = { foo = "Hello", bar = "World" }
in ./Template
-- Template
env.foo ++ env.bar
I fall strongly on the side of disallowing any form of dynamic scoping, and there are plenty of places to read about the consequences of either online, so I won’t rehash the arguments here.
That does makes sense, but I was hoping that the evaluation of interpolated text happened in a different pass I suppose.
So really what it is I'm looking for that we're missing is some form of built-in that allows for doing Text/interpolate context ./Template
, or something along those lines. As it is right now I can do something like:
./Template as Text
To gain a raw string with the template in it, but going from that to something rendered is impossible.
Perhaps some built-in such as above, or a Template
type similar to Text
could help here? Using Dhall for templating is pretty powerful but it currently makes it difficult to work with "raw" template files programatically. For example, if I keep a bunch of template files in templates/
and I want to expose these to users to edit as text, I need to at run-time load these and then programatically wrap the text with a function prelude and ''
to make them evaluable by Dhall.
@Reisen: Is there any reason why you cannot do this in your template file?
\(env : { foo : Text, bar : Text }) ->
''
Foo: ${env.foo}
Bar: ${env.bar}
''
@Gabriel439 It seems @Reisen’s goal is to have users write “plain text” template files where the rules are basically like “wrap vars in ${...}, and the vars available are foo
, bar
, ...”
The example shows a bit of a middle ground, which confuses things a bit … i.e., if you’re going to use something to do
"''\n" ++ templateFile ++ "''\n"
then you might as well do
"λ(env : { ... }) → ''\n" ++ templateFile ++ "''\n"
But I think @Reisen wants to have template files that look exactly like their output, modulo substitution in order to simplify things for the end-user.
@sellout: Yeah, I understand the goal. What I meant to ask is if it would be okay to retain the boilerplate at the top of the file and tell the less technical user to ignore that boilerplate.
Where I'm going with this is that I believe you can automate away a lot of the boilerplate by using an import to specify the type of the environment bound by each template, like this:
\(env : ./Environment) ->
''
…
''
That then provides two benefits:
@Gabriel439 The main problem here is that the files themselves aren't created by me, they're spit out of another tool as markdown files written by other users who understand Markdown but aren't necessarily technical. Of course I can try and push the issue down the line to the users and have them write headers in the Markdown they write, but I want to avoid that. So right now my only real choice is to do a kind of:
fold [ headerFor "SomeInputType", "''", markdownContent, "''" ]
To produce an input I can use for Dhall.
I want to as much as possible avoid inflicting knowledge of Dhall onto the end-user in the templating stage, while pulling the benefits of getting type-checked templating in my consuming code. Dhall is the closest to being able to do this, giving me errors at evaluation time that I just don't get with E-DE, and I lose flexibility with Shakespear.
Of course, I can survive with the run-time folding of a mini-boilerplate prelude in my code, but it just seemed like something that should be possible with a Text/interpolate
of some kind.
Importing the Environment as you mentioned happens to be something I do right now using Typeable
to type the right context at run-time. Basically the end goal is this:
./SomeContextType
, with the type of the environment. I document this for end-users.@Reisen: Is there a tooling limitation why the users can't insert the boilerplate? The reason I ask is that if the Markdown-are tool they use to edit the template fails on the header, then it's likely to also fail on anything more sophisticated than interpolating variables that already have type Text
. However, it sounds like you plan to interpolate things more complex than that if you are interested in Dhall's type-checking feature.
@Gabriel439 I've given this a bit more thought and I think my initial opening of this ticket was mostly just a kneejerk reaction coming from other templating languages. After having pushed this as our project choice, I've found:
Double/show
and various folds to do anything useful. I can't escape this, so what does a header matter.let header = ./header.html
for example.I'm going to go ahead and close this ticket. I still think there may be some value in being able to use something along the lines of Text/interpolate
within Dhall, but it is no longer an issue for our project. Thanks for giving this issue some thought as well! Dhall is absolutely fantastic.
@Reisen: You're welcome! :slightly_smiling_face:
Interpolation seems to happen at the file level. This may be intentional, but seems like a large shortcoming. As an example
If I try and run this with some data:
I receive an error about
env
being unbound. If I bring the template into the same file instead of trying to expand it with./Template
, everything works. I assume this has to do with scope being checked only within a files current expression, and not after being expanded into some other context. Perhaps there's a workaround for this with interpolation however?