Comma in (sub) traits?

6 views
Skip to first unread message

Wolverian

unread,
Mar 7, 2005, 5:55:49 AM3/7/05
to perl6-l...@perl.org
Hello all,

while writing some experimental code with Pugs, I realised that it is a
bit hard for me to parse the following type of declaration:

sub greeting (Str $person) returns Str is export {
"Hello, $person"
}

Specifically, the 'is export' trait is too buried. Reformatting it like
this helps:

sub greeting (Str $person)
returns Str is export {
"Hello, $person"
}

But I really do not like the vertical alignment of the traits and the
body of the sub. So we're back to the first situation. We could also put
the 'returns' on the first line, after the signature (and strictly
speaking it at least can be a part of the signature), and the traits on
successive lines after that, but the alignment problems kicks in again.

There are other ways to format the declaration, like indenting the
traits line:

sub greeting (Str $person) returns Str
is export {
"Hello, $person"
}

This looks distinctly odd to me, although I think it works better than
the aligned version. Moving the traits line to column 0 is even weirder.

I think it is clear that I do not want to put the { on its own line. :)

The problem can be alleviated a bit by giving each trait a more
separable visual identity:

sub greeting (Str $person) returns Str, is export {
"Hello, $person"
}

The above works better for me than either of the previous examples. So
my question is: can this be legal Perl 6 code (and will it DWIM)? There
are ways to format this I didn't think of, I'm sure, so I'd like to know
too what the recommended style is. (perl6doc perlstyle...)

This same problem (well, it is a problem to me) applies to other places
where traits are used as well, but I'm specifically asking in the
context of named subroutine declarations, since parsing the comma seems
at least possible there. The visual distinction in a regular 'my'
declaration brought by the comma might also look too much like a list.
(It probably is a list.)

Sorry if this has been discussed before, or even in the design
documents. I'm also sorry if this is too rambling for the list. It's not
that important, just a thought.

Cheers,
wolverian

signature.asc

Aldo Calpini

unread,
Mar 7, 2005, 9:43:19 AM3/7/05
to wolverian, perl6-l...@perl.org
wolverian wrote:
> Hello all,
>
> while writing some experimental code with Pugs, I realised that it is a
> bit hard for me to parse the following type of declaration:
>
> sub greeting (Str $person) returns Str is export {
> "Hello, $person"
> }

don't know if it helps, but I guess that you can also write it like
this, if you prefer:

sub greeting(Str $person) {
returns Str;
is export;
"Hello, $person";
}

