in reply to Changing -> to work within a string

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";

If you do not want to create the global variable you have to use tie(...) instead of use Interpolation ... like this:

... package main; use Interpolation; my $foo = new Foo; my $Foo = {}; tie %$Foo, 'Interpolation::general', sub { my $cmd = shift(); no strict 'refs'; $foo->$cmd(@_); }, '$@->$'; print "x $Foo->{bar}\n"; print "x $Foo->{bar}{1}\n"; print "x $Foo->{bar}{1,2}\n";

Of course this way you have to create a tied hash (or reference to a tied hash) for each object you want to be able to call this way. If you can do that you may create a single %CALL hash and use that one like this:

... package main; use Interpolation; my $foo = new Foo; my $CALL = {}; tie %$CALL, 'Interpolation::general', sub { my $obj = shift(); my $cmd = shift(); no strict 'refs'; $obj->$cmd(@_); }, '$$@->$'; print "x $CALL->{$foo}->{bar}\n"; print "x $CALL->{$foo}->{bar}{1}\n"; print "x $CALL->{$foo}->{bar}{1,2}\n";
but I think this doesn't look good anymore.

Jenda

Update: You may also want to look at Perl6::Interpolators. They might suit you even better.

Update 2: There's one gotcha I should warn you about. The parameters to the methods are converted to strings! So if they were references they are not any longer. And if they contained the character with code 28 ($;) then they will be split up! If this is a problem you have to use a little different syntax:

package Foo; sub baz { my $self = shift(); foreach (@_) { print "$_ is a ".(ref $_ ? "reference" : "string")."\n"; } } ... package main; my $FooX = {}; tie %$FooX, 'Interpolation::general', sub { my $cmd = shift(); no strict 'refs'; $foo->$cmd(@_); }, '$$*->$'; print "x $FooX->{baz}{1}{2}{$foo}\n"; or my $CALLX = {}; tie %$CALLX, 'Interpolation::general', sub { my $obj = shift(); #print "Yep it's a ref\n" if ref $obj; my $cmd = shift(); no strict 'refs'; $obj->$cmd(@_); }, '$$$*->$'; print "x $CALLX->{$foo}->{baz}{$ref}{100}{$object}\n";
I doubt your users will like this though.