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.
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.
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. :-)
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.
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. .
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?
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...)
> 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 ( ... ) { ... }
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..
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.