=head1 TITLE

Interpolation of method calls

=head1 VERSION

Maintainer:     Michael G Schwern <[EMAIL PROTECTED]>
Date:           14 Sep 2000
Version:        1
Mailing List:   [EMAIL PROTECTED]


=head1 ABSTRACT

Method calls should interpolate in double-quoted strings, and similar
locations.

    print "Today's weather will be $weather->temp degrees and sunny.";

Would deparse to:

    print 'Today\'s weather will be '.$weather->temp().' degrees and sunny.';


=head1 DESCRIPTION

=head2 The Current Problem With OO & Interpolation

Object-oriented programming encourages data-hiding, and one of the most basic
tool for this is the accessor method.  For reasons which should be obvious,
C<$obj->foo()> is usually better than C<$obj->{foo}>.  However, there are
several barriers to using an accessor method as simply as one does a hash
lookup.  Other RFCs deal with most of the current issues, but a basic one
still remains.

    print "Today's weather will be $weather->temp degrees and sunny.";
    
This does not DWIM.  Instead of interpolating C<$weather->temp> as a method
call, it comes out as C<$weather.'->temp'> and is usually followed immediately
by the question "What does 'Weather=HASH(0x80d4174)->temp' mean??"  Most
programmers learning OO Perl expect this to work and are surprised to find
that it does not.

Work arounds abound:

    # If I wanted printf(), I'd have written it in C.
    printf "Today's weather will be %d degrees and sunny.", $weather->temp;

    my $temp = $weather->temp;
    print "Today's weather will be $temp degrees and sunny.";
    
    print "Today's weather will be @{[$weather->temp]} degrees and sunny.";

    print "Today's weather will be ".$weather->temp." degrees and sunny.";

None are as simple and as obvious as:

    print "Today's weather will be $weather->{temp} degrees and sunny.";

and because of this users groan at having to use accessor methods and are
often tempted to violate encapsulation for ease of use.

=head2 Proposed Solution - Interpolate Methods

Therefore, it is proposed that direct object method calls be interpolated
inside double quoted strings and similar constructs.

    print "Today's weather will be $weather->temp degrees and sunny.";

should parse out as:

    print 'Today\'s weather will be '.$weather->temp().' degrees and sunny.';

thus returning DWIMness to methods and strings and removing one barrier to
accessor method's acceptance over hash lookups for objects.

Methods will be run in scalar context.  A method which returns a single scalar
is treated normally.  If a list is returned, it should be treated same as
array interpolation.  The list seperator will be applied.  In effect, the
deparsing will really work out as follows:

    print 'Today\'s weather will be '.join($", $weather->temp()).
          ' degrees and sunny.';

However if temp() calls wantarray(), the result will be FALSE (scalar).

(For the remainder of the RFC, the join() will be assumed when discussing
deparsing for brevity.)

Should it be decided that a formal distinction be made between accessor
methods and other types (RFC 95), method interpolation should interpolate
B<any> method.


=head2 Argument passing

Interpolation should also handle passing arguments to methods in a string:

    print "Today's weather will be $weather->temp("F") degrees and sunny.";

This should deparse to:

    print 'Today\'s weather will be '.$weather->temp("F").
          ' degrees and sunny.';

The arguments to the method are considered as normal expressions, thus:

    print "There is $obj->foo(this => $yar, that => 2 + 2) in my head.";

deparses as:

    print 'There is '.$obj->foo(this => $yar, that => 2 + 2). ' in my head.";


=head1 CAVEATS

Indirect object syntax, being already ambiguous, cannot be easily be
distinguished in a string from normal text and should not be interpolated. 
This is ok, since accessors are rarely called with indirect object syntax.


Are there any contexts besides double quotes ("", qq{}, <<"EOF") where this
need be applied?  What about inside regexes?  And if so, left and/or right
hand side?


Normally, whitespace is allowed between tokens of a method call.

    $obj -> bar ("this");
    
and

    $obj->bar("this");

are equivalent.  Whitespace between the object, '->', method name and opening
paren should be disallowed when interpolated.  This will avoid many ambiguous
cases.


Should the method not exist, Perl will throw an exception/die as usual.


C<"$var->{this}[2]{is}->{complex}->method"> should also be interpolated.  Also
C<"$obj->method->{key}"> for the case where a method returns a reference.


=head1 IMPLEMENTATION

The behavor of the parser to check for embedded variables would have to be
altered, namely the case where an embedded variable is being dereferenced.  A
case would be added to allow method calls as well as hash and array index
dereferences.  Otherwise, parsing should remain as normal.


=head1 REFERENCES

RFC 95  - Object Classes (proposes automatic accessor methods)

RFC 163 - Automatic accessors for hash-based objects


=head1 MIGRATION

Perl 5 to Perl 6 can simply change s/->(\w)/\\->$1/g in double quoted strings
to avoid the new interpolation.

=cut

-- 

Michael G Schwern      http://www.pobox.com/~schwern/      [EMAIL PROTECTED]
Just Another Stupid Consultant                      Perl6 Kwalitee Ashuranse
Maybe they hooked you up with one of those ass-making magazines.
        -- brian d foy as misheard by Michael G Schwern

Reply via email to