New ideas take time to settle. But I may be getting over my squeamishness about having the default interpretation of COMPOSE be to use your current context.
So, this would be the meaning in COMPOSE2 when you pass a pattern with no markings.
>> dir: %some-dir/
>> compose2 '(()) %"((dir))/This Filename (Is Dumb).pdf"
== %"some-dir/This Filename (Is Dumb).pdf"
(Note it didn't do two slashes there. This is because I'm aiming to make COMPOSE treat FILE! composition specially in terms of impementing a kind of "filename calculus". e.g. it would not allow you to compose a FILE! in that spot unless it's a directory with a slash at the end, given that a slash follows it.)
How to get the "use binding of block" behavior simply?
So if no special mark indicates use binding from current environment, and the @ mark means "use the binding on the list I'm giving you", how do you say "use the binding of the template list at the tip"?
It's a little annoying to write manually. ![]()
compose2 (inside template '@()) template
But how annoying is it really? And actually, since it doesn't need a binding, we could use another part-of-speech...
compose2 '$() template
A bit esoteric to say "$ means use binding of template" but you have to quote the binding to get it. That seems to be begging for mistakes, saying $() instead of '$() and getting the "bind here" behavior. I wish there were some kind of semiotic thing we could do like:
compose2 [() <-] template
(I say "I wish" as if we couldn't actually do exactly that. But we can. I'm just a little squeamish about weird dialects like that in fundamental functions. Should I be?)
ANYWAY... the new idea means you can compose unbound code more easily:
>> x: 1000
>> compose '[Hello (x + 20) Unbound World]
== [Hello 1020 Unbound World] ; unbound
Anyway, like I say, it has taken a while for me to be comfortable but with interpolate working so darn well I feel that COMPOSE should be its name, and move on...