(this guess is based on something I recall having read in A12 about
classes; if my guess is wrong, I'll be happy to stand corrected :-).

cheers,
Aldo

Thomas Sandlaß

unread,
Mar 7, 2005, 9:26:59 AM3/7/05
to wolverian, perl6-l...@perl.org
wolverian wrote:
> There are other ways to format the declaration, like indenting the
> traits line:

Yes, I like:
sub greeting( Str $person )


returns Str
is export
{
"Hello, $person"
}

With the sub-line as some kind of intro and the block as the terminator.
A longer signature would be aligned after the opening paren---and along
the zone markers.

Regards,
--
TSa (Thomas Sandlaß)

Larry Wall

unread,
Mar 7, 2005, 11:40:19 AM3/7/05
to perl6-l...@perl.org
On Mon, Mar 07, 2005 at 12:55:49PM +0200, wolverian wrote:
: Hello all,

:
: while writing some experimental code with Pugs, I realised that it is a
: bit hard for me to parse the following type of declaration:
:
: sub greeting (Str $person) returns Str is export {
: "Hello, $person"
: }
:
: Specifically, the 'is export' trait is too buried.

Here are some alternatives you don't seem to have considered:

sub greeting (Str $person) is export returns Str {
"Hello, $person";
}

sub greeting (Str $person) is export
returns Str {
"Hello, $person";
}

sub greeting (Str $person)
is export
returns Str {
"Hello, $person";
}

sub greeting (Str $person)
returns Str
is export {

"Hello, $person";
}

my Str sub greeting (Str $person) is export {
"Hello, $person";
}

my Str
sub greeting (Str $person) is export {
"Hello, $person";
}

: Reformatting it like this helps:


:
: sub greeting (Str $person)
: returns Str is export {
: "Hello, $person"
: }
:
: But I really do not like the vertical alignment of the traits and the
: body of the sub. So we're back to the first situation. We could also put
: the 'returns' on the first line, after the signature (and strictly
: speaking it at least can be a part of the signature), and the traits on
: successive lines after that, but the alignment problems kicks in again.
:
: There are other ways to format the declaration, like indenting the
: traits line:
:
: sub greeting (Str $person) returns Str
: is export {
: "Hello, $person"
: }
:
: This looks distinctly odd to me, although I think it works better than
: the aligned version. Moving the traits line to column 0 is even weirder.
:
: I think it is clear that I do not want to put the { on its own line. :)

That's how I started out in C, and then eventually mutated to a form
in which I put the { on its own line only if I had multiple lines in
the signature. In that case I decided the consistency was overrated.
I basically do the same with any bracketing construct now--if the front
stuff rates more than one line, then I pull the brack out front on its
own line, and not otherwise. It seems the least insane approach to me,
but I realize the inconsistency will bug some people more than others.

Anyway, this policy works for me, and for more than just sigs--it makes
it possible to split up the parameters when they are long and
complex, so I can happily write anything from

sub Foo foo (Bar $bar) is export {
...
}

to

method foo ( $self:
$odd returns Int where { $_ % 1 },
$even return Int where { not $_ % 1 },
Block ?&permutator,
*@list
)
returns Footype
is good
is bad
is ugly
{
...
}

or maybe

method foo ( $self:
$odd returns Int where { $_ % 1 },
$even return Int where { not $_ % 1 },
Block ?&permutator,
*@list )
returns Footype
is good
is bad
is ugly
{
...
}

Well, that's not exactly pretty, but I figure that if you've blown
that many lines on the signature, another line for the opening curly
isn't that much, and makes it visually easy to find where the code
actually starts. Anyway, I think it's more important to have a style
that can mutute from horizontal to vertical form than it is to have
a consistent style.

: The problem can be alleviated a bit by giving each trait a more


: separable visual identity:
:
: sub greeting (Str $person) returns Str, is export {
: "Hello, $person"
: }
:
: The above works better for me than either of the previous examples. So
: my question is: can this be legal Perl 6 code (and will it DWIM)? There
: are ways to format this I didn't think of, I'm sure, so I'd like to know
: too what the recommended style is. (perl6doc perlstyle...)
:
: This same problem (well, it is a problem to me) applies to other places
: where traits are used as well, but I'm specifically asking in the
: context of named subroutine declarations, since parsing the comma seems
: at least possible there. The visual distinction in a regular 'my'
: declaration brought by the comma might also look too much like a list.
: (It probably is a list.)

Yes, that's the basic problem with comma, and the declaration of traits
on "my" and "sub" is one thing I *would* like to keep consistent. I'm
not consistent about consistency, you see, except when I am...

And I try to believe six foolish consistencies before breakfast each day. :-)

Larry

Larry Wall

unread,
Mar 7, 2005, 11:44:14 AM3/7/05
to perl6-l...@perl.org
On Mon, Mar 07, 2005 at 08:27:10AM -0800, David Storrs wrote:
: On Mon, Mar 07, 2005 at 03:43:19PM +0100, Aldo Calpini wrote:
:
: > don't know if it helps, but I guess that you can also write it like
: > this, if you prefer:
: >
: > sub greeting(Str $person) {
: > returns Str;
: > is export;
: > "Hello, $person";
: > }
: >
: > (this guess is based on something I recall having read in A12 about
: > classes; if my guess is wrong, I'll be happy to stand corrected :-).
:
: On reflection, I see why that probably works. I also pray that I
: never have to maintain code that uses it, because it seems very
: misleading. .

Yes, and it wouldn't work at all if you ever wanted to autoload anything.
If we ever get to where we're autoloading class bodies, they'd have the
same problem with embedded declarations. The compiler can't work with
information that isn't there.

Larry

David Storrs

unread,
Mar 7, 2005, 11:27:10 AM3/7/05
to perl6-l...@perl.org
On Mon, Mar 07, 2005 at 03:43:19PM +0100, Aldo Calpini wrote:

> don't know if it helps, but I guess that you can also write it like
> this, if you prefer:
>
> sub greeting(Str $person) {
> returns Str;
> is export;
> "Hello, $person";
> }
>
> (this guess is based on something I recall having read in A12 about
> classes; if my guess is wrong, I'll be happy to stand corrected :-).

On reflection, I see why that probably works. I also pray that I


never have to maintain code that uses it, because it seems very
misleading. .

--Dks
--
dst...@dstorrs.com

Thomas Sandlaß

unread,
Mar 7, 2005, 11:53:23 AM3/7/05
to Larry Wall, perl6-l...@perl.org
Larry Wall wrote:
> Yes, and it wouldn't work at all if you ever wanted to autoload anything.
> If we ever get to where we're autoloading class bodies, they'd have the
> same problem with embedded declarations. The compiler can't work with
> information that isn't there.

This is something that is blurry to me: how does one separate declaration
and implementation. It is clear that a declaration has got a {...} block
and an implementation doesn't. But does that mean that there are package
files that function like header files in C++ or like interface files in
Ada and Modula?

Or does that work more like Cecil signature declarations which can be
spread out as needed and actually express a callers expectations which
can be matched with the implementation side?

MfG
--
TSa (Thomas Sandlaß)


Larry Wall

unread,
Mar 7, 2005, 12:38:49 PM3/7/05
to perl6-l...@perl.org
On Mon, Mar 07, 2005 at 05:53:23PM +0100, Thomas Sandlaß wrote:
: Larry Wall wrote:
: >Yes, and it wouldn't work at all if you ever wanted to autoload anything.
: >If we ever get to where we're autoloading class bodies, they'd have the
: >same problem with embedded declarations. The compiler can't work with
: >information that isn't there.
:
: This is something that is blurry to me: how does one separate declaration
: and implementation. It is clear that a declaration has got a {...} block
: and an implementation doesn't. But does that mean that there are package
: files that function like header files in C++ or like interface files in
: Ada and Modula?

In theory, yes, though I would hope more like Ada than C++. #include
is a rotten way to do business. The idea of Perl's "use" is that you're
essentially calling a subroutine in the package that gives you as much
of the definition as you need. The fact that it might define a whole bunch
of other stuff at the same time is immaterial to you. As in happens,
it might have already been declared by a previous "use", as well as later
in a lazy fashion. It's really the import function that is managing the
interface though. The import mechanism might be different in Perl 6, but
the underlying idea that you execute real Perl code to define things
is certainly going to carry over from Perl 5.

: Or does that work more like Cecil signature declarations which can be


: spread out as needed and actually express a callers expectations which
: can be matched with the implementation side?

I am not familiar with Cecil, but in Perl 6 caller expectations
are primarily expressed through the actual types you feed to MMD.
If the compiler can figure out more based on your own declarations,
that's fine, but the bias is definitely toward late binding.

I suppose if a user defines an normal inner sub that redispatches to
an outer set of multi subs, it functions a bit like a user-defined
expectation. We don't currently have a way of directly mapping a set
of inner multis to a set of outer multies without going through an
interposed non-multi.

We also give a bit of user-defined interface control in letting the user
tell the module which version it wants to act like. In the degenerate
case, that means it just picks the right file, but we should recognize
that the version we specify in a use is maybe an interface version, and
multiple interfaces could be served up by a single back-end implementation.
That approach might help with resource collisions between different versions
of the same module.

Beyond that, we provide the user with aliasing and delegation and
wrappers, at least on a sub/method level. But given that all code
that executes is a sub on some level, there can probably hooks to
wrap classes and modules too, if ordinary inheritance, composition,
and delegation aren't up to the task. But at some point you just
give up and call it cheating, er, I mean, AOP. :-)

Basically, once you realize the compiler is not longer doing the
compilation, but just helping the program compile itself by running
odd bits of code here and there, the door is open to turn Perl into
any other language you like. The only question is what discipline
the culture will enforce around the complete mayhem that is possible.
It is at this point that I am placing my trust in the Perl community.
(But then, my definition of "community" is somewhat Darwinian...)

Larry

Juerd

unread,
Mar 7, 2005, 12:24:08 PM3/7/05
to Larry Wall, perl6-l...@perl.org
Larry Wall skribis 2005-03-07 8:40 (-0800):
> method foo ($self: $odd returns Int where { $_ % 1 }, $even

> return Int where { not $_ % 1 }, Block ?&permutator, *@list)
> returns Footype is good is bad is ugly { ... }

That someone took the time to bring this up pleases me. I'm very strict
when it comes to indenting and what I find most readable and thus
prefer. Of course, everyone should have their own style and there's no
shame in having something that some consider ugly. Still, for my own
code, I wish to keep things the way they are.

I indent in two situations. The first is continuation of a statement,
when things don't fit in 80 characters. I try to do this after an infix
operator, or before it if the infix operator is or/and/xor/||/$$/->. The
only thing changing there is the addition of ^^, // and err. And of
course that -> is now spelled ..

The second place where I allow myself to indent is within nested
brackets, or sometimes some other circumfix delimiter. If an { belongs
to a certain control statement, it should not have its own line. If any
newline is in the delimiters, even the first and last elements in them
should be on their own lines.

Indentation is always 4 columns. Never 8, never 2. The only exception is
vertical alignment. Outdents exist only to naturally end indentation.

Subs are a problem in Perl 6, because their declaration can be very long
and easily span multiple lines.

With my current "rules", I'd end up with

method foo (
$self:
$odd returns Int where ...,
$even returns Int where ...,


Block ?&permutator,
*@list
) returns Footype is good is bad is ugly {
...
}

The { is not really on the same line as "method", but at least it's not
on its own.

But it is indeed hard to parse a list of things that have no well
visible separator. I could break my one-space-max rule:

method foo (
$self:
$odd returns Int where ...,
$even returns Int where ...,


Block ?&permutator,
*@list
) returns Footype is good is bad is ugly {
...
}

But that feels like there really are commas, but they were made
invisible. I could also break my continued-lines-are-indented rule:

method foo (
$self:
$odd returns Int where ...,
$even returns Int where ...,


Block ?&permutator,
*@list
)
returns Footype
is good
is bad
is ugly {
...
}

But then, the other way around is prettier:

method foo


returns Footype
is good
is bad

is ugly (
$self:
$odd returns Int where ...,
$even returns Int where ...,
Block ?&permutator,
*@list
) {
...
}

Not that I like ") {", but I'm used to seeing it from Perl 5's if. This
makes "method foo" look much less important than it is. But with
indentation, the block is no longer clearly visible:

method foo


returns Footype
is good
is bad

is ugly (
$self:
$odd returns Int where ...,
$even returns Int where ...,
Block ?&permutator,
*@list
) {
...
}

Or { needs to go on its own line, which really disturbs me if the { is
not the beginning of a term. And this style is wrong because either ()
or {} need to not line up.

The thing missing is indeed the comma. Looking for other places where
comma is "missing", I thought of qw, or its new <> variant. Isn't the
following a neat solution for the problem we're faced with?

method foo (
$self:
$odd returns Int where ...,
$even returns Int where ...,
Block ?&permutator,
*@list
) returns Footype, is <good bad ugly> {
...
}

Okay, I cheated by still adding a comma. How about allowing this then:

method foo (
$self:
$odd returns Int where ...,
$even returns Int where ...,
Block ?&permutator,
*@list
) :returns<Footype> :is<good bad ugly> {
...
}

I'm not sure what to think of my own suggestion. I find this neat and
ugly at the same time. Ugly, because now something that used to be
barewordish/keywordish now feels like strings, beatiful because it solves
a problem, neat because it's syntax that exists elsewhere too.

I think allowing comma or finding another character that can replace it
is the best option, but I think we're low on ASCII characters. Backticks
can be beatiful, but not for this :)

Hm, infix +? If I understand things correctly, it's invalid in the
current design anyway. It communicates that things all belong together,
but it looks really weird:

method foo + returns Footype + is good + is bad + is ugly

And it really screams for allowing different order:

is good + returns Footype + method foo + is bad + is ugly

So that is probably not a good idea. Infix & has the same advantage and
disadvantage. The obvious characters, comma, and semicolon are out of
the question because of my/our/has. But could ~ work? I know they're not
strings, but string concatenation doesn't make sense in this syntactical
context anyway.

method foo ~ returns Footype ~ is good ~ is bad ~ is ugly (
...
) {
...
}

This can even serve as a visual indentation without really indenting if
you put them all on their own lines:

method foo
~ returns Footype
~ is good
~ is bad
~ is ugly (
...
) {
...
}

And it doesn't look bad after the signature either:

method foo (
...
) returns Footype ~ is good ~ is bad ~ is ugly {
...
}

But this works only for verticality if they're allowed between signature
and traits too:

method foo (
...
)
~ returns Footype
~ is good
~ is bad
~ is ugly {
...
}

I like the previous better, though:

method foo
~ returns Footype
~ is good
~ is bad
~ is ugly (
...
) {
...
}


Juerd
--
http://convolution.nl/maak_juerd_blij.html
http://convolution.nl/make_juerd_happy.html
http://convolution.nl/gajigu_juerd_n.html

Wolverian

unread,
Mar 9, 2005, 7:15:56 AM3/9/05
to perl6-l...@perl.org
On Mon, Mar 07, 2005 at 08:40:19AM -0800, Larry Wall wrote:
> Here are some alternatives you don't seem to have considered:

[...]

> my Str sub greeting (Str $person) is export {
> "Hello, $person";
> }
>
> my Str
> sub greeting (Str $person) is export {
> "Hello, $person";
> }

Do these declare the subroutine in the lexical scope only?

> And I try to believe six foolish consistencies before breakfast each day. :-)

I'm glad you do! I value consistency a lot, but I do realise one has to
choose the _right_ consistencies.

Anyway, thanks for replying. I think I can live with the issue. :) It seems to
center on the fact that Perl 6 allows you to put a lot of stuff into the
signature. This isn't helped much by any potential Haskell-style pattern
matching, at least not in a way I can see.

I still do want to match against constants in the signature, however:

sub foo ( 0 ) { ... }
sub foo ( $bar ) { ... }

So I'm very confused about my opinion on the issue of pattern matching..

> Larry

--
wolverian

signature.asc

Larry Wall

unread,
Mar 9, 2005, 12:13:27 PM3/9/05
to perl6-l...@perl.org
On Wed, Mar 09, 2005 at 02:15:56PM +0200, wolverian wrote:

: On Mon, Mar 07, 2005 at 08:40:19AM -0800, Larry Wall wrote:
: > Here are some alternatives you don't seem to have considered:
:
: [...]
:
: > my Str sub greeting (Str $person) is export {
: > "Hello, $person";
: > }
: >
: > my Str
: > sub greeting (Str $person) is export {
: > "Hello, $person";
: > }
:
: Do these declare the subroutine in the lexical scope only?

Yes, but if you're exporting the sub, references to it are potentially
escaping the lexical scope.

: > And I try to believe six foolish consistencies before breakfast each day. :-)


:
: I'm glad you do! I value consistency a lot, but I do realise one has to
: choose the _right_ consistencies.
:
: Anyway, thanks for replying. I think I can live with the issue. :) It seems to
: center on the fact that Perl 6 allows you to put a lot of stuff into the
: signature. This isn't helped much by any potential Haskell-style pattern
: matching, at least not in a way I can see.
:
: I still do want to match against constants in the signature, however:
:
: sub foo ( 0 ) { ... }
: sub foo ( $bar ) { ... }
:
: So I'm very confused about my opinion on the issue of pattern matching..

Well that's just shorthand for:

sub foo ( Int $bar where { $_ == 0 } ) { ... }


sub foo ( $bar ) { ... }

except, of course, you'd have to mark them both as "multi" before you
get MMD. As it is, you'll get a warning about redefinition.

Larry

Larry Wall

unread,
Mar 9, 2005, 12:19:17 PM3/9/05
to perl6-l...@perl.org
On Wed, Mar 09, 2005 at 09:13:27AM -0800, Larry Wall wrote:
: sub foo ( Int $bar where { $_ == 0 } ) { ... }

Well, I'm not sure about that syntax. It might have to be either

sub foo ( Int where { $_ == 0 } $bar ) { ... }

or

sub foo ( $bar of Int where { $_ == 0 } $bar ) { ... }

But if even I fall into that syntactic trap, maybe we'll end up allowing
it as a special DWIM case.

Larry

Reply all
Reply to author
Forward
0 new messages