new topic: I call length($<string>) and get number of lines - codefrag below - on MAC OS X 10.7

K

kquirici

if( ! open JOURNALTXT, $inputfilename) {
die "cannot open ".$inputfilename;
}

while (<JOURNALTXT>){
$journalin = $journalin . %_;
}

close JOURNALTXT;

$journal_txt_len = length($journalin);
print "journal length: " . $journal_txt_len;


-----------------
the last print statement returns 159 which is the number of lines; there are
actually around 8k chars.

At first I thought it was because I was using TextWrangler which uses unicode utf8, so I googled that and added all the stuff necessary for unicode on perl 5.whatever, but I still just got number of lines.

any help much appreciated.

Regards,

Ken Quirici
 
K

kquirici

Checking the return value of open is very good; but if you do it this
clumsily it will soon become infuriating and you will start leaving it
out. You should also include $! in the error message so you know what
went wrong.

You should be keeping your filehandles in variables, rather than using
global barewords. You should also be using 3-arg open.

open my $JOURNALTXT, "<", $inputfilename
or die "cannot open '$inputfilename': $!";

Alternatively, you can 'use autodie', which will handle the error for
you.


What do you think this does? (Specifically, %_ in scalar context.)


Did you try printing $journalin, to see what's in it? It isn't what you
expect.

More generally, this is an extremely roundabout way of reading a file
into a variable. Either use

{
local $/; # this sets $/ to undef
$journalin = <$JOURNALTXT>;
}

or use File::Slurp.

Ben

Thanks for your reply Ben. I got it to work. Oddly enuf I have no idea
why it works, because it looks exactly the same as before - I made some
mods that I deleted and returned it to its original form except now it works:

if( ! open JOURNALTXT, $inputfilename) {
die "cannot open ".$inputfilename;
}

while (<JOURNALTXT>){
$journalin = $journalin . $_;
}

close JOURNALTXT;
#print $journalin;

my $journalen = length($journalin);
print "\njournal length: " . $journalen;

prints the correct number of chars.

Thanks & Regards & Mystified,

Ken Quirici
 
K

kquirici

Checking the return value of open is very good; but if you do it this
clumsily it will soon become infuriating and you will start leaving it
out. You should also include $! in the error message so you know what
went wrong.

You should be keeping your filehandles in variables, rather than using
global barewords. You should also be using 3-arg open.

open my $JOURNALTXT, "<", $inputfilename
or die "cannot open '$inputfilename': $!";

Alternatively, you can 'use autodie', which will handle the error for
you.


What do you think this does? (Specifically, %_ in scalar context.)


Did you try printing $journalin, to see what's in it? It isn't what you
expect.

More generally, this is an extremely roundabout way of reading a file
into a variable. Either use

{
local $/; # this sets $/ to undef
$journalin = <$JOURNALTXT>;
}

or use File::Slurp.

Ben

Ah, I see what the problem was - I had %_ instead of $_.

Thanks & Regards,

Ken Quirici
 
M

Marc Girod

Sorry, but what is %_?
I cannot find it in perlvar, yet I don't get an error with:

perl -Mstrict -wle 'print %_'

Marc
 
R

Randal L. Schwartz

kquirici> $journalin = $journalin . %_;

Did you want %_ there, or $_?

print "Just another Perl hacker,"; # the original
 
J

Justin C

Ah, I see what the problem was - I had %_ instead of $_.

Thanks & Regards,

Ken Quirici


But don't disregard what Ben suggested, it's better, clearer
and more concise than what you have. In addition, if you
don't implement better methods when they're pointed out to
you then the next time you have a problem and ask here you're
going to get the same "use the three argument open", and
"local $/ for slurping" rather than getting to the meat of
your problem.


open my $JOURNALTXT, "<", $inputfilename
or die "cannot open '$inputfilename': $!";

my $journalin;
{
local $/; # this sets $/ to undef
$journalin = <$JOURNALTXT>;
}

print "journal length: ", length($journalin), "\n";



Justin.
 
T

Tim McDaniel

local $/; # this sets $/ to undef

I think that a rather more consise way to document that and to assure
any reader that it is true is

local $/ = undef;

or

undef(local $/);

(That latter appears to actually work.)
 
R

Rainer Weikusat

I think that a rather more consise way to document that and to assure
any reader that it is true is

local $/ = undef;

Code is not documentation. The comment informs a reader that $/ is
actually supposed to be undef. The assignment is just useless.
 
U

Uri Guttman

k> if( ! open JOURNALTXT, $inputfilename) {
k> die "cannot open ".$inputfilename;
k> }

why didn't you listen to what ben said about that code? also you can
interpolated $inputfilename into the die string which is a much better
style.


k> while (<JOURNALTXT>){
k> $journalin = $journalin . $_;
k> }

that is one of the slowest and clumsiest ways to read a whole file
in. first off learn about the .= assignment op (see perldoc perlop). but
even then why are you just reading each line to append it to the buffer?
ben showed you a much better way to read a whole file and File::Slurp is
the perl standard way these days.

k> close JOURNALTXT;
k> #print $journalin;

k> my $journalen = length($journalin);
k> print "\njournal length: " . $journalen;

k> prints the correct number of chars.

if all you wanted was the size of the file, -s will do that in one
call.

uri
 
