Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Changing -> to work within a string

by shushu (Scribe)
on Mar 19, 2003 at 11:22 UTC ( [id://244308]=perlquestion: print w/replies, xml ) Need Help??

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

Hallo monks!

In the environment I develop I give the users an option to write with Perl their own scenarios, using several pre-defined objects.
Every such object is based on AUTOLOAD subroutine that dispatch the relevant method to a certain use.
For example, a machine object has a working directory attribute. A user that want to use this attribute will write:
$machine->work_dir
To get the value of the working directory.

The problem is - the users are beginners in Perl development, and this is not their main task. When using several attributes in one line, they have to concatenate, what cause them troubles.
For example, getting a directory under the work directory that include a version number can look like this:
my $directory = $machine->work_dir . "/subdir/" . $machine->software_v +ersion . "/";
While the users want to write:
my $directory = "$machine->work_dir/subdir/$machine->software_version/ +";
Which will give them something like "HASH=(34234)->work_dir/subdir/HASH=(34234)->software_version/".

Do you guys have any idea how Perl can be changed to do what my users want ?

TIA,
shushu

Replies are listed 'Best First'.
Re: Changing -> to work within a string
by fruiture (Curate) on Mar 19, 2003 at 11:35 UTC

    I don't think it's a good idea to change Perl, because the interpolation rules are very basic and you would affect (=break) _a lot_ of other things. If somebody wants to use Perl, he/she should try to understand the very basics and if your beginners are unable to figure out that bit of concatenation, which i don't believe, they're absolutely not to be confronted with a programming language at all.

    You _could_ instead of $machine have a magic %machine hash that via tie()ing invokes methods on FETCH:

    "some string with $machine{work_dir} in it"

    But this is a workaround, i believe it's easier to explain the simple syntax than to write that TIEHASH-module (which isn't too hard itself).

    --
    http://fruiture.de
Re: Changing -> to work within a string
by Jenda (Abbot) on Mar 19, 2003 at 12:22 UTC

    With a fairly recent Interpolation.pm you can get almost what you are after:

    use strict; package Foo; sub new { my $self = {}; bless $self, 'Foo'; } sub bar { my $self = shift(); if (@_ == 0) { return "Call \$foo->bar()"; } else { return "Call \$foo->bar( '" . join("', '", @_) . "')"; } } package main; my $foo = new Foo; use Interpolation 'foo:$@->$' => sub { my $cmd = shift(); no strict 'refs'; $foo->$cmd(@_); }; # this creates a tied PACKAGE variable %main::foo !!! print "x $foo{bar}\n"; print "x $foo{bar}{1}\n"; print "x $foo{bar}{1,2}\n"; # if you want the arrow just create a reference to the %main::foo my $Foo = \%foo; print "x $Foo->{bar}\n"; print "x $Foo->{bar}{1}\n"; print "x $Foo->{bar}{1,2}\n";

Re: Changing -> to work within a string
by broquaint (Abbot) on Mar 19, 2003 at 11:30 UTC
    It ain't pretty but this should work
    my $directory = "${\$machine->work_dir}/subdir/${\$machine->software_version}/";
    But as it stands perl sees your string as
    my $directory = $machine."->work_dir/subdir/".$machine."->software_version}/";
    So you might need to either change the users' interface or force a style on them and definitely not use a source filter.
    HTH

    _________
    broquaint

Re: Changing -> to work within a string
by Pardus (Pilgrim) on Mar 19, 2003 at 13:00 UTC
    Why use an OO-interface at all if you don't want you're users to have to understand this. If you just give them the vars $machine_workdir and $machine_software_version they are happy. If you want something advanced you could try giving them a hash %machine which is tie'ed to some object instead of blessed to an object. This will be less transparent, but it is easier to use unexperienced users (just don't tell them about the tie ;) ).
    --
    Jaap Karssenberg || Pardus (Larus)? <pardus@cpan.org>
    >>>> Zoidberg: So many memories, so many strange fluids gushing out of patients' bodies.... <<<<
      Well, Thanks everybody.
      It seems that using tie is the right direction.
      But now I will make it harder...
      The same $machine object does not only have attributes I can use, it also has methods I can execute.
      $machine->shell("ls " . $machine->work_dir);
      Will execute the "ls" on the work directory. Using the tie I would want to write
      $machine->shell("ls $machine{work_dir}");
      The problem is - I actually have two variables - an object $machine, and a hash %machine. But the user don't know it, and I want the user to be able to wrap this line like this:
      sub do_ls { my $machine = shift; $machine->shell("ls $machine{work_dir}"); }
      If the user will need to do double shift, it will ruin the whole idea.
      Any ideas ?
      TIA,
      shushu TIA, shushu
Re: Changing -> to work within a string
by Marcello (Hermit) on Mar 19, 2003 at 12:58 UTC
    Why not write a function that takes care of the concatenation? All the users have to do is call this function with as many parameters as they want, and it will return the concatenated string.
    my $directory = concat($machine->work_dir, "/subdir/", $machine->softw +are_version, "/");
    Or is this too difficult for the users to understand?

      my $directory = concat($machine->work_dir, "/subdir/", $machine->software_version, "/");

      That sounds an awful lot like perl's built in join function, called like so:

      my $directory = join "", $machine->work_dir, "/subdir/", $machine->sof +tware_version, "/";

      cheers
      davis
      It's not easy to juggle a pregnant wife and a troubled child, but somehow I managed to fit in eight hours of TV a day.
        In fact, it is. I suggested writing a function that takes care of this because:

        1. you can alter the function in the future
        2. you can give it a more user-friendly name if wanted

        Regards,
        Marcel
(dkubb) Re: (1) Changing -> to work within a string
by dkubb (Deacon) on Mar 20, 2003 at 06:38 UTC

    Why not use sprintf to keep the method calls somewhat separated from the string?

    eg:

    my $directory = sprintf '%s/subdir/%s/', $machine->work_dir, $machin +e->software_version;
    Dan Kubb, Perl Programmer
•Re: Changing -> to work within a string
by merlyn (Sage) on Mar 22, 2003 at 16:33 UTC
    Method calls don't work in a string because subroutines didn't work in a string in Perl4. Variable references that use arrow to dereference do work in a string because variable interpolation worked in Perl4. It makes sense when you have a sense of history, but confuses the newbies occasionally.

    -- Randal L. Schwartz, Perl hacker
    Be sure to read my standard disclaimer if this is a reply.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (4)
As of 2024-04-25 12:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found