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

Re: Dualvar via table

by davido (Cardinal)
on Jan 17, 2020 at 18:21 UTC ( #11111541=note: print w/replies, xml ) Need Help??

in reply to Dualvar via table

I almost typed 90% of what LanX responded with, and even had some example code that was in some ways similar to his. Glad I checked before posting. I may include it at the bottom just as another demonstration.

Here is my concern, and it's similar also to LanX's: Conceptually the scalar container has a payload, and it has the ability to represent that payload according to the context provided by the operators that are acting upon it. The fact that this data polymorphism is implemented by encapsulating a PV (string pointer), NV (floating point pointer), IV (integer value), and a few other internal buckets into the scalar is how Perl manages to make this polymorphism computationally efficient at the expense of some memory. Using these buckets that house the representations of the data contained in a scalar variable as multiple entities is risky because it assumes that the subset of Perl you know will be acting on this scalar variable will not cause any clobbering or other attempts to bring the representations into consistency. But this is a subset of Perl. There is only a subset of scalars that will qualify for this treatment, depending on how they're created and used elsewhere in the script.

Whomever works with this variable needs to assure that they don't use parts of Perl that might have a problem with the inconsistency, and also make sure to be using the parts of Perl that do follow the PV/IV/NV internals pattern. That second part means not using tie. The first part means all bets are off if the variable passes through a module that implements XS XSubs in a way that are oblivious and possibly incompatible with dualvars. You are also taking serialization risks: If someone decides to compose your variable into a part of a structure that gets converted to JSON, all bets are off whether it will be treated as a string or a number. Well, that's maybe a little too glib, but different JSON encoders follow subtly different rules.

I'm also not a tremendous fan of overloading in most code, as I've seen what it can become in languages where it is more prolific. It still involves a form of spooky action at a distance. It works out fairly well for Math::BigInt, and a few other places, though. So I wouldn't disqualify it completely. But I would prefer creating an object that has explicit accessors for the data and for the text. Nevertheless, overloading is at least a language feature for Perl rather than an implementation detail, and comes with better guarantees and simpler rules. So it's possibly a reasonable solution for you.

All that said, here's the code that I was going to use as an example before noticing that LanX beat me to it:

#!/usr/bin/env perl use strict; use warnings; package MyCode; use overload '""' => sub {shift->{'text'}}, '0+' => sub {shift->{'data'}} fallback => 1; sub new { my $class = shift; return bless {@_}, $class; } package main; my @lines; while (<DATA>) { chomp; next unless length; my ($payload, $string) = split ',', $_, 2; push @lines, MyCode->new(text => $string, data => $payload); } foreach my $line (@lines) { print 0+$line, " $line\n"; } __DATA__ 100,PRINT "Hello world." 200,GOTO 100


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://11111541]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (5)
As of 2021-04-16 23:31 GMT
Find Nodes?
    Voting Booth?

    No recent polls found