evalEmpire / perl5i

A single module to fix as much of Perl 5 as possible in one go
http://search.cpan.org/perldoc?perl5i
Other
156 stars 42 forks source link

Make chomp return the chomped string instead of chomping in place #120

Open DarwinAwardWinner opened 14 years ago

DarwinAwardWinner commented 14 years ago

The behavior of chomp has always been kind of weird, especially when it forces you to write:

chomp(my $line = <INPUT>);

instead of:

my $line = chomp <INPUT>;

Shouldn't chomp work more like trim?

avar commented 14 years ago

FWIW the reason this is done is that chomp() is much faster in void context. Instead of creating a new string it just modifies its length (it doesn't even reallocate).

And further the reason chomp() still returns the value that it does is historical. Some code out there depends on it.

The latter could be munged by perl5i. But it's a core operator so overriding it means overidding pp_chomp.

Also note that you could call chomp like this:

chomp(@strings);
schwern commented 14 years ago

chomp() can be overridden by defining CORE::GLOBAL::chomp. It can be made to behave lexically the perl5i way or the normal way. The trouble is, the wrapper will come with a performance penalty that effects all uses of chomp().

Fortunately, autoboxing lets us get around that. We can do whatever we like with the autoboxed version. while( $line = <$fh>->chomp ) { .. } would be interesting.

Once again I wish for the Ruby style method! naming convention to indicate methods which act in place.

DarwinAwardWinner commented 14 years ago

See also: http://dev.perl.org/perl6/rfc/58.html

schwern commented 14 years ago

There are two thing which trouble me about that Perl 6 RFC. The proposed special case for chomp() in while() is, well, a special case. Second, that chomp() would work differently in void and non-void contexts. Similar problems came up on p5p when discussing trim().

The dichotomy between the efficiency of in-place manipulation and the convenience of returning the modified structure plagues Perl ops.

DarwinAwardWinner commented 14 years ago

Aren't COW strings supposed to solve this in Perl 6? Though obviously this doesn't help for Perl 5.

schwern commented 14 years ago

Since chomp() is altering the string before returning, I don't see how it would. Unless it does something Extremely Clever like sharing the underlying C string between the two scalars, each using a different length. But that's not generally applicable.

avar commented 14 years ago

It could. That's how the core datastructures of Clojure and similar functional "strings are immutable" languages work, you can create lots of copies of 10MB strings and only store the differences.

There's COW support in p5, but I don't know its status.

daxim commented 13 years ago

In favour of keeping chop/chomp as is. Add functions chopped/chomped from http://p3rl.org/Text::Chomped instead which DTRT.

schwern commented 13 years ago

It just occurred to me that we already have trim which does what we want, it just needs to be given an argument.

my $line = <$fh>->trim("\n")

Is it worthwhile to write a special method just for trim("\n")? Or is it sufficient to just mention the above in the FAQ?

If so, what would it be called that would be more convenient to type and as obvious what it's doing? chomped fails the second case as it says nothing about how it's different from chomp.

doherty commented 13 years ago

Yes, it is worthwhile.

use perl5i::2;
use Test::More tests => 2;

my $string = " hello \n";
is($string->trim,  'hello', 'trim DTRT');

$string = " goodbye \n";
is($string->chomp, ' goodbye ', 'chomp, wtf'); # I expect this to work too