-
Notifications
You must be signed in to change notification settings - Fork 14
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
Have a mechanism to allow arbitrary (undeclared) identifiers in expressions #159
Comments
I think it goes well with Racket's |
It's a humbling feeling to read through a manual page and recognize that it's well-written, but still not understand much of it. I think this is due to me not having enough Racket context, though. Here, let me just throw "study Racket" on top of my TODO pile, right after "finish the 'Let Over Lambda' book"... |
Another raw/undigested comment about identifiers: in quite a few built-in and user-defined syntactic constructs, the presence of an identifier is a declaration. We might want to have a nice way to specify that too. In that case, there would be three modes:
Though the devil is in the "some block" details, I fear. Often enough the block in question is not the immediately surrounding one, but perhaps the next one down. (Examples: sub/macro parameter lists, |
Sorry, it's a bit hard to digest without having read some racket macros thing (like the Fear of Macros tutorial). It's basically dynamic variables (Perl 6's (aif condition (+ 3 it)) ;; "it" is bound to the condition The mechanism is used this way: (define-syntax-parameter it ;; define "it" is a special syntactical construct, which some macro will define
(lambda (stx) (raise-syntax-error #f "use of it out of anaphoric macro" stx))) ;; default value, if you try to use a bare "it" outside of an anaphoric macro
-- then you define the macro:
(define-syntax aif ;; anaphoric if
(syntax-rules () ;; this () is the list of identifiers to match literally. none here
[(aif test then) ;; the macro syntax
(let ([t test]) ;; the result: first evaluate test
(syntax-parameterize ([it (syntax-id-rules () [_ t])]) ;; then bind "it" to t's value
(if t then else)))])) ;; and generate an "if" node |
let's make this Perl 6, to try to be clearer ... my $?*it = Failure.new("not in an anaphoric construct");
macro aif($condition, $body) {
quasi {
my $?*it = {{{$condition}}}; # dynamically scoped for the rest of the quasi block.
if $?*it { {{{$body}}} }
}
}
aif 3 + 3, {
say $?*it; # the identifier already exists at this point, even without us knowing `aif` is a macro! it doesn't need to be specially introduced! it's just dynamically redefined!
} (there are chances you could even do it with just |
Yes, that was much clearer. I haven't tried, but I expect I'll be able to go back and read that manual page without a problem now. Thank you for your efforts at getting the point across; it's much appreciated. Yes, I expect you would be able to use dynamic variables with macros like that in Perl 6. Or at least, I got it to work in Rakudo just now:
(No, I have no idea what that "Weird node" warning is about.) |
Though needless to say, using dynamic variables kind of misses the point of anaphoric macros... 😄 |
oh, for sure. It's dynamic at compile-time, but very lexical at runtime :). |
No, it ends up dynamic at run-time too:
What I meant was that variables introduced anaphorically are meant to look like ordinary lexical variables, which dynamic variables don't do. |
I was talking about my $?*, not dynamic variables as they exist. |
Even so, having to mark a variable with sigils just so that it'll work inside of the macro invocation defeats the whole point of anaphoric macros (and of this issue), does it not? |
I don't understand what you mean here? This feature "dynamically scoped at compile-time only" is very specific, isn't it? It's a workaround to "introducing arbitrary identifiers": you have a fixed set of identifiers to work with. |
Yes, we seem to be speaking at cross-purposes a little for the past three messages or so. But I think it can be worth sorting out. I think what's missing is a clear statement of our goals. My goal is for a symbol such as Your goal was to explain Did I get that right? |
Oh, it doesn't look normal for sure. That can deemed fine. However your (b) is wrong: the very idea is that the variable is only declared in the module that declared |
I was thinking about this one today. Here's a possible mechanism:
I was also thinking a |
I just ran head-first into this distinction when trying to implement #410 in a branch. We need to distinguish now, at the grammar level. At least between things that do lookup (identifier terms) and things that don't. |
Another use case for this feature would be automatically declaring |
In the action method
term:identifier
, there's this wonderful piece of code:Actually, for the purposes of this issue we can ignore the postponement logic and the check for postdeclared macros; the code then becomes much simpler:
In other words, undeclared variables cause the compiler to abort with
X::Undeclared
.What if we could selectively turn off this check? Or, even better, what if we could selectively let some identifiers through? I think that would make a big difference for DSLs, to enable stuff like this:
The details are not clear to me, but it just occurred to me that we can do this. And we probably should.
It's funny, I've used "Perl 6 has a very particular intertwining between parser and static checks" as an argument many times, but I've never considered doing the above, which seems like it'd solve quite a few problems.
The text was updated successfully, but these errors were encountered: