Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Schizophrenic var

by bliako (Monsignor)
on Dec 05, 2022 at 21:59 UTC ( [id://11148581]=perlmeditation: print w/replies, xml ) Need Help??

I admit that dualvar was a term I never felt looking up until it came up recently here at the Monastery at Re^2: Rosetta Code: Long List is Long -- dualvar by marioroy. And I had a look at it. I found that Scalar::Util's dualvar can indeed create such a variable but I did not find any way of driving an existing variable into schizophrenic behaviour.

And so here is a gutty way to alter the string and/or numeric part of an existing scalar. Mind you I did a brief search on whether there was already some existing package doing that but did not find any.

This can find applications in some cases of the Schwartzian transform where the "decorations" and "undecorations" can apply on existing data rather than creating new (re: decorate/undecorate, Schwartzian_transform). The concept is not new (e.g. see comments under https://www.endpointdev.com/blog/2009/08/perls-scalarutildualvar/), but I did not find anything without creating new (dual)var but altering existing var. So here it is in a single-file SCSE form (XS can be found in ./_Inline/build dir):

## by: bliako ## on: 2022-12-05 ## EDIT: kudos to https://metacpan.org/release/PEVANS/Scalar-List-Util +s-1.63/source/ListUtil.xs (line 1674, dualvar) use strict; use warnings; use Devel::Peek; use Inline Config => clean_after_build => 0; use Inline C => <<'EOC'; // alter the 'numeric' slot of existing var 'asv' with that of + 'theiv' void setIV(SV *asv, SV *theiv){ (void)SvUPGRADE(asv, SVt_PVNV); SvIV_set(asv, SvIV(theiv)); SvIOK_on(asv); } // alter the 'string' slot of existing var 'asv' with that of +'thesv' void setSV(SV *asv, SV *thesv){ sv_setsv(asv, thesv); } EOC my $num = 42; my $x = "My name is Ace!"; Dump($x); setIV($x, $num); Dump($x); setSV($x, "Hello Ozy!"); Dump($x); # and here is a one-legged Schwartzian transform # to sort strings on their lengths using above XS: my @unsorted = ("Just", "another", "Perl\x{7}\x{7}\x{7}", "hacker\x{7} +"); my @sorted = sort { $a <=> $b } map { setIV($_, length($_)); $_ } @unsorted; print "Sorted: @sorted\n"; ;

Hacking away with Perl into the new year ... (actually I think I am in 2048 already, riding on Perl)

bw, bliako

Replies are listed 'Best First'.
Re: Schizophrenic var
by Discipulus (Canon) on Dec 06, 2022 at 07:39 UTC
    Hello bliako,

    for sure in your resarch you read create-your-own-dualvars. It tells $! is already dualvar:

    perl -le "for (0..42){local $!; $! = $_; print 0 + $!, qq( - $!)}" 0 - 1 - Operation not permitted 2 - No such file or directory 3 - No such process 4 - Interrupted function call 5 - Input/output error 6 - No such device or address 7 - Arg list too long 8 - Exec format error 9 - Bad file descriptor 10 - No child processes 11 - Resource temporarily unavailable 12 - Not enough space 13 - Permission denied 14 - Bad address 15 - Unknown error 16 - Resource device 17 - File exists 18 - Improper link 19 - No such device 20 - Not a directory 21 - Is a directory 22 - Invalid argument 23 - Too many open files in system 24 - Too many open files 25 - Inappropriate I/O control operation 26 - Unknown error 27 - File too large 28 - No space left on device 29 - Invalid seek 30 - Read-only file system 31 - Too many links 32 - Broken pipe 33 - Domain error 34 - Result too large 35 - Unknown error 36 - Resource deadlock avoided 37 - Unknown error 38 - Filename too long 39 - No locks available 40 - Function not implemented 41 - Directory not empty 42 - Illegal byte sequence

    > but I did not find any way of driving an existing variable into schizophrenic behaviour.

    All scalars are already schizophrenic (but using strict they claim for a psychologic support, not sure if for the compiler or for the programmer ;)

    perl -wle "use strict; for my $x(@ARGV){ print qq(I was: $x); print qq +(adding 1 I'm: ),$x + 1; print $x > 0 ? qq(I'm more than zero! ) : qq +(I'm less than or zero! ); print $\ }" 0z 42A I was: 0z Argument "0z" isn't numeric in addition (+) at -e line 1. adding 1 I'm: 1 I'm less than zero! I was: 42A Argument "42A" isn't numeric in addition (+) at -e line 1. adding 1 I'm: 43 I'm more than zero!

    perl -wle "$x = q(a); print ++$x" prints b

    L*

    PS

    This is even more weird.. I want to see if the numeric part of a filehandle was the same of what fileno returned.. it would be fun.. but no fileno

    perl -lwe "open my $fh, '>', 'test'; print 0 + $fh; print + $fh" 16950176 GLOB(0x102a3a0) # ..and no: 16950176 is not the sum of numerical values of characters perl -wle "$str = q!GLOB(0x102a3a0)!; for (split '',$str){ print qq($_ + = ),ord($_);$res += ord($_);} print $res" G = 71 L = 76 O = 79 B = 66 ( = 40 0 = 48 x = 120 1 = 49 0 = 48 2 = 50 a = 97 3 = 51 a = 97 0 = 48 ) = 41 981

    PPS perl -wle "$x = q(a); print ++$x" prints b but not all chars are numeric, sorry I'm not JAPH, but J1PH1 :)

    perl -we "print ++$_ for 'I@OG+' =~ /./g" Argument "@" isn't numeric in preincrement (++) at -e line 1. Argument "+" treated as 0 in increment (++) at -e line 1. J1PH1

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      for sure in your research you read create-your-own-dualvars

      Ha ha, this has now become hilarious!

      Yesterday in Re^3: Rosetta Code: Long List is Long (Updated Solutions - dualvar), I claimed "Despite using Perl for 20 years, I'd never heard of dualvar before" ... yet on seeing your reference to good old brian_d_foy's dualvar article just now, I rushed to my bookshelf to find brian's superb book still sitting there, along with my customary book notes scribbled on a piece of paper inside the book ... which noted the existence of dualvar on page 30 as "interesting"! Oops, looks like my memory is starting to fail.

      Also interesting is that the paper copy had some nice levity to it which is sadly missing from the Web version ... at least the paper copy concludes the dualvar item with "now that you know this, don't start using it everywhere. Save it for very special situations, like impressing people at conferences and cocktail parties." ... or impressing people at Perl Monks in the case of marioroy. :)

        I used "dualvar" also, in MCE::Shared::Cache. When max_age is specified during construction of the cache, the dualvar is used internally to store the expiration time with the key name in the keys array.

        # update expiration $keys->[ $off ] = ( $exptime >= 0 ) ? dualvar( time + $exptime, $_[1] ) : dualvar( -1, $_[1] );

        Basically, the "dualvar" capability in Perl allows the "max_age" feature without increasing the memory consumption of the cache or impacting performance.

      All scalars are already schizophrenic

      This has little to do with the values, and more with the operations you are doing. If a value starts with a number, it will be treated as that number when used in numeric operations. And it will issue a warning if it is followed by non-numeric data, as you demonstrated. "0z" is not comparing as "less than zero", it is comparing equal to zero. And the ++ operator has two different functions depending on what type of input it is given.

      This is even more weird.. I want to see if the numeric part of a filehandle was the same of what fileno returned.. it would be fun.. but no fileno

      The value shown is a GLOB reference, which internally contains the file handle in its IO slot. All references, aside from objects using overloading, numify to their refaddr.

      $ perl -le'my $ref = []; print $ref; printf "%s(0x%x)", ref $ref, 0+$ref;'
      ARRAY(0x15500a648)
      ARRAY(0x15500a648)
      

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (1)
As of 2024-04-25 04:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found