User-defined infix subs/methods?

20 views
Skip to first unread message

Autrijus Tang

unread,
Jul 9, 2005, 11:34:23 AM7/9/05
to perl6-l...@perl.org
In Pugs's ext/Set/lib/Set.pm, there are a number of user-defined
infix operators. To avoid unicode in mails, I'll use a hypothetical
&infix:<===> as the operator name.

Consider the sub case:

class Set;
sub infix:<===> (Set $x, Set $y) { ... }

Is it correct that this line:

Set.new === Set.new

Only works when the &infix:<===> function is in scope? That is, one
would need to add `is export` to its declaration for the user of the
Set module to access to this operator.

Does the same holds for `multi sub` as well?

What if this is expressed as a method:

class Set;
method infix:<===> (Set $y) { ... }

Does it also need `is export`? If not, how does the parser know that
the === is a valid operator name, without the ability to deduce the type
of its left hand side object? If yes, does it simply fail at runtime
if the left hand side has no infix:<===> defined? Exporting a method
is a novel concept to me, too.

Thanks,
/Autrijus/

Larry Wall

unread,
Jul 9, 2005, 6:58:45 PM7/9/05
to perl6-l...@perl.org
On Sat, Jul 09, 2005 at 11:34:23PM +0800, Autrijus Tang wrote:
: In Pugs's ext/Set/lib/Set.pm, there are a number of user-defined

: infix operators. To avoid unicode in mails, I'll use a hypothetical
: &infix:<===> as the operator name.

We've intentionally been using Unicode in this mailing list on the
assumption that people will learn to deal with it one way or another if
they have to, and will otherwise put it off as long as possible. :-)

: Consider the sub case:


:
: class Set;
: sub infix:<===> (Set $x, Set $y) { ... }
:
: Is it correct that this line:
:
: Set.new === Set.new
:
: Only works when the &infix:<===> function is in scope? That is, one
: would need to add `is export` to its declaration for the user of the
: Set module to access to this operator.

A6 discusses this to some extent. We need to distinguish the function
from its syntax. A function or method, even if it has a funny name
like infix:<===>, is just an ordinary function or method, and can
exist in any scope that any other function or method can exist in.
As such, it can be subject either to early binding or late binding,
just as any other function or method can.

However, anything which implies a change in syntax must, by definition,
be bound as early as possible, but no earlier. In particular, Perl 6
mandates that all syntax change be lexically scoped. So the *syntax* of
anything macro-like is propagated only by export, and has a syntactic
effect only if imported lexically, or more precisely, when bound into
a lexical scope at compile time. Everything from user-defined syntactic
categories to wholesale Perl grammer rule overrides falls into this
category of macro-like entities.

: Does the same holds for `multi sub` as well?

Yes, at least one of the multi-subs in question must export its syntax
to your lexical scope (or be predefined by Perl). It is not necessary
for all of them to export to your scope, since as soon as you've installed
infix:<===>, you have a way to call all of them.

: What if this is expressed as a method:


:
: class Set;
: method infix:<===> (Set $y) { ... }
:
: Does it also need `is export`? If not, how does the parser know that
: the === is a valid operator name, without the ability to deduce the type
: of its left hand side object? If yes, does it simply fail at runtime
: if the left hand side has no infix:<===> defined? Exporting a method
: is a novel concept to me, too.

You aren't exporting the method. You're exporting the call syntax
that remaps A === B into infix:<===>(A, B). That's going to use MMD
by default, but that includes ordinary methods in its calculations.
I suppose it would be possible to allow the exported syntax to instead
map A === B into A.infix:<===>(B), but I'm told SMD is for weenies. :-)

Nevertheless, if someone writes that, SMD is probably what they expect.

There are a couple of unanswered questions here you haven't asked yet.
First, how do builtins get installed, and can I influence the parsing
of a module I'm about to use by installing some syntax into * first.
That is, does a compilation clone * for its initial grammar when
it starts up? I think that's a little too dangerous as it stands.
It should take a little more effort to mess with the minds of
unsuspecting modules, so maybe the standard syntax is cloned out of
*STANDARD_PERL_6 or some such scary package name. It's the default for
starting all require-like Perl 6 parses. By default, eval() should
start in the current grammar, but there needs to be a p6eval that
starts in the standard grammar, and hopefully for the translator,
a p5eval that parses in Perl 5 by default, at least until it sees a
v6; or some such. (Or maybe it's just an option on eval, which would
let us even specify the version we were hoping to emulate.)

Another question is whether some or all of the syntax declarations
should be exported by default, in the absence of an explicit
"is export". And if so, what is the default export tag? I suspect
most such syntax will be defined with the intention of exporting it.
On the other hand, there may well be some people who will prefer
never to import syntax except explicitly. We want to serve both
needs expeditiously. I think any macro, foo: category, or grammar mod
automatically exports with "is export<SYNTAX>" or some such (unless
you override it), and that is considered a subset of the DEFAULT tag.
However, there needs to be some setting on the "use" end that kicks
SYNTAX out of DEFAULT for the current use. Not sure what that would
be.

