-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement quasi unquotes #30
Comments
After some deliberation on Conceptually, the typing is a run-time check. With #33 we can probably do better than that, and detect impossible things statically. The important thing is that the parser is no longer confused. |
A quasi can be full of holes -- so-called "unquotes". An unquote contains an expression that needs to evaluate to a Qtree, which then gets spliced directly into the code in the quasi. It's quite similar to qq string interpolation, but with code instead of a string. The unquote is a way of "escaping" out of the literal code and into the land of Qtrees. As an example, these all mean the same thing: quasi { say("Mr Bond!") } quasi { say({{{Q::Literal::Str("Mr Bond!")}}}) } my s = Q::Literal::Str("Mr Bond!"); quasi { say({{{s}}}) } my t = quasi { "Mr Bond!" }; quasi { say({{{t}}} } (The last one doesn't work yet, I think. It should, though.) The quasis are replaced by actual Qtrees at *evaluation*, when the runtime "hits" the quasi by evaluating an expression in which it is a part. At that point, we run down the Qtree structure of the quasi block, cloning everything we find (except trivial leaf nodes, which are safe to re-use), and replacing every unquote we find with its expression (hopefully a Qtree). That's what the new .interpolate method is for. Addresses #30. Still a lot to do.
A quasi can be full of holes -- so-called "unquotes". An unquote contains an expression that needs to evaluate to a Qtree, which then gets spliced directly into the code in the quasi. It's quite similar to qq string interpolation, but with code instead of a string. The unquote is a way of "escaping" out of the literal code and into the land of Qtrees. As an example, these all mean the same thing: quasi { say("Mr Bond!") } quasi { say({{{Q::Literal::Str("Mr Bond!")}}}) } my s = Q::Literal::Str("Mr Bond!"); quasi { say({{{s}}}) } my t = quasi { "Mr Bond!" }; quasi { say({{{t}}} } (The last one doesn't work yet, I think. It should, though.) The quasis are replaced by actual Qtrees at *evaluation*, when the runtime "hits" the quasi by evaluating an expression in which it is a part. At that point, we run down the Qtree structure of the quasi block, cloning everything we find (except trivial leaf nodes, which are safe to re-use), and replacing every unquote we find with its expression (hopefully a Qtree). That's what the new .interpolate method is for. Addresses masak#30. Still a lot to do.
I've thought some more about it and I think that the syntax should be But what finally brought me around is that we'll likely end up with a syntax like We still kind of get the strange consistency with the colon even when it isn't a colon. And it's kind of nifty that it's actually another symbol, too. People could go "ah, it's like types, but for parsing". |
I started keeping a "quasi checklist", a list of the individual parsing modes a
Note that this is a checklist for quasis, not for unquotes. Will need a similar checklist for unquotes, which I deferred until after this for reasons I don't remember now. |
Alright, now that that's done, let's keep a checklist for the unquote forms, too. Seemed to work pretty well.
|
(Syntax is now Let's be conservative and wait with this until we see a clear use case for it. I think if we decide to go down this road, the really useful part would be the ability to auto-concatenate identifiers and strings into bigger identifiers, like so:
That could be really nice — but let's scope that to be outside of this issue. |
I'll just note that this issue is a little bit stalled because it's hit some conceptual difficulties. When you're about to parse an expression, you might hit a prefix op or a term. Therefore, any of these is fine as an expression:
The problem comes because we don't know which "parser mode" we should have been in until after the Perhaps it would be possible to "fixup" the parser state once we see the Q type. The parser assumed it was expecting a term (say), but now that we see Or, maybe the |
Nothing has happened on this front. I'm defaulting to suggesting |
Not sure how that allows one-pass parsing, though ? |
But I think that, inherently, having splicing in a syntaxful language means you can't keep one-pass parsing. Or you're going to have to patch holes by yourself. One way that could look like would be...
That looks awful – because it is. As we've already pointed out numerous times, this is not an issue at all in Lisp(s), because we're already done parsing when we do splicing. (foo ,@(mapcar #'process xs))
;; literally parsed as (at least in CL)
(foo (unquote-splicing (mapcar #'process xs))) So, it's "free" in the sense that it's not in any way special syntax. I think we've established that quite some time ago, but I think it's still worth pointing out. Anyway, I'm not sure how a solution featuring "one-pass parsing" would make sense, let alone look like. Maybe we could get away with only a lot of backtracking? Even then, I'm not sure. I'm not arguing we should pre-process the code, and put in the AST text in place of the I've thought about figuring out a syntax lisp-like, in that you could also use it for day-to-day use, like Lisp can use |
Well, hm, we'd know with a one-token lookahead... but that doesn't sound all that alluring now that I say it out loud. Notably, the expression parser would still need to go "oh, that's a |
Ok, new suggestion that really front-loads the unquote signal: |
that doesn't really simplify anything over |
That's an interesting assertion that I don't immediately agree with. 😄
Yes, that's the worst-case solution to what we need to do with the grammar.
Hm, wait, isn't this trivially true for Perl 6 as well? Parsing happens first, and leads to an AST with a lot of
Given that what we're implementing is a Perl and not a Lisp, are there any obvious benefits that carry over cleanly that I seem to be stubbornly ignoring? That question is often on my mind. 😄 |
Oh, but it does, because
Compare this to
|
Sorry, I meant "versus the possible |
Oh yeah, that one's equivalent as far as the above argument is concerned. Any reason I should prefer |
Absolutely none! Except maybe that it doesn't stand out as much – which is fine for Lisp, since it has no syntax, but might not be for Perl 6/007. I thought |
Here's one reason I've fallen out of love with But then the final ingredient which would make all that machinery make sense is missing: you can't nest those things. Specifically, you can't unquote "several levels up" in analogy with how you'd do flow control with loop labels:
TimToady assures me that this doesn't work, shouldn't work, and will never work. The reason, as far as I understand it, has to do with proper nesting, which is something we value in the parser more than the above conjectural feature. The way the parser works is that it never violates proper nesting, and so you can't unquote Given all that, I just don't see why anyone would choose to use a non-standard delimiter, except possibly to make their code look funny. And — given that I considered the above conjectural feature to be the chief argument for the |
Yes, that's perhaps one of the biggest unknowns with the Let's find out! 😄 |
You needn't convince me about nesting – I argued about it quite a lot already!. So, yeah, I don't remember believing in that S06 bit... but anyway, whatever you choose is fine. We could try translating these: from Graham's "On Lisp": (and another one is the same SO question): (defmacro =defun (name parms &body body)
(let ((f (intern (concatenate 'string
"=" (symbol-name name)))))
`(progn
(defmacro ,name ,parms
`(,',f *cont* ,,@parms))
(defun ,f (*cont* ,@parms) ,@body)))) |
macro cont-defun(Q::Identifier $name, Q::ParamList $parms, Q::Block $body) {
my $new-name = $name.scope.declare("cont-$name.bare()");
quasi {
macro unquote(Q::Identifier @ $name)(unquote(Q::ParamList @ $parms)) { # should the ParamList unquote be bare, without parenthesis?
quasi { # an unquote inside of another one
my $f = unquote(Q::Identifier @ unquote(Q::Identifier @ $new-name)); # ... just to make this more readable
$f(unquote(Q::ParamList @ unquote(Q::ParamList @ $parms))); # same q. for ParamList
};
}; # end of inner macro
sub unquote(Q::Identifier @ $new-name)(unquote(Q::ParamList @ $parms))
unquote-unhygienic(Q::Block @ $block); # mmh... needs that "unhygienic" so that `$parms` are visible.
};
} Whew. |
Seems like the github live update earlier had me miss one comment...
That's not exactly what I mean – but I was unclear, as usual. I meant that there's no "parser state" to be recovered after an unquote. You don't have to "insert" anything, to parse in a different way – it's not even really splicing at parse-time, it's a function call in the source code.
Not quite, exactly because of that same "parser state". In lisp, it's all functions calls. Doesn't matter if you're splicing an operator or whatever-else.
I'm not 100% sure what you're refering to here? |
Just making sure it's not the case that the Lisp advantages you like to highlight are blindingly obviously mappable onto the problems we're wrestling with in 007 (and Perl 6). The very-early stages of Perl 6 macros consisted of "yuh, of course we're gonna have Lisp macros (and not dirty C macros, at least not just)". Later: "oh, huh, Perl is not Lisp, Perl is Perl". (And all the other languages that are not Lisp are also not Lisp, and all have slightly different readings of what "macro" means.) With all that said, I really, really want to learn from Lisp and soak up all the experience with macros that's obviously there. That's why I keep trying to read Lisp code, and to grok what the macros in there are doing. |
Completely rewritten Hopefully you'll forgive some bikeshed coloring suggestions. On less confusing and prettier quasi syntaxClaim: the keyword-and-block
So... Wikipedia:
So, strawman proposal, replace the
quasi quotes the enclosed code.^1 (Or more brackets, with matching open/close count eg For the Texas equivalent, use at least three pipes:
On less confusing and prettier unquote syntaxClaim: the
So... Wikipedia:
So, strawman proposal, use bracketing that includes a reversal of the ⌜ and ⌝ symbols:
For the Texas equivalent use:
^1 If there must be a keyword, perhaps |
Consider yourself forgiven. And please forgive me in turn for answering somewhat selectively, where I feel I have something to say. Feel free to take my silence on the rest as implicit agreement. Maybe.
I'll 50% agree on this one. It's a block more often than people actually mean block. That is, in
someone clearly meant to produce the expression On the flip side, though, it is a block in the sense that it holds in variable declarations.
This is part of "hygiene". I expect people are going to like that and be pleasantly un-surprised by that, because that's how braces/blocks behave.
Ok, but is it worse than using In some ways, it's too good a term to pass up, even when the match isn't squeaky-Lisp perfect.
Would it help if I reformulated the above as "a neat way to build code, some of comes in as parameters"? Because that's what it says, 'cept with more stilted language.
Yes, in logic. That whole article you're quoting refers to Quine's notion of quasiquotation in formal languages, that is, in mathematical logic. The Lisp-y backquote and the comma would have much bigger claims to quasiquotation syntax than
Not saying I endorse it, but what in your syntax would be the corresponding way to express
Unmatched footnote. What's your use case for having more brackets? Do you conceive of something like
Still not assuming I endorse the rest, this is not going to fly because the Texas equivalent of a matching pair of braces can not be a non-matching symbol. (Not by some hardcoded rule specified somewhere, granted, just... not.)
Ok, then let me help you with that one: it's ugly. 😄 Question is more like, is that a (necessary) feature, or something we should fix?
Again, blocks convey scoping and hygiene, something that isn't all that far-fetched with unquotes either.
You're proposing using a quasi-quotation symbol (from mathematical logic) to stand in for unquotes? You don't consider that a bit confusing?
I think that falls under "you think it's cute today". More specifically/constructively: we could have played around with outwards-facing brackets for ranges, like some mathematical textbooks do:
But we didn't — nor a competing form with ranges like Also, what in your syntax would be the corresponding way to express
One good thing about this footnote: I finally understood why the heck you proposed |
I consider these good arguments for using However, I was thinking that you intend to also support quasis that:
Afaict supporting these, even if they're a much less common use case, would be good arguments for not using
Yes, very much so according to google, wikipedia, and my English language sensibilities.^1
The reformulation isn't helpful to me because I understand quasi quotation. But yes, I think that reformulation is much closer to what mere mortals will get. It also happens to coincide with the
Sure. But:
So that nixes backquote and comma.
I don't know. I'll respond to that in another comment.
It's pretty weak.^2 Let's move on.
Fair enough. That was one of a couple of especially wild suggestions. :)
Well, as I said, I'm strawman proposing. This is part of exploring what I see as problems with planned Perl 6 syntax. It didn't feel right to simply complain without strawman proposing something else. But, yes, I see the mathematical usage to be so near identical in concept to quasi-quoting in programming languages that use of the same syntax seemed attractive and I see unquotes as basically the inverse of quasi-quoting. That said:
Fair enough. This was the other especially wild suggestion. :)
I'll defer a response to that for a later comment.
Indeed. That was part of my point. I still think I'd find it easier to explain my mostly tongue-in-cheek suggestion "toast" to a mere mortal than "quasi". (To a small degree it was not entirely tongue-in-cheek; I thought it could perhaps be spelled Anyhow, I've since come up with another strawman proposal:
That is, the keyword Of course, the And for unquotes I strawman propose:
If a user actually means to write If you really don't like the above, please consider waiting a week or two before replying. :) ^1 Data For me a google for "enumeration" yields 100+ million matches. "commonly used in mathematics and computer science to refer to a [ordered] listing of all of the elements of a set.". Several mainstream languages use Conclusion? "enumeration" is a common English word. It has exactly the right meaning for a programming language enumeration. Data For me a google for "subset" yields 40+ million matches. "a part of a larger group of related things. ... a set of which all the elements are contained in another set." In Perl 6 a Conclusion? "subset" is a common English word. It has exactly the right meaning for a subtype that's a subset. Using the keyword (Likewise "given" is also a common English word whose meaning is well suited to the use made of it in Perls.) Data For me a google for "quasi" yields 200+ million matches. "seemingly; apparently but not really. ... being partly or almost.". So, a popular word, used more than enumeration and subset combined, but with a meaning that isn't at all suggestive of what a quasi quote is when it's used without the word "quote". And the #1 result when I search for the highly specific phrase "quasi-quotation" is the wikipedia page on "quasi-quotation" which all but ignores programming language use of the concept. Conclusion? "quasi" is a common English word. It does not remotely hint at what it might mean in Perl 6. Even the relatively obscure term "quasi quotation" is a poor fit. I was hugely surprised by your suggestion that the keyword choices "enum" and "subset" are of about the same quality as "quasi". Hopefully the foregoing has opened your mind about this bit of bikeshedding. You may be in love with "quasi", and it makes sense in 007, but I would like to think that Perl 6 macros will aim at avoiding unnecessarily weird color schemes. ^2 Assuming a Texas variant of quasi quoting existed, and that it was several |
This also starts making use of an optional parameter to the `unquote` rule, passing along the expected type in the context so that we can fail earlier, inside of the rule instead of outside it. This will go some way to getting out of the quagmire described in #30 (comment) -- it was enough for Q::ArgumentList, for example, which clashes with term position -- but I'll be quick to note that it doesn't address the problem at its root. Notably, when we do hit the type, at the end of the unquote, we've already had who-knows-how-many side effects along the way from the stuff inside that we parsed. In other words, something like `unquote(qtype @ expr)` would still be beneficial, maybe even necessary, in order to finish up issue #30.
Since Putting Qtypes in the Lastly, though I seem to be in a minority in this thread to do so, I kind of like the keyword |
Oh! Here's another thing I wanted to mention. Besides the slogan
that I mentioned above, I would also like to champion the slogan
The two features that I usually associate with slangs fit well with quasiquotes:
But there's a third one too that I hadn't kept at the front of my attention but that seems blindingly true with quasis:
In the case of quasis, the runloop is simply a sub that evaluates to a Qtree. I don't know if it means that all slangs are templates... I guess time will tell. |
FYI, I just began reading A Guide To Parsing; in it, Federico explains how "In a way parsing can be considered the inverse of templating". |
Well, yes — parsing But also, in subtle ways, no... which is why Frederico writes "in a way", I guess. 😛 For one thing, spooling a flat structure from a deep model is algorithmically very different from deriving a deep model from something flat. There's a fair amount of guessing/backtracking when you do the latter which is missing from the former. The one point that stands out from skimming the document is that Perl 6 (and 007) are languages such that scannerless parsing is the only option. That's because "where the lexer ends and the parser begins" becomes such an overriding issue that scannerless becomes the only reasonable option. And that's because "you have to know which language you're in" in order to even do lexing properly — in other words, lexing is tied up with and dependent on the parsing up to that point. Not all languages are like that, but it feels reasonable (maybe inevitable) that a syntax-extensible language with macros and slangs be like that. I liked the text (having skimmed it). Thanks for throwing it my way. 😄 |
And also, yes, quasis (being templates) are the "inverse" of parsing in the sense that when you stuff a string into an |
Brainstorm incoming. I tried to read the entire thread before commenting but some dude raiph hijacked the thread with bikeshedding and I lost heart wading thru it all. I hope I'm not about to do repeat his mistake but we are all one after all so I apologize if there ain't that much difference between the two of us. Also, I'm pretty sure the following will be completely invalid and/or stupid in multiple places, but I'm just going to spew it out rather than pause to worry about that because that can kill the flow and you were gracious about his stuff, so why shouldn't I just post what I've got right now? #Strawman proposal 1 Macros are their own slang, analogous to the way rules are. The macro slang is almost identical to the main language except it introduces a couple critical tweaks. It's essentially a template language where most of a typical template uses exactly the same syntax as the main language. Macros with unquotes must initially mention their unquotes (with possibly one exception which I'll get to) as either parameters of the macro in a parenthesized list at the start, or via variable declarations. Each such mention of an unquote / parameter must use a prefix which I'll call a sigil. I'm thinking symbols like So, for example:
The #Strawman proposal 1.1 The default type for macro parameters depends on their sigil:
#Strawman proposal 2 Replace use of the word
The unicode characters #Strawman proposal 3 Let the main language parse anonymous Am I completely crazy? |
Hi, sorry for dropping the ball on this one. Will attempt a reply now. |
Here's hoping I manage to write this without coming off as exceedingly nitpicky or grumpy. 😄 @raiph, the summary is that you are addressing issues which (I've come to understand) are important in your mind, but not so highly prioritized in mine. (I'm still glad that you're inventing in this space, don't get me wrong. Keep it coming!) Because I know that summary is not nearly sufficient, let me list some specifics:
That's it. Again, sorry if this comes off as just finding flaws — I hope I'm getting across that the above are not so much reactions from me as they are from the realities of syntax, parsing, compilation, and Perl. (And, likely as not, my own view of things is limited too and there are adequate responses/workarounds to what I consider problematic.) |
Although I haven't much shifted my stance on whether "quasiquote" (and its current keyword/syntax) is easy to understand or optimal... ...I realized one thing the other day that sets 007 (and Perl 6) apart from Lisp: in 007 (and Perl 6) there's quasiquotation, but no quotation. (See here for a quick explanation of quotation and quasiquotation in Lisp.) We don't have a construct, analogous to Again, this doesn't much change my stance as to the appropriateness of these terms in 007 and Perl 6... but it does explain to me parts of what people (maybe?) find distasteful about the term "quasiquote" in 007 and Perl 6. |
@raiph, I'm not sure I said it clearly back in 2016, so let me say it now: reversing the quotation symbols for unquotes strikes me as an idea that really has the heart in the right place — they're called "unquotes", after all, and my working understanding of what they do semantically is that they decrement the quoting depth — it's just that I don't believe the execution of the idea works. Or, to be more precise, I can't think of one example in the wild where it has worked. The reason, I think, is simple: it runs against the grain of what parsers are typically able to deal with. Squint hard enough, and you see not just parser technology adapting to what language syntax needs, but also the converse — it's not that we couldn't produce a parser that handled |
Since I wrote the above, I've also come to realize that Scheme/Lisp quotation (and quasiquotation) is much worse for hygiene than Raku's/Alma's variant. (I've come to this realization after dipping into the two Kernel/vau papers, on which I hope to write several comments, soon.) I don't like to tease without providing details, so here is a brief summary: in Scheme/Lisp, lookup of a symbol happens entirely at runtime, whereas in Raku/Alma, lookup has a static part and a dynamic part; this is what leads on to unique variables and a stronger guarantee of hygiene. Hope to write more on this soon. |
@raiph I just found the term "code quotes" in this paper, and found it sympathetic. From what I can see, these are actual quasiquotes (in Java), but the name is friendlier, and reminded me of your I don't see that I ever addressed using I think in a parallel universe we could have easily gone with Of course, since Alma is meant to be able to extend any and all syntax, |
Hi Carl, belated happy 2021. :) I just noticed a bunch of comments in this repo in recent months that I'd previously missed in issues I'm mentioned in. One thing I'm unclear about and need to resolve is whether including asides intended to be about the macros Raku eventually gets, not alma, are inappropriate here. In this comment I will presume they're OK if explicitly noted as such. PLMK if you'd rather I just dropped them altogether.
You'd already said as much back in 2016, and I had replied with:
And now, in 2021, my thinking is... fair enough. :)
Aiui the intent was that Raku's macros should default to hygiene so that sounds good. Aiui the intent was that Raku's macros should also be able to be unhygienic. So there's that too. Though I'm sure that could reasonably be punted on for now / this decade. Does (And some more suggestions for Raku paint -- not alma. Maybe
I agree. Actually I'd say One huge thing in favor of But That said, as an incurably cheeky bit player I now strawman suggest yet another color that seems appealing as I write this sentence: |
Happy 2021, and (a not belated) 新年快乐 in the year of the ox! Happy 牛 NIU year 😆
Well, this thread is funny — it started out as a small checklist to do an ostensibly simple thing (to make HN happy, more than five years ago), but it quickly ran into a technical hurdle which I will now describe: Let's say there's an unquote in a quasi: The resolution to that, which basically happened in and around this issue, is the I'm not married to this syntax which kind of introduces a new (pseudo-)operator Unfortunately, just outlining the solution doesn't make it so; the implementation of this has stalled on exactly how to make that happen within the limits of a recursive-descent parser, and so I've been taking a yak-shaving tour towards exploring alternate parsers that would be up to the job (#293). (As I type this, I'm thinking "surely it can't be that tricky? All I need is to hardcode multiple rules for the different types of unquotes...". I might give it a go, if for no other reason than to remind myself why it was indeed that tricky.) As this thread got stuck like a gazelle on the savanna, it became easy prey for discussions about quasiquoting, possible syntaxes, and philosophy/etymology. I would like to stress immediately that this has been one of the most valuable/enjoyable Alma issues for me, if not the most valuable/enjoyable. Simply because it has generated so many thoughts and ideas and bravely put them up for scrutiny — as well as involving basically all the people who have ever had an active interest in Alma. It's suitable, if unquotes are somehow at the core of what Alma is and wants to be, for this issue to also be the core of the repository's activity. I have not minded at all the fact that often the solutions proposed were for problems that I already considered solved, or not in dire need of solving. 😄 It is right to call some of the discussion "bikeshedding", yes, but that term to me was never all that negative; it's about finding smaller optima within larger ones.
They are not just OK, but encouraged. My stance on Raku these days is... complicated, but I still like and believe in the language. Although Alma (née 007) is not exclusively about supplying macros for Raku (née Perl 6), that charter is still in play. (Concretely, it's less about "yo Raku, you should use the
I still haven't dropped the other shoe on the above teaser, but it's happening slowly over in #302 (another @raiph thread, and strong contender to "most interesting discussion in the repo", at least I think so). But saying things many times is probably good, so I'll try in a partial, most likely flawed way now: in Raku (and Alma), parsing goes as far as establishing the definition of a use there and then. That is, if you have
The parser knows enough when it sees the use Not so Scheme. In Scheme, a symbol is just a symbol, and so the parser sees an (I know, it's surprising! Scheme is known for its hygiene.) The upshot is that, when time comes to expand a hygienic macro, what Scheme needs to do is a massively complicated (and costly) cover-all-bases alpha-rewriting of everything. John Shutt described this process as something he made sure he understood well enough for his thesis work, but then promptly forgot about soon after. The point is that, because the parser does the bare minimum, all of the hygiene work has to happen during macro expansion instead. In Raku/Alma, the parser quite naturally does more, and so the later hygiene work during macro expansion becomes less.
"Unhygienic" could refer to two things.
So, not much need for punting, I think. Like, 90% of "unhygienic" isn't even a feature, and the remaining 10% we have a plan for and could prioritize as high as we want.
Since this question follows directly on talks of hygiene, I'm assuming you feel it's making a connection to hygiene. But I... don't quite see it. I'll try to answer anyway. There are two ways to think about what a quasi expression represents. The first is that a code level, it's more of a "template" or (if you will) a function waiting for some parameters that it'll use to build an AST. The second is that whenever you evaluate a quasi expression (at "runtime", which may well be at macro expansion time during compile time), the result you get is an AST. The template/function interpretation is "internal" to the implementation, and all we ever observe is the AST result. In either case — regardless of which interpretation you pick as "the" interpretation — it's the case that I just realized something. The above means that
Well, first off, see all of the above answers. Second off, I'm still trying to follow the initial design set out by S06. (Yes, seemingly years after everyone else stopped caring about the synopses. 😄) What it says about this is that you can choose your delimiters as you please for Also, when we say hygiene is so nice we'd like it to be the default (in spite of Common Lisp people's contrary opinion), I'm wondering if dropping hygiene just by switching delimiters doesn't make it a little bit too easy to drop hygiene. At the very least, I'd like to see some other reason to want to drop hygiene (besides anaphora) before I go and make it super-easy.
I do like it. And via S06, either Damian or Larry liked it many years ago, and I enjoy the feeling of respecting that, too. In fact, if you take a huge step back and imagine a whole host of activities where you keep some parts of a quotation literal and allow some parts to be interpolated — Python f-strings, ES6 template strings, SQL prepared statements, Lisp quasiquotes — I think a good term for that general activity might very well be "quasiquotation".
The problem with that is that it focuses on the mechanism and not on the result, which is usually a mistake when naming things in programming languages. Consider if instead of Now, arguably, the term "quasi" commits exactly the same mistake, focusing on the mechanism and not the result. But while (A famous and widespread example of "keywords that talk about the mechanism" is |
I'd like to solicit a macro Something tells me that that's not as easy as it might sound, because |
I don't think that's possible in (most) Lisps, FWIW. You can't define something like |
Bel defines those in terms of Bel: |
Hacker News wants unquotes. We happily oblige.
Unquotes in expressions
Whenever the parser is ready to parse a term, it should also expect an unquote.
Technically, I don't see why we shouldn't expect the same for operators. But we get into the interesting issue of what syntactic category it is.
Screw it, I'm tired of theorizing. Let's just steal the colon for this.
Backporting this solution to terms, you could mark up a quasi as
term
if you want, but it's the default so you don't have to:At the time of evaluating the quasi (usually macro application time), we'll have the type of the unquoted Qtree. The runtime dies if you try to stick a square Qtree into a round unquote.
But the parser can sometimes reject things early on, too. For example, this shouldn't even parse:
(That slot doesn't hold an operator, it holds an identifier.)
Unquotes for identifiers
007 currently has 5 major places in the grammar where it expects an identifier:
is <ident>
traitsmy
andconstant
sub
andmacro
The traits one is kind of uninteresting right now, because we have four trait types. Someone who really wanted to play around with dynamic traits could write a case expression over those four. So let's skip traits — might reconsider this if we user-expose the traits more.
The three declaration cases are the really interesting ones. Notice that each of those has a side effect: introducing whatever name you give it into the surrounding lexical scope. (Handling that correctly is likely part of the #5 thing with Qtree strengthening.)
I would be fine with the
{{{identifier: id}}}
unquote accepting bothQ::Identifier
nodes andStr
values.Q::Identifier
is basically the only node type where I think this automatic coercion would make sense.Unquotes in other places
These are the remaining things I can think of where an unquote would make sense:
Q::Statements
)Q::Parameters
)Q::Block
)Q::Trait
) — note: we should probably have aQ::Traits
container, just like we do for statements and parametersQ::Statement
) — not sure what this one'll give us over sequence of statements, but it's possible it might be usefulQ
nodesQ::Unquote
) — mind explosion — note that this is only allowed inside aQ::Quasi
The text was updated successfully, but these errors were encountered: