Multi-argument version of define-meta
#215
Closed
opened 5 years ago by basus
·
13 comments
Loading…
Reference in New Issue
There is no content yet.
Delete Branch '%!s(<nil>)'
Deleting a branch is permanent. It CANNOT be undone. Continue?
Would it be possible to get a multi-argument version of
define-meta
? I think this would improve readability for blog-like posts, so that instead ofwe could write
I'm not sure if I'd gotten quite the right syntax for this.
So first of all,
◊define-meta[draft]{false}
would be equivalent to(define-meta draft "false")
, so that doesn't quite work. You can use◊define-meta[draft #f]
instead.I initially thought that you can write a simple user-defined macro to expand
define-metas
to a bunch ofdefine-meta
, but that doesn't quite work because Pollen searches fordefine-meta
before macro expansion happens (or at least that's what I understand). Perhaps @mbutterick could extend the expander to do alocal-expand
first? Not sure if it's really worth it though, particularly because it will increase the time to lookup metas.Another solution is to add a support for
define-metas
into Pollen directly, as you originally requested.(Also,
◊foo[...]{}
and◊foo[...]
are equivalent, so you can drop the braces too)@mbutterick I'm just throwing ideas here (which could be terrible). Would it be possible to replace the "search for
define-meta
" with(begin-for-syntax (hash-set! meta ...))
and use(require (for-template ... meta))
on extraction instead? With this way,define-meta
could have some computation and play nice with macros while nothing in phase 0 is computed.We could extend the
define-meta
form to accept input like this:Which seems close to what you want?
The reason metas don’t have computation (and a restricted set of valid values) is to guarantee that they can be extracted quickly. IIRC earlier Pollen users overwhelmingly preferred this approach (on the idea that any value that needs to be computed can live inside the body of the Pollen source and be exported).
@mbutterick I'm not exactly sure what's going on, but extracting data from
define-for-syntax
is faster than Pollen's current manual data extraction.Consider
introduction.html.pm
in yourpollen-tfl
. Add a filetest.rkt
with the following content:Here's the result:
Now, add the following to
introduction.html.pm
And change
test.rkt
to the following:Here's the result:
So with this approach,
define-meta
can be both more expression (can have computation) and faster.I really like this idea!
~Yes, I still think it makes sense to restrict the metas to simple datums.~ edit: @sorawee got me scratchin my chin
@sorawee That’s not quite a fair fight, since
select-from-metas
will cache the metas on disk (if they haven’t been already). Try this test, for instance:Yep, you are right. It's not faster, but have the same performance.
And with caching, the current extraction wins:
In any case, nothing stops you from (ab)using
for-syntax
as you propose. The point ofdefine-meta
is to have an easy-to-explain method of stashing these values. I would have misgivings about using thefor-syntax
layer for this by default.BTW I don’t claim that the
define-meta
form is a miracle of intuitive operation. The analogy todefine
, after all, is a little strained, because these things end up as keys and values in a hash table. If I had to do it again I would lean harder into that, and have operations likemetas-ref
andmetas-set!
instead ofdefine-meta
.I actually don't like that at all because the name
metas-set!
will mislead users in two ways:They might expect that there could be any computation in the value part.
They might expect that this will work:
but it obviously cannot, since metas are extracted syntactically. Note that the current
define-meta
has the same problem too, but its name makes it more likely for users to use it at the top-level.Also note that one sensible grammar that will enforce meta definition at the top-level is:
Not sure if I missed anything, but if we restrict
define-meta
viadefine-for-syntax
to accept only simple datums, then it should for the most part be functionally equivalent to the currentdefine-meta
from users' point of view, no? That is to say, all of these are really just implementation details. From users' perspective, nothing should be significantly changed. One minor difference is that it plays nicer with macro expansion -- that is, it will be now possible to define a macro that expands todefine-meta
.Well, then good thing I did it wrong 😉
I’m using that pattern in
quadwriter
to set top-level attributes. I don’t like it for Pollen metas, however, because it’s not prefixed with the◊
command character, so it’s inconsistent with other Pollen commands. I imagine it would also be harder to pluck them out of the source reliably (e.g., it’s easy to pull out metas because they’re always introduced withdefine-meta
)I don’t think I yet understand the benefit of moving metas into the syntax layer, though let’s start a separate issue about that, if you want to make the case.
In the meantime I can make the change requested by @basus.
Thanks for making the change! I didn't follow all the discussion above, and I'm not familiar enough with Racket to be able to understand the issues with
define-for-syntax
, but this should be helpful for now.One potential use case: you want to have a meta like
◊(define-meta "last-edited" 'today)
, and then'today
gets replaced with the actual current date (or the last-modified date on the file). But I think this can (and should) be easily handled by code outside the meta definition.