aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--challenge-062/markus-holzer/raku/ch-1.raku81
1 files changed, 48 insertions, 33 deletions
diff --git a/challenge-062/markus-holzer/raku/ch-1.raku b/challenge-062/markus-holzer/raku/ch-1.raku
index 550eecea7d..a2207abf11 100644
--- a/challenge-062/markus-holzer/raku/ch-1.raku
+++ b/challenge-062/markus-holzer/raku/ch-1.raku
@@ -1,43 +1,58 @@
+# This should really follow the spec or use something from CPAN
class Mail
{
- has Str $.adress;
- has Str $.domain;
- has Str $.mailbox;
- has Str $.norm;
-
- submethod TWEAK( :$!adress )
- {
- my $index = $!adress.index: '@';
-
- $!mailbox = $!adress.substr( 0, $index );
- $!domain = $!adress.substr( $index + 1, * ).lc;
- $!norm = $!mailbox ~ '@' ~ $!domain;
- }
+ has Str $.address;
+ has Str $.domain;
+ has Str $.mailbox;
+ has Str $.norm;
+ has Bool $.valid;
+
+ method Str { $!address }
+
+ submethod TWEAK( :$!address )
+ {
+ my $index = $!address.index: '@';
+ return unless $index && 0 < $index < $!address.chars - 1;
+
+ $!mailbox = $!address.substr: 0, $index;
+ $!domain = lc $!address.substr: $index + 1, *;
+ $!norm = $!mailbox ~ '@' ~ $!domain;
+ $!valid = True;
+ }
+}
- method gist() {
- $.norm }
+subset FileIsReadable where { .IO.f && .IO.e && .IO.r }
+subset FilesAreReadable where { .all ~~ FileIsReadable }
- method Str() {
- $.adress }
-}
+#| read from files
+multi sub MAIN(
+ Bool :$u, #= unique. filters duplicates
+ *@files where FilesAreReadable #= files containing email addresses, 1 per line
+) {
+ output-email-addresses $u, sort-mail-addresses @files.map: *.IO.open( :r ) }
-multi sub MAIN( :$u ) {
- output-email-adresses $u, sort-mail-adresses $*IN }
+#| read from STDIN
+multi sub MAIN( Bool :$u ) {
+ output-email-addresses $u, sort-mail-addresses $*IN }
-multi sub MAIN( :$u, *@args ) {
- output-email-adresses $u, sort-mail-adresses @args.map: *.IO.open( :r ) }
+# catch bad arguments
+multi sub MAIN( Bool :$u?, *@bad ) is hidden-from-USAGE {
+ $*USAGE.say }
-sub output-email-adresses( $unique, @things ) {
- .Str.say for $unique ?? @things.unique( :as( *.norm ) ) !! @things }
+sub output-email-addresses( $unique, @addresses ) {
+ .address.say for $unique
+ ?? @addresses.squish( as => *.norm )
+ !! @addresses }
-sub sort-mail-adresses( *@handles )
+multi sub sort-mail-addresses( $handles where { .cache.all ~~ IO::Handle } )
{
- my &adress = -> $adress { Mail.new( :$adress ) };
- my &sort = -> $a, $b { $a.domain cmp $b.domain || $a.mailbox cmp $b.mailbox };
-
- @handles
- .map( *.lines )
- .flat
- .map( &adress )
- .sort( &sort )
+ my &address = -> $address { Mail.new( :$address ) }
+ my &valid = -> $mail { $mail.valid || $*ERR.say("Bad data <$mail>") && False }
+ my &sort = -> $a, $b { $a.domain cmp $b.domain || $a.mailbox cmp $b.mailbox }
+
+ $handles
+ .map( | *.lines )
+ .map( &address )
+ .grep( &valid )
+ .sort( &sort )
} \ No newline at end of file