[32218] in Perl-Users-Digest

home help back first fref pref prev next nref lref last post

Perl-Users Digest, Issue: 3483 Volume: 11

daemon@ATHENA.MIT.EDU (Perl-Users Digest)
Mon Aug 29 09:09:27 2011

Date: Mon, 29 Aug 2011 06:09:07 -0700 (PDT)
From: Perl-Users Digest <Perl-Users-Request@ruby.OCE.ORST.EDU>
To: Perl-Users@ruby.OCE.ORST.EDU (Perl-Users Digest)

Perl-Users Digest           Mon, 29 Aug 2011     Volume: 11 Number: 3483

Today's topics:
    Re: aolutions to the world's big probs <tadmc@seesig.invalid>
    Re: how do I create a hash from the list <tzz@lifelogs.com>
    Re: Loading to Memory <tzz@lifelogs.com>
    Re: Loading to Memory <rvtol+usenet@xs4all.nl>
    Re: Loading to Memory <grahn+nntp@snipabacken.se>
    Re: Loading to Memory <rvtol+usenet@xs4all.nl>
        My code works but is clunky and inelegant; help to impr <news@lawshouse.org>
    Re: My code works but is clunky and inelegant; help to  <tadmc@seesig.invalid>
    Re: My code works but is clunky and inelegant; help to  <news@lawshouse.org>
    Re: My code works but is clunky and inelegant; help to  <willem@toad.stack.nl>
    Re: My code works but is clunky and inelegant; help to  <hjp-usenet2@hjp.at>
    Re: My code works but is clunky and inelegant; help to  <news@lawshouse.org>
    Re: My code works but is clunky and inelegant; help to  <tadmc@seesig.invalid>
    Re: My code works but is clunky and inelegant; help to  <news@lawshouse.org>
        traversing a hash structure <ela@yantai.org>
    Re: traversing a hash structure <news@lawshouse.org>
        Digest Administrivia (Last modified: 6 Apr 01) (Perl-Users-Digest Admin)

----------------------------------------------------------------------

Date: Fri, 26 Aug 2011 06:56:09 -0500
From: Tad McClellan <tadmc@seesig.invalid>
Subject: Re: aolutions to the world's big probs
Message-Id: <slrnj5f1tc.s15.tadmc@tadbox.sbcglobal.net>

robin <r@thevoid1.net> wrote:

> I think


Sure you do.


-- 
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.


------------------------------

Date: Fri, 26 Aug 2011 09:17:17 -0500
From: Ted Zlatanov <tzz@lifelogs.com>
Subject: Re: how do I create a hash from the list
Message-Id: <87ty94p89e.fsf@lifelogs.com>

On Thu, 25 Aug 2011 14:23:05 -0700 (PDT) James <hslee911@yahoo.com> wrote: 

J> Generally speaking,

J> @a = qw/aa 1 bb 2 cc 3 dd 4/;
J> @b = map {$_%2?"":$_} 0..$#a;
J> %h = map {$a[$_] => $a[$_+1]} @b;
J> print "$_=>$h{$_}\n" for sort keys %h;

J> You get,
J> aa=>1
J> bb=>2
J> cc=>3
J> dd=>4

That's not general, readable, or correct.  As Uri said you can simply
assign the first qw// you gave to a hash and it Just Works.  But consider

%a = qw/aa 1 bb 2 cc 3 dd 4 aa 5/;

Is the 'aa' key 1 or 5?  Your approach has the same flaw, it will wipe
the 'aa' key.

My suggestion, which you perhaps quoted without understanding it
completely, ends up with

# preserve all elements in order
%a = ( aa => [ 1, 5 ], bb => [ 2 ], cc => [ 3 ], dd => [ 4 ] );

or with

# preserve element frequencies (they are all 1 here)
%a = ( aa => { 1 => 1, 5 => 1 }, bb => ( 2 => 1 ), cc => ( 3 => 1 ), dd => ( 4 => 1 ) );

which are both useful depending on the need.  Also see Hash::Merge on
CPAN for a general solution to this well-known data structure problem.

Ted


------------------------------

Date: Fri, 26 Aug 2011 09:09:38 -0500
From: Ted Zlatanov <tzz@lifelogs.com>
Subject: Re: Loading to Memory
Message-Id: <87y5ygp8m5.fsf@lifelogs.com>

