http://www.perlmonks.org?node_id=101326

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

Is it possible to create variables in perl that have the contextual behavior of $!? In a string context it yields the system error string. In a numeric context it yields the current value of the last syscall error. It would be very could to be able to do this with my own variables. thanks, --eric

Replies are listed 'Best First'.
Re: $! context behavior
by miyagawa (Chaplain) on Aug 01, 2001 at 13:51 UTC
    use overload. Here is a class that returns "foo" in a string context, and retutns 1 in numeric context.

    package SampleOverload; use overload '""' => \&as_string; use overload '0+' => \&as_num; sub new { bless { str => "foo", num => 1 }, shift; } sub as_string { shift()->{str}; } sub as_num { shift()->{num}; }

    Interesting examples of modules using overload is y2k and Dunce::time, that magically fixes y2k or 10-digit time problem.

    --
    Tatsuhiko Miyagawa
    miyagawa@cpan.org

Re: $! context behavior
by busunsl (Vicar) on Aug 01, 2001 at 12:32 UTC
    You can tie a variable to a class, and by that give it any behaviour you want.

    Have a look at tie.

Re: $! context behavior
by premchai21 (Curate) on Aug 01, 2001 at 13:12 UTC
(tye)Re: $! context behavior
by tye (Sage) on Aug 01, 2001 at 21:49 UTC

    You can use overload to simulate this behavior. But SetDualVar lets you build scalars the same way that $! is built, which it quite a bit less overhead (as if that matters). The module lets you set both the numeric and string value of a scalar without the two having to agree.

    Note that tie can't distinguish string and numeric "sub-contexts" and so isn't enough by itself to accomplish this. But you can use tie in conjunction with either overload or SetDualVar to do this (or just use overload by itself).

    And, if you really want to have it act just like $!, then a handy way to look up error strings from error numbers:

    sub getErrorText { local( $! )= 0+shift(@_); return "$!"; }

    But that also made me realize that you don't even need a module to create a dual-valued scalar that duplicates $! since

    $errno= $!= 5; print 0+$errno," $errno\n";
    prints something like "5 Input/output error".

    Also note that getting the type of "copy semantics" you want may be the determining factor in which method to use.

            - tye (but my friends call me "Tye")