no syntax;

use use :SYNTAX(0);

$?USE_SYNTAX ::= 0;

[your ad here]

Larry

Autrijus Tang

unread,
Jul 12, 2005, 5:27:48 AM7/12/05
to perl6-l...@perl.org
On Sat, Jul 09, 2005 at 03:58:45PM -0700, Larry Wall wrote:
> It should take a little more effort to mess with the minds of
> unsuspecting modules, so maybe the standard syntax is cloned out of
> *STANDARD_PERL_6 or some such scary package name. It's the default for
> starting all require-like Perl 6 parses.

Note that this requirement is already satisfied, under the "separate
compilation doctrine" in the hackathon notes.

Each compilation unit needs to be compiled without any information to
the symbols in the caller environment. It may export symbols, but may
not silently make use of caller's symbols, which naturally includes
user-defined operators.

Thanks,
/Autrijus/

Larry Wall

unread,
Jul 12, 2005, 5:10:06 PM7/12/05
to perl6-l...@perl.org
On Tue, Jul 12, 2005 at 05:27:48PM +0800, Autrijus Tang wrote:

Good, I'd forgotten about that. Which means that it's even harder
for someone to compile a module in a "strange" dialect, since they'd
essentially have to write their own version of "use" that forces
recompilation ("reuse", if you will). And the harder we make it to
write "reuse", the better.

Larry

Larry Wall

unread,
Jul 13, 2005, 12:28:28 PM7/13/05
to perl6-l...@perl.org
On Wed, Jul 13, 2005 at 05:10:14PM +0200, Michele Dondi wrote:
: On Tue, 12 Jul 2005, Larry Wall wrote:
:
: >Good, I'd forgotten about that. Which means that it's even harder

: >for someone to compile a module in a "strange" dialect, since they'd
: >essentially have to write their own version of "use" that forces
: >recompilation ("reuse", if you will). And the harder we make it to
: >write "reuse", the better.
:
: IIUC this will introduce a certain degree of asymmetry though, in that in
: some sense p6 will be extremely generous in giving users the ability to
: use whatever dialect/syntax modification they like in their programs but
: just at the same time it will try to make it hard for them to do so when
: refactoring code into suitable modules. Ain't it so?

Well, yes and no.

No, it just means you need to make sure you copy the "pedigree"
into the new module, if you want the same language. Since we have
policy modules, this could be as simple as copying a single "use
MyLanguage;". I don't mind making some of the pedigree information
indirect like that, as long as the indirection itself is explicit.
But I will always resist any proposal to move pedigree information
out into the implicit environment. That would be as useful as URI
you don't know the root of. It would be a good way to fragment the
Perl community into a tower of babble.

That being said, yes, it will make refactoring harder to the extent
you've mixed the language pedigree in with the actual code you're
trying to refactor. But then, detangling that sort of mixup is
precisely what refactoring is all about, ain't it?

Larry

Michele Dondi

unread,
Jul 13, 2005, 11:10:14 AM7/13/05
to Larry Wall, perl6-l...@perl.org
On Tue, 12 Jul 2005, Larry Wall wrote:

> Good, I'd forgotten about that. Which means that it's even harder
> for someone to compile a module in a "strange" dialect, since they'd
> essentially have to write their own version of "use" that forces
> recompilation ("reuse", if you will). And the harder we make it to
> write "reuse", the better.

IIUC this will introduce a certain degree of asymmetry though, in that in

some sense p6 will be extremely generous in giving users the ability to
use whatever dialect/syntax modification they like in their programs but
just at the same time it will try to make it hard for them to do so when
refactoring code into suitable modules. Ain't it so?


Michele
--
Either of these mechanisms should be available in IE (after
sacrificing a suitable animal to XP SP2, I suppose).
- Alan J. Flavell in clpmisc, "Re: character encoding in CGI.pm"

Ingo Blechschmidt

unread,
Jul 13, 2005, 11:48:47 AM7/13/05
to perl6-l...@perl.org
Hi,

Michele Dondi wrote:
>> Good, I'd forgotten about that. Which means that it's even harder
>> for someone to compile a module in a "strange" dialect, since they'd
>> essentially have to write their own version of "use" that forces
>> recompilation ("reuse", if you will). And the harder we make it to
>> write "reuse", the better.
>
> IIUC this will introduce a certain degree of asymmetry though, in that
> in some sense p6 will be extremely generous in giving users the
> ability to use whatever dialect/syntax modification they like in their
> programs but just at the same time it will try to make it hard for
> them to do so when refactoring code into suitable modules. Ain't it
> so?

no, if I understood Larry correctly, you can of course write a nice
grammar-modifying module, but other modules you use() still use
Perl 6's standard grammar. E.g.:

use Grammar::Ruby;
# Ruby syntax from here on:
proc { |a| puts a + 1 }.call 3 # 4