On Thu, 25 Aug 2011 15:31:55 -0700 (PDT) hillgoogle@charter.net wrote: 

h> Thanks all. Specifically, I'm looking at getting output from Memory
h> instaed of a DB because memory is volatile and I it read it faster.
h> So ... I would insert data from my DB (mysql) and then my app would
h> read data NOT from the DB, but the memory. Right, when the machine
h> went down I would re-load to memory, or when I had updates from the
h> DB.

h> @Tobias ... I'll look at those links, ty!

h> @Others ... Anything else?

As Tobias suggested memcached is your best bet today IMHO.  It's
extremely easy to install, configure, use locally and remotely, and
understand.  I've used it in production with 16GB of memory allocated to
it (specialized status monitoring application) and it has performed
flawlessly *without a restart*, no memory leaks or any other issues for
almost a year or continuous usage.

Ted


------------------------------

Date: Sat, 27 Aug 2011 19:52:05 +0200
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: Loading to Memory
Message-Id: <4e592ec5$0$2431$e4fe514c@news2.news.xs4all.nl>

On 2011-08-25 00:49, hillgoogle@charter.net wrote:

> On my unix box I want to load some data into memory using one program
> and then retrieve it using another.
>
> Anyone have any examples of how I can load that to my unix machine
> memory?

Check out CHI, which is in the Task::Kensho list.

http://search.cpan.org/perldoc?CHI
http://search.cpan.org/perldoc?Task::Kensho

-- 
Ruud



------------------------------

Date: 27 Aug 2011 20:05:16 GMT
From: Jorgen Grahn <grahn+nntp@snipabacken.se>
Subject: Re: Loading to Memory
Message-Id: <slrnj5ijfr.gtj.grahn+nntp@frailea.sa.invalid>

On Thu, 2011-08-25, hillgoogle@charter.net wrote:
> Thanks all. Specifically, I'm looking at getting output from Memory
> instaed of a DB because memory is volatile and I it read it faster.
> So ... I would insert data from my DB (mysql) and then my app would
> read data NOT from the DB, but the memory. Right, when the machine
> went down I would re-load to memory, or when I had updates from the
> DB.

All of that is the job of the database software (and it might delegate
that work to the OS, which caches disk accesses in memory).

If you have nothing better to do, and you know that in a few seconds
you will want to access some part of the database, it *might* make
sense to do "dummy reads" from the database, or perhaps a
"cat the_database_file >/dev/null".  Or it might not.

/Jorgen

-- 
  // Jorgen Grahn <grahn@  Oo  o.   .     .
\X/     snipabacken.se>   O  o   .


------------------------------

Date: Sun, 28 Aug 2011 12:00:50 +0200
From: "Dr.Ruud" <rvtol+usenet@xs4all.nl>
Subject: Re: Loading to Memory
Message-Id: <4e5a11d2$0$2456$e4fe514c@news2.news.xs4all.nl>

On 2011-08-27 22:05, Jorgen Grahn wrote:
> On Thu, 2011-08-25, hillgoogle@charter.net wrote:

>> Thanks all. Specifically, I'm looking at getting output from Memory
>> instaed of a DB because memory is volatile and I it read it faster.
>> So ... I would insert data from my DB (mysql) and then my app would
>> read data NOT from the DB, but the memory. Right, when the machine
>> went down I would re-load to memory, or when I had updates from the
>> DB.
>
> All of that is the job of the database software (and it might delegate
> that work to the OS, which caches disk accesses in memory).
>
> If you have nothing better to do, and you know that in a few seconds
> you will want to access some part of the database, it *might* make
> sense to do "dummy reads" from the database, or perhaps a
> "cat the_database_file>/dev/null".  Or it might not.

A hot database is indeed often much faster than a cold one. Further make 
sure that you added the right indexes, and are using the proper storage 
engine (like InnoDB vs. MyISAM).

The MySQL way for "cat the_database_file>/dev/null" is 'CHECKSUM TABLE 
mytable'. If the number of concurrent users is normally less than 20, 
consider using SQLite.

If you have popular big queries with big result sets, also look into 
tuning the query cache settings. And look into replication, to do all 
reading from a slave.

-- 
Ruud


------------------------------

Date: Fri, 26 Aug 2011 11:35:44 +0100
From: Henry Law <news@lawshouse.org>
Subject: My code works but is clunky and inelegant; help to improve it?
Message-Id: <jtOdnf8Moqec6srTnZ2dnUVZ8k-dnZ2d@giganews.com>

