Recently, I took a stab at learning Haskell, but that's not really where this meditation came from. I've always thought there should be a side-effect-less (I know, not a real word) way to do substitutions, so I don't have to explicitely copy over a variable.
my $first; ... my $second = $first; $second =~ s/some/substitution/;
Okay, okay, so this really isn't a big deal, but it's worse off when I'm doing a map...
my @output = map { my $temp = $_; $temp =~ s/some/subst/g; $temp } @input;
So today I was at work, not doing much, and I thought about the different ways I could do this, and I finally wrote a module. I'm wondering what you, my fellow monks, think about this.
So what I finally decided on is a source filter. I know, there are a lot of people out there that eschew source filters, but I think it may be the best way to do it. So I ended up with the ability to do this:
use Regex::FunctionalSubstitute; my $first; ... my $second = $first \~ s/some/subst/g;
and
my @output = map { $_ \~ s/some/subst/g; } @input;
Frankly, especially in the map case where map is meant to transform, this just feels right to me. Now, I'm not sure about the exact syntax... I decided on \~, but am certainly not set on it, for two reasons. 1: \ gives the look of "not binding" compared to = looks like "binding". 2: \ also is part of Haskell's anonymous sub syntax, which is sometimes what I think of when I think about Haskell.
I should mention what the source filter does and it's repercussions. The source filter changes: $identifier \~ s/some/subst/ into do { $temp_var = $identifier; $temp_var =~ s/some/subst/; $temp_var }. The problem with this is that $1, $2, etc., and everything involved in regex's will be out of scope, and therefore un-useable, so I would have to find a way to circumvent this, but this may cause similar problems to 'use English'. The source filter changes: $identifier \~ s/some/subst/ into ( $temp_var = $identifier, $temp_var =~ s/some/subst, $temp_var )[2] which has the effect of preserving $1, $2, etc. as well as returning the right value, both inside and outside map.
Well, enough explanation, here's the current code (definitely not finished).
package Regex::FunctionalSubstitute; use Filter::Simple; use strict; use warnings; my $identifier = qr/\$\S+/; my $operator = qr/\\~/; my $temp = '$Regex::FunctionalSubstitute::temporary_variable'; =head1 TODO Test Suite This documentation More accurate 'identifier' regex =head1 Conversion $this = $that \~ s/one/two/; converts to: $this = ( $temp = $that, $temp =~ s/one/two/, $temp )[2] =cut FILTER_ONLY( code => sub { my $ph = $Filter::Simple::placeholder; s{ ($identifier) # the source of the substitutio +n \s* # possible space between $operator # the operator '\~' \s* # more possible space between ($ph) # the regex itself } { ( $temp = $1, $temp =~ $2, $temp )[2] }gx; }, ); 1;
Update: Changed the transformation after fiddling with this for a while, so now $1, $2, etc. should be preserved.
-Bryan
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re: A Functional Substitute
by BrowserUk (Patriarch) on Aug 08, 2005 at 21:45 UTC | |
|
Re: A Functional Substitute
by friedo (Prior) on Aug 08, 2005 at 21:48 UTC | |
by mrborisguy (Hermit) on Aug 08, 2005 at 23:21 UTC | |
by jdporter (Paladin) on Aug 09, 2005 at 14:57 UTC | |
by mrborisguy (Hermit) on Aug 10, 2005 at 23:53 UTC | |
|
Re: A Functional Substitute
by tinita (Parson) on Aug 09, 2005 at 09:12 UTC | |
|
Re: A Functional Substitute
by kappa (Chaplain) on Aug 12, 2005 at 16:44 UTC |