Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

My first functional perl6 program

8 views
Skip to first unread message

Mark J. Reed

unread,
Aug 23, 2006, 6:39:52 PM8/23/06
to perl6-l...@perl.org
To get my feet wet, I thought I'd translate my silly little cryptogram
helper. It turned out like this:


#!/usr/local/bin/pugs
#======================================================================
# Braindead cryptogram assistant with hard-coded key.
#----------------------------------------------------------------------
my %key =
(
a => 'f', b => 'o', e => 'n', f => 'w', g => 'd', h => 'a', j => 'm',
k => 'i', l => 's', m => 'l', n => 'c', o => 'g', q => 'r', r => 'h',
s => 'k', t => 'u', u => 'p', v => 't', w => 'j', x => 'e', y => 'v',
);


# Start by mapping all letters to question marks so the as-yet-undeciphered
# letters will stand out. Then add the letters from the key, making sure to
# get both lowercase and uppercase forms

my %trans = ('a'..'z') »=>« ('?' xx 26);

%trans{%key.keys.map({.lc,.uc})} = %key.values.map({.lc,.uc});

for =<> { say(.trans(%trans)) }


Surprisingly terse. I wonder if there a more elegant way to do that
hash assignment?

It was especially convenient that String#trans accepts a Hash for the
mapping; my Perl5 and Ruby versions also store the key in a hash, but
then use keys+join and values+join to get tr-friendly strings out of
it. This was much more natural.

(Speaking of which, pugs apparently doesn't have C<tr> as a global
function, only the .trans method)

It does sadden me somewhat that the say() requires the parens (or an
explicit $_ etc). But I'll live. :)