I have written some code which takes the body of a message in RFC2646 
format (format=flowed) and generates the appropriate HTML for it to 
render in the mail-archiving system I'm writing.

It works, but every time I look at the code it offends me: it's clunky 
and even I as a novice Perl programmer can see that it is not Perl-ish. 
  Is there anyone with the time and the inclination to comment on the 
way I've coded the algorithm (or indeed the algorithm itself) to help me 
make it better?  I'm particularly offended by having to use the switch 
$para to keep track of whether I've opened a <p> already so I have to 
close it with </p>; apart from that there just seems to be too much 
fiddling around.

(BTW I've considered Text::Flowed and Text::Linefold; neither provides 
any assistance).

To sum up RFC2646: lines that end in space-linend are treated as part of 
the same paragraph with the line that follows; and lines which have 
quote characters at the front are grouped into paragraphs with the same 
quote level, which can then be rendered as the viewing client sees fit.

Here's my code, extracted into a single runnable program (it actually 
forms part of a larger HTML formatting module).  If you're copying it 
make sure to preserve the spaces at the end of the 1st and 10th lines of 
test data.

#! /usr/bin/perl

use strict;
use warnings;

my $flow = <<ENDMSG;
This is an introductory paragraph
of two lines
 >Quote level 1
 >>Quote level 2
 >>More quote level 2
 >>>Quote level 3
 >>>More level 3
 >Quote level 1 again
This is another paragraph.
Here is another; this one
has two lines.
ENDMSG

print flow_text($flow);

sub flow_text {
   my ( $body, $stylename ) = @_;
   $stylename = 'quote' unless $stylename;
   my @lines = split "\n", $body;
   my $html = '';
   my ( $this, $last );
   my $current_level = 0;
   my $para = 0;
   $last = '';
   for $this ( @lines ){
     next unless $this;
     $this =~ s/^\s+//;  # Remove any leading space
     if ( $this =~ m|^(\>+)| ){   # Quoted line
       my $quotes = $1;
       $html .= "</p>\n", $para =0 if $para;
       my $level = length( $quotes );
       $this = substr($this,$level);  # Remove the quote marks
       if ( $level > $current_level ){
         my $style = $level>1? ($stylename . ($level-1)) : $stylename;
         $html .= (' ' x $level) . "<div style=\"$style\">$this\n";
       }
       else {
         $html .= _close_quotes( $current_level, $level ) . (' ' x 
$level) . "$this\n";
       }
       $current_level = $level;
     }
     else {  # Un-quoted
       $html .= _close_quotes( $current_level, 0 );
       $current_level = 0;
       if ( substr($last, -1) eq ' ' ){
         $html .= "$this\n";
       }
       else {
         $html .= "</p>\n" if $para;
         $html .= "<p>$this\n";
         $para = 1;
       }
     }
     $last = $this;
   }
   $html .= "</p>\n" if $para;
   return $html;
}

sub _close_quotes {
   # Generates </div> tags.
   # Parameters:
   #  0  The current quote level
   #  1  Optionally the desired quote level; one level of quotes will be
   #     closed if this parameter is omitted.
   # Returns the relevant HTML string.  Null if the current level is 
zero or the
   # desired level is not less than the current level.
   my ( $level, $desired_level ) = @_;
   return '' unless $level;
   my $html = '';
   $desired_level = $level-1 unless $desired_level || $desired_level == 0;
   return '' unless $level > $desired_level;
   for ( my $i = $level; $i>$desired_level; $i-- ) {
     $html .= (' ' x ($i-1)) . "</div>\n";
   }
   return $html;
}

-- 

Henry Law            Manchester, England


------------------------------

Date: Fri, 26 Aug 2011 18:28:07 -0500
From: Tad McClellan <tadmc@seesig.invalid>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <slrnj5gaem.t2s.tadmc@tadbox.sbcglobal.net>

Henry Law <news@lawshouse.org> wrote:

> It works, but every time I look at the code it offends me: it's clunky 
> and even I as a novice Perl programmer can see that it is not Perl-ish. 
>   Is there anyone with the time and the inclination to comment on the 