T

Tim McDaniel

Quoth (e-mail address removed):

Is that surprising? local returns an lvalue, just like my; this is
very similar in form to the standard

(my $new = $old) =~ s/.../.../;

It's not the returning an lvalue part that I find hard to grasp --
though I had not realized that, so thank you.

It just still seems fundamentally weird to me that you can bury a
variable declaration within an expression, and further that it doesn't
end with the enclosing parentheses or expression. Yes, yes, the
perlfunc docco for "my" has "A 'my' declares the listed variables to
be local (lexically) to the enclosing block, file, or 'eval'." and
similarly for "local". And nobody else is responsible for it feeling
weird to me. Still. Weird.
 
T

Tim McDaniel

Rainer Weikusat said:
Code is not documentation.

A source file
- must express to the compiler the instructions to be followed
- also ideally ought to communicate to a human reader, expressing the
purpose and function of the overall file and of the various parts

I believe that most code, just by being code, communicates its purpose
to humans, at least at the lowest tactical levels and often even
higher. I believe that there is such a thing as "self-documenting
code" -- that code can also be documentation.

For example, a variable doesn't just have a use as a distinct thing,
but its name can be documentation: @cmd, $i, MAX_WIDTH, @global_flags,
$subdirectory. I've sometimes assigned intermediate values in an
expression to appropriately named variables -- sometimes because I
want to see the intermediates during debugging, but sometimes just to
clarify a large computation.

That is, I disagree with the premise of
Code is not documentation.
I define "documentation" as "everything that communicates to a human
reader". So I say that all code is documentation. Further, since
comments so easily get out of date, code is really the primary
documentation. If you insist that "documentation" must be "everything
explanatory that isn't code", then I think your definition has no
practical use.

When I have more than one way to write code to perform an action,
I consider efficiency, but I also consider a reader of the code
(my future self as well) and how well they will grasp it at a glance.
Where efficiency matters little (a small array, a computation
dominated by a larger process), I might use something easy to
understand. Or I might use something trickier and obscure, but
comment it copiously.

The immediate case was someone writing a line that localized $/ and
also expressed that they wanted it to be undefined. I'm not the one
who expressed the notion that the undefined value is important to
emphasize. Maybe you think that
local $/;
expresses the concept well enough. But I've hit enough problems of
looking at a block of code and trying to figure out what the values
are supposed to be at the end, and enough cases of assignments being
forgotten, that I prefer to be explicit.
 
R

Rainer Weikusat

A source file
- must express to the compiler the instructions to be followed
- also ideally ought to communicate to a human reader, expressing the
purpose and function of the overall file and of the various parts

I believe that most code, just by being code, communicates its purpose
to humans, at least at the lowest tactical levels and often even
higher.

People believe in all kinds of strange stuff. If you wrote the code,
chances are that seeing it reminds you of its purpose. But that's
obviously not going to happen for anyone else and in this case, the
(source) code communicates what the code is doing but not why it is
doing this.

[...]
The immediate case was someone writing a line that localized $/ and
also expressed that they wanted it to be undefined. I'm not the one
who expressed the notion that the undefined value is important to
emphasize. Maybe you think that
local $/;
expresses the concept well enough.

local $/;

is an operation whose semantics are documented: It creates a new
lexical binding for $/ (meaning, one which exists until the (dynamic)
end of the enclosing block) and - as with all Perl variables which
aren't initialized - its initial value is the so-called 'undefined
value'.
But I've hit enough problems of looking at a block of code and
trying to figure out what the values are supposed to be at the end,
and enough cases of assignments being forgotten, that I prefer to be
explicit.

And I have encountered enough cases were people managed to outsmart
themselves in their own code and made 'trivial oversight' errors
because of that that I'm completely convinced that the overriding
concern when writing code ought to be: Keep it simple. Every
expression in the code is one which somebody who sees it for the first
time has to read and understand, there's always a possibility for
errors here and the more expressions there are, that is, the more
complicated the code is, the greater the chance of such a
misunderstanding becomes. And this implies that one should never, ever
write any code which doesn't have a well-defined technical purpose
someone who doesn't share a brain with the author can understand: Any
such occurence make the code more complicated, by virtue of adding
expressions to it, but since there's nothing tangible in return, this
is a completely useless complication.

Apart from that none of

local $/;

local $/ = undef;

local $/ = undef;
$/ = undef;
$/ = undef;
$/ = undef;

are anyhow more 'explicit' than any of the others. Pointles
repetitions do not serve to make a text clearer.
 
T

Tim McDaniel

People believe in all kinds of strange stuff. If you wrote the code,
chances are that seeing it reminds you of its purpose. But that's
obviously not going to happen for anyone else

I *have* to be misreading you. You can't possibly be asserting that
it is impossible for you to deduce meaning and purpose behind these
example lines that I just came up with:

if (! send_email($from, $to, $subject, $body)) { ... }

foreach $i (0 .. @array-1) { ... }

$value =~ s/\s+/ /g;
$value =~ s/^ //;
$value =~ s/ $//;

my @org_ids = SQLvalues('select id from organization where deleted is null');
my @meta_orgs = GetEnclosingOrgs(@org_ids);

{
my %unique_ids;
@unique_ids{@ids} = ();
@ids = sort keys %unique_ids;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top