Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

Interpolating Property strings help.

by krisahoch (Deacon)
on Jan 24, 2003 at 22:27 UTC ( [id://229728]=perlquestion: print w/replies, xml ) Need Help??

krisahoch has asked for the wisdom of the Perl Monks concerning the following question:

Fellow Monks,

I am trying to interpolate java style property values simuliar to the way ant does it. See below

build.dir = /usr/build product.dir = ${build.dir}/product
In this example, product.dir expands to be /usr/build/product

I am using the Config::Properties module for a base. I have a function that takes a properites hash

# File contents build=/usr/local/build eval=evaluation full=distribution PRODUCTONE=${build}/${eval} PRODUCTTWO=${build}/${full}/Second
I have it resolving the first value in a variable (PRODUCTONE) to /usr/local/build. The problem is that when the second value is resolved to blank. Here is a Dumper dump (faux).
VAR '1' = { 'build' => '/usr/local/build', 'eval' => 'evaluation', 'full' => 'distribution', 'PRODUCTONE' => '/usr/local/build/', 'PRODUCTTWO' => '/usr/local/build//Second', }

This problem has me pulling out my hair, and I really need help. Here is the snippet of code that I am using...

#===================================================================== += sub interpolateValues($) { my $self = shift; return unless defined($INTWeb::Properties::INTERPOLATE_VALUES); my $List = shift; foreach my $listKey (keys(%{$List})) { my $listValue = $List->{$listKey}; #print "|--+ $listKey: $listValue\n"; if ($listValue =~ m/\$\{(.*?)\}/) { my $extractedVariable = $1; my $defined = $self->isDefined($List, $extractedVariable); $defined += $self->isDefined($self->{Resolved}, $extractedVar +iable); die("FATAL: $extractedVariable is not a valid propery variabl +e name\n") if($defined == 0); my $substituteThis = $extractedVariable; my $substituteWith = $self->{Resolved}->{$extractedVariable}; my $final = $List->{$listKey}; $final =~ s/(\$\{$extractedVariable\}/$substituteWith/; print "FINAL: $final\n"; } else { $self->{Resolved}->{$listKey} = $List->{$listKey}; delete ($List->{$listKey}); } } } sub isDefined { my $self = shift; my $hash = shift; my $key = shift; return defined($hash->{$key}); } #--------------------------------------------------------------------- +-
Please help.


Kristofer Hoch

Si vos can lego is, vos es super erudio

Replies are listed 'Best First'.
Re: Interpolating Property strings help.
by sauoq (Abbot) on Jan 25, 2003 at 00:28 UTC
    Please help.

    I'm not sure I can help you solve your problem as it seems you've left out some of the code that produces the result. How does your $List variable get populated, for instance?

    I can make some suggestions that might help you clean up your code regardless of whether they fix your problems.

    • Don't use prototypes unless you know what you are doing. By the way, you don't know what you are doing until you understand the points raised in Tom Christiansen's article.

    • Get rid of your isDefined() subroutine. All it is doing is allowing you to replace

      defined $hash->{$key}
      with
      $self->isDefined($hash, $key)
      which is longer, less clear, and less efficient. Even if it made sense to use such a generic utility function (and in your case, it doesn't) it does not make sense to make it a method unless it does something specific to your class.

    • Consider using [^}]* in your regex as that's what you really seem to mean.

    • Consider making your regexen more robust in general. Your substitution:

      $final =~ s/(\$\{$extractedVariable\}/$substituteWith/;
      will work on data that looks like foo = ${bar}/baz but it will fail on foo = ${ bar }/baz because it isn't tolerant of whitespace.

    • Rethink your style of naming variables. $extractedVariable might be a little confusing. Is that the variable name? Is that the value held by some variable somewhere? Etc. Something like $identifier is shorter, easier to read, and more descriptive. I also notice that after the line

      my $substituteThis = $extractedVariable;
      you never bother to use the $substituteThis variable. You don't use it because you don't need to use it. Don't try to reassign variables to give them better names, just pick good names in the first place.

    I have another suggestion that I didn't want to include in the above list because it is purely a matter of style and you may not even have a choice depending on coding guidelines in your environment. Consider naming your variables like $foo_bar rather than $fooBar. I strongly agree with those that claim it makes for much more readable code.

    -sauoq
    "My two cents aren't worth a dime.";
    

      sauoq,

      Thank you for the suggestions. I will try the regex this monday. I need to reply to a couple of your points though

      Get rid of your isDefined() subroutine. All it is doing is allowing you to replace
      I am not the only one who uses this function. It has great meaning somewhere else

      Consider making your regexen more robust in general.
      The regex I chose is exactly what I am requireing. There is to be no whitespace allowed when expanding property values

      The $substituteThis and $substituteWith variables were used before I asked for help. I just hadn't pruned them out yet. I will rename $extractedVariable to $extractedVariableName

      The style thing. I come from a C programming background into a Perl and then Java. My preference is the Java variety.


      Kristofer Hoch

      Si vos can lego is, vos es super erudio

        A routine that turns defined $hashref->{$key} into $self->isDefined($hashref, $key) doesn't seem to have any purpose other than obfuscation to me. At least as far as I'm concerned, your code immediately became twice as clear once I substituted that for defined.

        Maybe it's an interface consistence thing that makes you have this method in your class - but that doesn't mean your routine should be using it.

        Makeshifts last the longest.

Re: Interpolating Property strings help.
by Aristotle (Chancellor) on Jan 25, 2003 at 00:36 UTC
    Your superfluous definition of isDefined makes the code quite hard to read, and the prototype on a method is silly since method dispatch never checks them, but here's what I fiddled it apart to, with a bit of guessing:
    sub interpolateValues { return unless defined $INTWeb::Properties::INTERPOLATE_VALUES; my $self = shift; my $list = shift; my $get_value_for = sub { my $var = shift; # !!! # the following doesn't seem right # don't you need to return $list->{var} # if ->{Resolved}->{var} is undef? # that seems to be your culprit return $self->{Resolved}->{$var} if defined $list->{$var} or defined $self->{Resolved}->{$var}; die "FATAL: $var is not a valid propery variable name\n"; }; while(my($key, $val) = each %$list) { if($val =~ s/\$\{(.*?)\}/$get_value_for->($1)/ge) { # ??? # you don't seem to be storing this anywhere? } else { $self->{Resolved}->{$key} = $val; delete $list->{$key}; } } }

    Makeshifts last the longest.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://229728]
Approved by Enlil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (4)
As of 2024-03-28 14:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found