(The key above is for today's Order of the Stick, btw.)


--
Mark J. Reed <mark...@mail.com>

Mark J. Reed

unread,
Aug 23, 2006, 6:49:06 PM8/23/06
to perl6-l...@perl.org
On 8/23/06, Mark J. Reed <mark...@mail.com> wrote:
> my %trans = ('a'..'z') »=>« ('?' xx 26);

Also, correct me if I'm wrong, but I should theoretically be able to
use xx * there, thus creating a lazily-evaluated infinitely-long list
of question marks?

Larry Wall

unread,
Aug 23, 2006, 7:10:32 PM8/23/06
to perl6-l...@perl.org
On Wed, Aug 23, 2006 at 06:49:06PM -0400, Mark J. Reed wrote:
: On 8/23/06, Mark J. Reed <mark...@mail.com> wrote:
: >my %trans = ('a'..'z') »=>« ('?' xx 26);
:
: Also, correct me if I'm wrong, but I should theoretically be able to
: use xx * there, thus creating a lazily-evaluated infinitely-long list
: of question marks?

Yes, that should work eventually, given that hypers are supposed to stop
after the longest *finite* sequence. In theory you could even say

my %trans = ('a'..*) »=>« ('?' xx *);

but we haven't tried to define what the semantics of a lazy hash would be...

Larry

Larry Wall

unread,
Aug 23, 2006, 7:17:34 PM8/23/06
to perl6-l...@perl.org
On Wed, Aug 23, 2006 at 06:39:52PM -0400, Mark J. Reed wrote:
: It does sadden me somewhat that the say() requires the parens (or an

: explicit $_ etc). But I'll live. :)

Strange, this works for me:

$_ = "foo"; say .uc
FOO

Seems to work with .uc() as well.

Larry

Mark J. Reed

unread,
Aug 23, 2006, 7:30:23 PM8/23/06
to perl6-l...@perl.org
On 8/23/06, Larry Wall <la...@wall.org> wrote:
> Strange, this works for me:
>
> $_ = "foo"; say .uc
> FOO

Maybe that was fixed in 6.2.12, then. I'm still running 6.2.11, and
at least on Cygwin, I get this:

$ pugs -e '$_ = "foo"; say .uc'
$
No output. And if I try .trans:

$ pugs -e '$_ = "foo"; say .trans(o=>0)'
*** No compatible subrountine found: "&trans"
at -e line 1, column 13-31

But in any clase I'm glad it's merely an implementation bug rather
than specced behavior.

Luke Palmer

unread,
Aug 24, 2006, 2:09:44 AM8/24/06
to perl6-l...@perl.org
On 8/23/06, Larry Wall <la...@wall.org> wrote:
> Yes, that should work eventually, given that hypers are supposed to stop
> after the longest *finite* sequence.

Shudder xx *

What the hell does that mean!?

Let me posit this:

@a = 0..42;
@b = list_of_twin_primes();
(@a >>=><< @b).length;

Is it 43, or does it not terminate (as far as we can tell)?

If we are to use lazy lists powerfully, we must be allowed to not be
able to know whether they are finite. I would argue that we don't
make semantic distictions (other than eager) between lazy and non-lazy
lists, because I'm guessing that such distinctions will remove the
power of lazy lists. I like to use lists in Haskell because I know
what they are; I don't care if they have been pre-evaluated or are
being evaluated as I am using them, I am sure of the semantics either
way. I fear that if eager lists are given an elevated status in Perl
6, then I would be afraid to use lazy lists for anything other than
minor conveniences.

The way i would define hyper would be to stop after the shortest list
(also with zip). I know there are reasons not to do that, however, it
is easy to say:

(@a, 0 xx *) >>+<< @b

or

@a >>+<< @b[^@a]

It removes this lazy/nonlazy distinction, making semantics simpler and
more predictable. It removes the need for default values for
operators, and exchanges it for the request for the programmer to say
what he means. It removes the need for defaulting parameters in the
zip call, simplifying its semantics.

Mostly, though, it will allow me to use lazy lists like
list_of_twin_primes() without me worrying that it will be
discriminated against in my generic list code.

Luke

Mark J. Reed

unread,
Aug 24, 2006, 9:25:06 AM8/24/06
to Luke Palmer, perl6-l...@perl.org
I found your rant a bit long on vehemence and short on coherence,
Luke, but if I understand you correctly, your complaint is that this
is finite:

@finite_list >>=><< @infinite_list

while, according to S03, this is long:

@short_list >>=><< @long_list

e.g. q(a b) >>=><< (1,2,3,4) would return (a=>1, b=>2, undef=>3, undef=>4).

I agree that is a logical contradiction. Either the first should be
infinite, or the second should be short.

But I still don't understand your expressed incredulity about xx *. I
think it's perfectly clear what that means. Fpr example, $foo xx *
creates a(n infinite) list which contains $foo at every position no
matter how high a position you ask for . . .

Mark J. Reed

unread,
Aug 24, 2006, 9:33:56 AM8/24/06
to Luke Palmer, perl6-l...@perl.org
On 8/24/06, Mark J. Reed <mark...@mail.com> wrote:
> e.g. q(a b) >>=><< (1,2,3,4) would return (a=>1, b=>2, undef=>3, undef=>4).

or rather, it would if I'd typed qw(a b) as I intended.

One other point: while I agree that we should shield the programmer as
much as possible from having to care whether a list is finite or not,
some things cannot be helped; for instance, calling .length on an
infinite list is going to be a bad idea no matter what...

Luke Palmer

unread,
Aug 24, 2006, 11:19:10 AM8/24/06
to Mark J. Reed, perl6-l...@perl.org
On 8/24/06, Mark J. Reed <mark...@mail.com> wrote:
> I found your rant a bit long on vehemence and short on coherence,
> Luke, but if I understand you correctly, your complaint is that this
> is finite:
>
> @finite_list >>=><< @infinite_list
>
> while, according to S03, this is long:
>
> @short_list >>=><< @long_list

Precisely.

> But I still don't understand your expressed incredulity about xx *. I
> think it's perfectly clear what that means. Fpr example, $foo xx *
> creates a(n infinite) list which contains $foo at every position no
> matter how high a position you ask for . . .

Ahh, that wasn't a complaint about xx *. I was shuddering an infinite
number of times.

Luke

Larry Wall

unread,
Aug 24, 2006, 2:33:58 PM8/24/06
to perl6-l...@perl.org
On Thu, Aug 24, 2006 at 12:09:44AM -0600, Luke Palmer wrote:
: The way i would define hyper would be to stop after the shortest list

: (also with zip). I know there are reasons not to do that, however, it
: is easy to say:
:
: (@a, 0 xx *) >>+<< @b
:
: or
:
: @a >>+<< @b[^@a]

Well, now that we have *, it does tilt the equation differently. We could
perhaps even allow * at the end of a list to expand to "* xx *" or some such.
It would make it easy to say when you don't care if the list is short:

(@a, *) >>+<< @b

Always presuming that + does something sane with *, of course.

With that I could probably be argued into stop-at-shortest semantics,
though I do wish there were an easy way to detect two lists that
weren't conformant. I hate forgetting things accidentally. Hmm,
if the standard + doesn't deal with Whatever, you get an error when
it hits one, but in a lexical scope you can define a "my multi" that
says how to handle a Whatever. Not sure if that's the right default
though--it doesn't actually detect non-conformant lists unless you
put * on the shorter one. We could check for conformance only on
lists that are known to be finite and assume the rest are infinite.

Or, as with the reduce ops, maybe we just need a hyperop variant like >>\+<<.
Presumably it'd be the variant that enforces conformance, so you have to
ask for it. Definitely needs more thought, though...

Larry

John Macdonald

unread,
Aug 25, 2006, 10:40:21 AM8/25/06
to perl6-l...@perl.org
On Wed, Aug 23, 2006 at 04:10:32PM -0700, Larry Wall wrote:
> Yes, that should work eventually, given that hypers are supposed to stop
> after the longest *finite* sequence. In theory you could even say
>
> my %trans = ('a'..*) »=>« ('?' xx *);
>
> but we haven't tried to define what the semantics of a lazy hash would be...

That's a rather large hazard. %trans{$key} would run until
the lazy hash is extended far enough to determine whether
$key is ever matched as a key - and that could easily mean
trying forever. So, it is only safe to use the hash for
keys that you *know* are in the domain; or, if the lazy
key generation is simple enough, keys that you *know* can
be excluded in a finite amount of time. (I'm assuming that
1 ~~ any( 5..* ) will be smart enough to return false.)

--

0 new messages