> sub flow_text {
>    my ( $body, $stylename ) = @_;
>    $stylename = 'quote' unless $stylename;
>    my @lines = split "\n", $body;


A pattern should *look like* a pattern:

    my @lines = split /\n/, $body;


>    my $html = '';
>    my ( $this, $last );


$this is scoped (file) globally, but used only in the for().

It should be scoped to the for() then.


>    my $current_level = 0;
>    my $para = 0;
>    $last = '';
>    for $this ( @lines ){


    for my $this ( @lines ){

or, do without the @lines temporary variable altogether:

    for my $this (split "\n", $body) {


>      next unless $this;
>      $this =~ s/^\s+//;  # Remove any leading space
>      if ( $this =~ m|^(\>+)| ){   # Quoted line


A pattern match should *look like* a pattern match.

You should use /slashes/ for delimiter unless there are
slashes in your pattern.

Angle bracket characters are not meta, so should not be backslashed:

    if ($this =~ /^(>+)/) {   # Quoted line


>        my $quotes = $1;


You can combine the assignement and the test into a single line too:

    if (my($quotes) = $this =~ /^(>+)/) {   # Quoted line

>
> sub _close_quotes {
>    # Generates </div> tags.
>    # Parameters:
>    #  0  The current quote level
>    #  1  Optionally the desired quote level; one level of quotes will be
>    #     closed if this parameter is omitted.
>    # Returns the relevant HTML string.  Null if the current level is 
> zero or the
>    # desired level is not less than the current level.
>    my ( $level, $desired_level ) = @_;
>    return '' unless $level;


If _close_quotes() is ever called in a list context, then this
failure will return a 1-element list.

It is more usual to return undef in scalar context and the empty
list in list context. You can do that easily with a bare return

    return unless $level;


-- 
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.


------------------------------

Date: Sun, 28 Aug 2011 19:00:53 +0100
From: Henry Law <news@lawshouse.org>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <QfGdnTBNM6bIH8fTnZ2dnUVZ7sadnZ2d@giganews.com>

On 27/08/11 00:28, Tad McClellan wrote:
> Henry Law<news@lawshouse.org>  wrote:
>
>> It works, but every time I look at the code it offends me: it's clunky
>> and even I as a novice Perl programmer can see that it is not Perl-ish.

Thank you Shmuel and Tad.

>>     my @lines = split "\n", $body;
>
>
> A pattern should *look like* a pattern:
>
>      my @lines = split /\n/, $body;

It's a habit I got into; I'll break it.

> $this is scoped (file) globally, but used only in the for().
>
> It should be scoped to the for() then.

Untidy, indeed.  And a possible maintenance hazard.

>      for my $this (split "\n", $body) {

Yes that would be neater: changed.

> Angle bracket characters are not meta, so should not be backslashed:

Laziness, y'know ... can't remember whether it's meta so bung in the 
backslash ...

> You can combine the assignement and the test into a single line too:
>
>      if (my($quotes) = $this =~ /^(>+)/) {   # Quoted line

Neater and just as easy to do.  But why the parentheses round "$quotes"? 
  I can't see what grouping or priority they change.

>>     return '' unless $level;
>
> If _close_quotes() is ever called in a list context, then this
> failure will return a 1-element list.
>
> It is more usual to return undef in scalar context and the empty
> list in list context. You can do that easily with a bare return

I'll remember that in future, but in this case I know exactly where the 
sub is called and what it's to return, and a zero-length string makes 
other code, not shown, simpler.  It looks like

  $some_string = $some_stuff || close_quotes(etc) || " more stuff";

As to Shmuel's points: (1)I'm ignoring DelSp for now;  if I end up with 
more spaces in the line than I need it's not important.  But (2) no, 
you're right about not eliminating vertical space.

Thank you both again for the time you spent.

-- 

Henry Law            Manchester, England


------------------------------

Date: Sun, 28 Aug 2011 18:25:31 +0000 (UTC)
From: Willem <willem@toad.stack.nl>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <slrnj5l20r.10ae.willem@toad.stack.nl>

Henry Law wrote:
) On 27/08/11 00:28, Tad McClellan wrote:
)> You can combine the assignement and the test into a single line too:
)>
)>      if (my($quotes) = $this =~ /^(>+)/) {   # Quoted line
)
) Neater and just as easy to do.  But why the parentheses round "$quotes"? 
)   I can't see what grouping or priority they change.

They give it list context instead of scalar context.
That is very important!  Otherwise it will not work.


SaSW, Willem
-- 
Disclaimer: I am in no way responsible for any of the statements
            made in the above text. For all I know I might be
            drugged or something..
            No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT


------------------------------

Date: Sun, 28 Aug 2011 20:36:31 +0200
From: "Peter J. Holzer" <hjp-usenet2@hjp.at>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <slrnj5l2lf.593.hjp-usenet2@hrunkner.hjp.at>

On 2011-08-26 10:35, Henry Law <news@lawshouse.org> wrote:
> I have written some code which takes the body of a message in RFC2646 
> format (format=flowed) and generates the appropriate HTML for it to 
> render in the mail-archiving system I'm writing.
>
> It works, but every time I look at the code it offends me: it's clunky 
> and even I as a novice Perl programmer can see that it is not Perl-ish. 
>   Is there anyone with the time and the inclination to comment on the 
> way I've coded the algorithm (or indeed the algorithm itself) to help me 
> make it better?

For now I comment only on the algorithm. You should fix the errors first
and then worry about aesthetic questions.


> To sum up RFC2646:

RFC 2646 is obsolete. Refer to RFC 3676 instead (the basic algorithm is
the same, it just adds support for languages which are normally written
without spaces).

> Here's my code, extracted into a single runnable program (it actually 
> forms part of a larger HTML formatting module).  If you're copying it 
> make sure to preserve the spaces at the end of the 1st and 10th lines of 
> test data.

Well, you didn't preserve them when copying them into the message, so I
could only add then again. It's probably better to use double quoted
strings instead of here documents if you can't trust your NUA.


> #! /usr/bin/perl
>
> use strict;
> use warnings;
>
> my $flow = <<ENDMSG;
> This is an introductory paragraph
> of two lines
> >Quote level 1
> >>Quote level 2
> >>More quote level 2
> >>>Quote level 3
> >>>More level 3
> >Quote level 1 again
> This is another paragraph.
> Here is another; this one
> has two lines.
> ENDMSG

Also, the text and the format don't fit together. None of the lines
containing the word "quote" are quoted. Because of the leading space
(see section 4.4 - Space-Stuffing) all of them are non-quoted lines
starting with ">".


> print flow_text($flow);
>
> sub flow_text {
>    my ( $body, $stylename ) = @_;
>    $stylename = 'quote' unless $stylename;
>    my @lines = split "\n", $body;
>    my $html = '';
>    my ( $this, $last );
>    my $current_level = 0;
>    my $para = 0;
>    $last = '';
>    for $this ( @lines ){
>      next unless $this;

This throws away all empty lines (you still need them as paragraph
separators) as well as lines consisting only of the digit 0.

>      $this =~ s/^\s+//;  # Remove any leading space
>      if ( $this =~ m|^(\>+)| ){   # Quoted line

This is the wrong order. Quoting must be checked before space-stuffing.
Also, only a single space must be removed.

>        my $quotes = $1;
>        $html .= "</p>\n", $para =0 if $para;
>        my $level = length( $quotes );
>        $this = substr($this,$level);  # Remove the quote marks
>        if ( $level > $current_level ){
>          my $style = $level>1? ($stylename . ($level-1)) : $stylename;
>          $html .= (' ' x $level) . "<div style=\"$style\">$this\n";

HTML has the blockquote element for quotes - no need to (mis)use div.

>        }
>        else {
>          $html .= _close_quotes( $current_level, $level ) . (' ' x 
> $level) . "$this\n";
>        }
>        $current_level = $level;

AFAICS you treat all quotes as flowable paragraphs - this is wrong.
Quotes may be fixed, too (and usually are).

>      }
>      else {  # Un-quoted
>        $html .= _close_quotes( $current_level, 0 );
>        $current_level = 0;
>        if ( substr($last, -1) eq ' ' ){
>          $html .= "$this\n";
>        }
>        else {
>          $html .= "</p>\n" if $para;
>          $html .= "<p>$this\n";
>          $para = 1;

I would use <pre> for (blocks of) fixed lines. They are often carefully
formatted and whitespace should be preserved.

	hp



------------------------------

Date: Sun, 28 Aug 2011 23:21:07 +0100
From: Henry Law <news@lawshouse.org>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <CN-dndZIDpTOIsfTnZ2dnUVZ8gGdnZ2d@giganews.com>

On 28/08/11 19:36, Peter J. Holzer wrote:
> For now I comment only on the algorithm. You should fix the errors first
> and then worry about aesthetic questions.

Hmm; thank you for what followed.  It's plain that I didn't think it 
through well enough.

> Refer to RFC 3676 instead

Yes.  I've done that now.

> Well, you didn't preserve them when copying them into the message, so I
> could only add then again.

What can I say other than "aaagggh ... sorry".  I even checked carefully 
on the screen before I sent it.

> Also, the text and the format don't fit together. None of the lines
> containing the word "quote" are quoted. Because of the leading space
> (see section 4.4 - Space-Stuffing) all of them are non-quoted lines
> starting with ">".
That surprised me, though I see on careful reading that you're right. I 
got confused by the formatting that my UA (Thunderbird) adopts, which 
has a space after the quote character.

> HTML has the blockquote element for quotes - no need to (mis)use div.

For some reason I had it in my mind that blockquotes couldn't be nested; 
I've now found that I'm wrong.  This is how one learns ...

> AFAICS you treat all quotes as flowable paragraphs - this is wrong.
> Quotes may be fixed, too (and usually are).

Reading the RFC more carefully I see that quoted lines are also marked 
by trailing spaces when they are to be flowable.  I need to implement 
that too.

I'm really grateful for your post, uncomfortable though it is.  But I 
guess we should not discuss the algorithm any more here because it's 
Nothing To Do With Perl (TM).

-- 

Henry Law            Manchester, England


------------------------------

Date: Sun, 28 Aug 2011 21:51:03 -0500
From: Tad McClellan <tadmc@seesig.invalid>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <slrnj5lv2j.4kr.tadmc@tadbox.sbcglobal.net>

Henry Law <news@lawshouse.org> wrote:
> On 27/08/11 00:28, Tad McClellan wrote:
>> Henry Law<news@lawshouse.org>  wrote:

>> Angle bracket characters are not meta, so should not be backslashed:
>
> Laziness, 


A Laziness that causes folks to work more,
is a *false* laziness.


> y'know ... can't remember whether it's meta so bung in the 
> backslash ...


Code is written one time and read many times.

You should optimize for maintenance rather than for development time.

Each reader will have to slow down because something is
escaped (ie. it does not have its "usual" meaning), only
to discover that nothing is different, and that things
*do* have their usual meaning.

You "tricked" the reader into paying more attention than was needed.


>>>     return '' unless $level;
>>
>> If _close_quotes() is ever called in a list context, then this
>> failure will return a 1-element list.
>>
>> It is more usual to return undef in scalar context and the empty
>> list in list context. You can do that easily with a bare return
>
> I'll remember that in future, 


You should always be prepared for your subroutines to
be called in either context.

Or at the least, complain loudly when it is called in an
un-supported context.

    die "somesub() must be used in scalar context\n" if wantarray;


> but in this case I know exactly where the 
> sub is called 


Subroutines are meant to be reused. When it is reused someplace
other than your "exact place", you could return true when
the correct value is false!


> and what it's to return, and a zero-length string makes 
> other code, not shown, simpler.


Uh, my suggested change also results in a zero-length string.

When undef is used as a string, it acts like the empty string.

And it has the added feature of being "falsy" in a list context
while yours is "truthy" in a list context.


-- 
Tad McClellan
email: perl -le "print scalar reverse qq/moc.liamg\100cm.j.dat/"
The above message is a Usenet post.
I don't recall having given anyone permission to use it on a Web site.


------------------------------

Date: Mon, 29 Aug 2011 11:24:06 +0100
From: Henry Law <news@lawshouse.org>
Subject: Re: My code works but is clunky and inelegant; help to improve it?
Message-Id: <rdqdnU1726Za9cbTnZ2dnUVZ7s2dnZ2d@giganews.com>

On 29/08/11 03:51, Tad McClellan wrote:
>> and what it's to return, and a zero-length string makes
>> other code, not shown, simpler.
>
> Uh, my suggested change also results in a zero-length string.
>
> When undef is used as a string, it acts like the empty string.

But it provokes that maddening message when "use warnings" is in force 
(as it always is in my code ...).  I like my code to run completely clean.

#! /usr/bin/perl
use strict; use warnings;
print "The following value: '" . notdef() . "' is undefined\n";

sub notdef {
   return;
}

Use of uninitialized value in concatenation (.) or string at ./tryout 
line 3.
The following value: '' is undefined

So either I'd need to disable warnings every time that subroutine is 
used (and in other similar circumstances) or else check each time using 
some construct like ( notdef() || '' )

> And it has the added feature of being "falsy" in a list context
> while yours is "truthy" in a list context.

Can't deny that.  (Amusing and useful neologisms ...)

-- 

Henry Law            Manchester, England


------------------------------

Date: Mon, 29 Aug 2011 12:01:40 +0800
From: "ela" <ela@yantai.org>
Subject: traversing a hash structure
Message-Id: <j3f30c$uvt$1@ijustice.itsc.cuhk.edu.hk>

For a market basket analysis, I'd like to traverse a hash structure 
containing entries like:

my %list;
$list{"c1"} = "milk%cheese%coca cola";
$list{"c2"} = "coca cola";
$list{"c3"} = "beef";
 ...
$list{"cn-1"} = "apple%cheese";
$list{"cn"} = "beef%milk";

so the knowledge derived may look like:
c1 is associated with c2, .., cn-1, cn
c3 is associated with cn
 ...

i.e. the total number of checking is "n + n-1 + ... + 2 + 1" .
While this can be easily achieved if the structure is array, the following 
looks clumsy... any better implementation?

while (%list) {
    $assign = 1;
    foreach $key (keys %list) {
        if ($assign == 1) {
            $head = $key;
            $assign = 0;
            next;
        }
        if ($list{$head} =~ /$list{$key}/ or  $list{$key} =~ 
/$list{$head}/ ) {
            print "$list{$head}\t$list{$key}\t1\n";
        }
    }
    undef $list{$head};
} 




------------------------------

Date: Mon, 29 Aug 2011 11:56:40 +0100
From: Henry Law <news@lawshouse.org>
Subject: Re: traversing a hash structure
Message-Id: <XtqdnXyPUrH07cbTnZ2dnUVZ8nidnZ2d@giganews.com>

On 29/08/11 05:01, ela wrote:
> For a market basket analysis, I'd like to traverse a hash structure
> containing entries like:
>
> my %list;
> $list{"c1"} = "milk%cheese%coca cola";

Just by the way, is this real code?  Surely Perl would have tried to 
parse %cheese etc as the names of hash variables?  Confusing at best.

> $list{"c2"} = "coca cola";
> $list{"c3"} = "beef";
> ...
> $list{"cn-1"} = "apple%cheese";
> $list{"cn"} = "beef%milk";
>
> so the knowledge derived may look like:
> c1 is associated with c2, .., cn-1, cn
> c3 is associated with cn

It looks as if the interesting stuff is the individual "line items" of 
the value strings: milk, cheese etc.  Are you stuck with this structure? 
  I think I'd start at load time and separate those "line items" into a 
hash _by line item_, so my hash looked like this:

my %things_people_buy = {
   milk => [ 'c1', 'cn' ],
   cheese => [ 'c1', 'cn-1' ] ... etc

The load code would look a bit like this (un-runnable)

while ( my $input_line = <SOMEFILE> ) {
   my @input_tokens = split /%/,$input_line;  # If % is your separator
   my $customer = shift @input_tokens;
   foreach my $thing ( @input_tokens ) {
     if ( exists $things_people_buy{$thing} ) {
       push @{$things_people_buy{$thing}}, $customer;
     }
     else {
       $things_people_buy{$thing} = [ $customer ];
     }
   }
}

You could then work out the associations by scanning the "things bought" 
hash; every customer in the list is associated with every other in the 
same list.

-- 

Henry Law            Manchester, England


------------------------------

Date: 6 Apr 2001 21:33:47 GMT (Last modified)
From: Perl-Users-Request@ruby.oce.orst.edu (Perl-Users-Digest Admin) 
Subject: Digest Administrivia (Last modified: 6 Apr 01)
Message-Id: <null>


Administrivia:

To submit articles to comp.lang.perl.announce, send your article to
clpa@perl.com.

Back issues are available via anonymous ftp from
ftp://cil-www.oce.orst.edu/pub/perl/old-digests. 

#For other requests pertaining to the digest, send mail to
#perl-users-request@ruby.oce.orst.edu. Do not waste your time or mine
#sending perl questions to the -request address, I don't have time to
#answer them even if I did know the answer.


------------------------------
End of Perl-Users Digest V11 Issue 3483
***************************************


home help back first fref pref prev next nref lref last post