Example (SQL query integrated via macro):
my Database $db = MySqlDatabase.connect(...);
$db.select * FROM Foo WHERE Foo.bar LIKE a%b;
Could I implement this with the select function being a macro on the
Database base class: but invoked via the $db invocant? I am aware that
the macro would be a compile-time operation: but it could resolve into a
run-time mechanism that uses the invocant.
Dave.
--
http://dave.whipp.name
If you use a module or class that defines macros, you can import the
syntax at that point as well as the name. Might take an explicit import
of the particular name to accomplish that though.
But basically, yes, you can do that. Macros would be pretty darn useless
if you couldn't import them.
Larry
To answer your actual question, you either need to have some keyword out
front to start the alternate parsing, or you need to treat ".select"
as an infix macro that has an ordinary expression on the left ($db) and
a specially parsed argument on the right (* FROM Foo WHERE Foo.bar LIKE a%b)
Larry
> To answer your actual question, you either need to have some keyword out
> front to start the alternate parsing, or you need to treat ".select"
> as an infix macro that has an ordinary expression on the left ($db) and
> a specially parsed argument on the right (* FROM Foo WHERE Foo.bar LIKE a%b)
This feels a bit clunky. The sort of hack one makes when its too late to
fix it.
If we define .select as an infix macro, it is then not scoped to the
invocant. This means that it would confict with any other .select method
that one might wish to call. E.g.
$io.select(...);
(OK, thats not a good example, but you get the gist). If sure it would
be possible to write the macro in such a way that it looks at its LHS
arg -- and ignores itself if its not a Database object ... but that
places an overly large burden on the macro writer. To avoid this burden,
I'd like to propose C<macromethod> as a counterpart to C<submethod>. A
macromethod would enable me to write an invocant-scoped macro, without
polluting the lexical namespace:
class Database
{
...
macromethod select ($lhs, $rhs:) is parsed /<sql.select.body>/
{
"$lhs.do_sql('select $rhs')"
}
}
Without this mechanism, then we need a way to prevent an infinite
regress on macro processing. I am assuming that, if the output of a
macro is a string, then that string will be re-parsed and any macros in
it will be expanded. How would an infix macro indicate that it didn't
want to handle the "$io.select" example? If it returns its input,
unchanged, then that would be an infinite loop.
Dave.
--
http://dave.whipp.name
Well, if you did that, it surely couldn't be polymorphic, which kind
of defeats most of the purpose of making it a method. Yeah, namespace
pollution is a little issue, but not really. You could scope the
macro to the Database class, so it would be C<Database::select ...>.
Interestingly, it would be almost impossible to get effective methods
that use an C<is parsed> trait. Is it legal to do so?
Luke
> Well, if you did that, it surely couldn't be polymorphic, which kind
> of defeats most of the purpose of making it a method.
I disagree. Consider the "template method" patten. This uses a
non-polymorphic method in a base class to invoke a set of polymorphic
methods in a standard sequence. I would consider my "macromethod" in a
similar vain.
Dave.
--
http://dave.whipp.name
I'm not quite sure I follow you (I'm not familiar with that pattern).
But the macromethod I imagine is the non-polymorphic one, and the one
it expands to is the polymorphic one, if I'm guessing correctly. And
you certianly could do that. But the actual I<parsing> could not be
polymorphic. Thus, this wouldn't work:
my $db = new Database;
$db.select ...
Because the compiler [may] not know that $db is a Database until
runtime, after it's been parsed. However, this could work:
my Database $db = new Database;
$db.select ...
Which may just be the price you have to pay to use C<macromethod>.
But then, the only advantage that I'm seeing to macromethod, other
than the namespace pollution bit, is that it can handle arbitrarily
complex variable names, which macros ought to do anyway. Which means
you usually have to use a parse tree instead of simple string
substitution (I trust Larry to make it sufficiently easy to do that).
So, what I'm essentially saying is that C<macromethod> doesn't buy you
much save syntactic sugar. Perhaps you can give a concrete
counterexample?
Luke
I am uncomfortable with the notion of depending on the declared type of
the left argument for deciding which macro to use, because its failure
mode potentially includes totally misparsing the right argument, and
because the declared type of the object is not necessarily the same
as the actual type, so if a derived class had its own idea of the macro,
the "wrong" macro would be used according to at least one viewpoint.
: Without this mechanism, then we need a way to prevent an infinite
: regress on macro processing. I am assuming that, if the output of a
: macro is a string, then that string will be re-parsed and any macros in
: it will be expanded. How would an infix macro indicate that it didn't
: want to handle the "$io.select" example? If it returns its input,
: unchanged, then that would be an infinite loop.
If the declaration is essentially nailing down a particular class in
a non-virtual sense, then there's really nothing gained over writing
IO::select $io: ...
DB::select $db: ...
other than the obvious obfuscational benefit of having the class
selection defined elsewhere.
I'm not saying that what you want is bad. I'm just uncomfortable
with it. Certainly a macro could be written to pay attention to the
declared type of its left argument, and we could even arrange for
some kind of compile-time multimethod dispatch with whatever syntax
is deemed appropriate. But mixing such compile-time semantics with
a notation that supposedly mandates run-time dispatch is a recipe
for a certain amount of confusion no matter how well we do it.
Larry
yes: http://patterndigest.com/patterns/TemplateMethod.html
> But the actual I<parsing> could not be
> polymorphic. Thus, this wouldn't work:
>
> my $db = new Database;
> $db.select ...
>
> Because the compiler [may] not know that $db is a Database until
> runtime, after it's been parsed. However, this could work:
>
> my Database $db = new Database;
> $db.select ...
To a large extent, this depends on how powerful the type-inference
mechanisms are. In theory, if MyDatabase.new "returns Database", then
the type of $db can be inferred. Even if the return type is not
explicitly defined, we can look in the method-body, and see that its
constructing/returning an object of base-type Database.
But you're right, there are situations where the (base) type might not
be knowable: and these could result in syntax errors.
> So, what I'm essentially saying is that C<macromethod> doesn't buy you
> much save syntactic sugar. Perhaps you can give a concrete
> counterexample?
I admit that I have a sweet-tooth: I like syntactic sugar ;-). And I'm
one of those environmentalists who don't like (namespace) pollution.
The sugar I'm using here is to go from
$db.do_sql("select * from Foo");
to
$db.select * from Foo;
I'm sure there is nice way to represent this with a leading keyword: but
one of the things that Perl6 is doing (over perl5) is to make (almost)
everything callable as methods. Thus if we allow (as a standard macro --
though a macromethod would also support it)
select $db: * from Foo;
then we should also allow the method-call syntax. I'll admit that this
is one of those cases where the user already knows that there's some
magic happenning -- that "select" is introducing a new syntax -- but it
would be nice to keep the invocant part looking like Perl6 code.
Perhaps I should back off a bit: Perl6 *will* be powerful enough support
the "Macros::macromethod" module, so perhaps I'll be able to write it in
a year's time, or so. It'll be a good test of the extensability mechanisms.
Dave.
--
http://dave.whipp.name
Except they wouldn't, at least not always.
$db.select * FROM Foo WHERE Foo.bar LIKE a%b;
$db.select() *
FROM(
Foo(
WHERE(
Foo.bar()
)
) LIKE (
a % b
)
);
The only part of that I'm not sure about is infix:LIKE, since such an
operator hasn't been declared. But I assume you get the idea--you could
conceivably have Very Bad Things happen if Perl doesn't catch a
macromethod call.
--Brent Dax <bren...@cpan.org>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
>How do you "test" this 'God' to "prove" it is who it says it is?
"If you're God, you know exactly what it would take to convince me. Do
that."
--Marc Fleury on alt.atheism
But in such cases, the $db variable would not (could not) have a
run-time ".select" method: so you'd still get an error -- albeit at run
time.
Dave.
--
http://dave.whipp.name
Since we're fishing, call it a circumfix operator, something like
sql...execute.
Like this:
$db.sql select * from Foo;
execute;
__________________________________________________
Do you Yahoo!?
Yahoo! Web Hosting - establish your business online
http://webhosting.yahoo.com