use SomeOtherModule
# SomeOtherModule.pm will be parsed using the standard grammar,
# *not* Grammar::Ruby.

If you wanted the compiler to parse SomeOtherModule.pm using Ruby's
grammar, you'd have to write:

use Grammar::Ruby;
reuse SomeOtherModule


--Ingo

--
Linux, the choice of a GNU | Row, row, row your bits, gently down the
generation on a dual AMD | stream...
Athlon! |

Larry Wall

unread,
Jul 13, 2005, 6:03:32 PM7/13/05
to perl6-l...@perl.org
On Wed, Jul 13, 2005 at 05:48:47PM +0200, Ingo Blechschmidt wrote:
: If you wanted the compiler to parse SomeOtherModule.pm using Ruby's

: grammar, you'd have to write:
:
: use Grammar::Ruby;
: reuse SomeOtherModule

You'd also have to write "reuse", because we're not going to write it
for you, because we'd rather you just put "use Grammar::Ruby" in the
front of the other module instead of trying to force it implicitly
into a different language. On the other hand, if Grammar::Ruby also
modifies the file extension to look for, "reuse" might be the fastest
way to write a Ruby compiler. :-)

Larry

Autrijus Tang

unread,
Jul 13, 2005, 9:19:29 PM7/13/05
to perl6-l...@perl.org
On Tue, Jul 12, 2005 at 02:10:06PM -0700, Larry Wall wrote:
> Good, I'd forgotten about that. Which means that it's even harder
> for someone to compile a module in a "strange" dialect, since they'd
> essentially have to write their own version of "use" that forces
> recompilation ("reuse", if you will). And the harder we make it to
> write "reuse", the better.

Within perl 5, there is an extremely easy way to write that, namely
coderef in @INC that provides line-based filtering:

http://search.cpan.org/dist/Acme-use-strict-with-pride/pride.pm

Are we to discontinue use of coderef-in-@*INC, and switch to the
slightly more difficult but far more manageable approach of rebinding
&*require?

Thanks,
/Autrijus/

Michele Dondi

unread,
Jul 14, 2005, 5:08:05 AM7/14/05
to Ingo Blechschmidt, perl6-l...@perl.org
On Wed, 13 Jul 2005, Ingo Blechschmidt wrote:

> no, if I understood Larry correctly, you can of course write a nice
> grammar-modifying module, but other modules you use() still use
> Perl 6's standard grammar. E.g.:

Ah, then of course I would have never expected things to be different at
all.

> If you wanted the compiler to parse SomeOtherModule.pm using Ruby's
> grammar, you'd have to write:
>
> use Grammar::Ruby;
> reuse SomeOtherModule

So that, after all, I don't think it would be much used since if
SomeOtherModule was thought to be parsed according to Grammar::Ruby, it
would take care of using it in the first place, I guess.

Unless, of course, SomeOtherModule could be parsed correctly -and
hopefully behave differently- under two or more different grammars, in
which case it would be funny to see the effects of, say,

use Grammar::Ruby;
reuse SomeOtherModule;
use Grammar::hq9plus;
reuse SomeOtherModule;
# ...

which reminds me of good'ol' "GEB"...


Michele
--
Never attribute to malice that which
can be adequately explained by stupidity
- "Hanlon's Razor"

Larry Wall

unread,
Jul 14, 2005, 2:49:14 PM7/14/05
to perl6-l...@perl.org
On Thu, Jul 14, 2005 at 09:19:29AM +0800, Autrijus Tang wrote:
: Within perl 5, there is an extremely easy way to write that, namely

: coderef in @INC that provides line-based filtering:
:
: http://search.cpan.org/dist/Acme-use-strict-with-pride/pride.pm
:
: Are we to discontinue use of coderef-in-@*INC, and switch to the
: slightly more difficult but far more manageable approach of rebinding
: &*require?

I suppose that depends in part on whether we want to guarantee the
@INC interface for Perl 6 at all. Or it may be that we keep @INC but
make it point to abstract repositories rather than just directories.
And maybe some of those repositories have an interface with active
components. Or maybe @INC is a list of repository locating commands
with optional arguments. Maybe @INC is *all* closures that return
a package object or fail. Maybe @INC is just a fancy rule.

I dunno. Nobody's actually designed the library system yet. It would
be nice if it degenerated to a simple file lookup in list of a simple
directories, I suppose, since that's the current Perl-think, but
that doesn't mean we have to cap the abstraction at the top.

I suppose what it comes down to is that we'll still have @INC, and
allow closures in it, and probably pull in the standard library with
a closure that knows how to load standard modules efficiently. Whether
or not the standard library is represented by a closure in @INC, the
standard library needs to have some kind of placeholder in the list
so that users can put overrides in front of it or defaults in back of
it. Or @INC has to be split into a @PREINC plus @POSTINC, but a single
@INC seems simpler, and also allows multiple "standard" libraries, as
long as there's some way to name them.

Larry

Reply all
Reply to author
Forward
0 new messages