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

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

Monks,

My last question turned out to be a basic RTFM, but this one has me truly stymied. I seek your wisdom...

Before I start, I know there is inherent danger in what I am asking. So hear me out before you flame me. As you could probably guess from my previous question, I'm creating a custom dialog in Windows. That dialog will drive a number of reports based on report name. Two widgets are disabled for certain users based on an XML configuration file. The schema of the XML is such that it's possible to describe behavior of the widget even if it is not enabled. However, trying to alter the behavior of the disabled widget causes issues in my program.

I've already worked out a way to avoid problems, but the conditional clause is pretty ugly. Basically I take in a name from the XML, and compare the name to the two known problem widgets. If it's neither name, I pass through. If it's one or the other name, and the widget with that name is enabled, I pass through. If the widget is disabled, I jump out. The condition looks something like this:

# Check if this is a problem widget, and if it is, is it visible if( ($widget_name ne "problem1" && $widget_name ne "problem2") || ($widget_name eq "problem1" && $problem1->IsVisible()) || ($widget_name eq "problem2" && $problem2->IsVisible()) ) { ... }

What would be much cleaner would be if I could get a reference to the original widget scalar based on the scalar's name. Something akin to getting a reference to a routine using my $ref = \&{'mysub'}; . I could then dereference the original widget scalar based on name and check if it's visible. Something along the lines of:

#Get reference to widget based on name then check if it's visible my $ref = \${$widget_name}; if($$ref->IsVisible()) { ... }

And before you object, the XML schema is such that the XML will be invalid if some wag puts in Robert'); DROP TABLE STUDENTS; -- or similar. Only actual valid widget names will work, otherwise the XML is invalid.

So is such a thing possible? Or is there some obvious other path that I'm too inexperienced to see?

Replies are listed 'Best First'.
Re: Is it possible to get reference to scalar based on scalar name
by chromatic (Archbishop) on Sep 05, 2012 at 17:56 UTC
    Or is there some obvious other path that I'm too inexperienced to see?

    Store your widgets in a hash.


    Improve your skills with Modern Perl: the free book.

      mrider sheepishly agrees I guess I was too close to the problem to see the obvious. Oh well, it's better to ask a dumb question than it is to do a dumb thing. Thanks! <:o)
Re: Is it possible to get reference to scalar based on scalar name
by sundialsvc4 (Abbot) on Sep 05, 2012 at 18:08 UTC

    To put it another way ... create a hash, each element of which is a reference to, either the object itself, or another hash which contains various references that you need when accessing it.   Thanks to the “auto-vivification” features of Perl, that can be quite easy to do.   For example:

    my $objs; $$objs{'widget1'}{'widget'} = $widget1; $$objs{'widget1'}{'object'} = $object1; ...

    If in this example $widget1 and $object1 contain references to this-or-that, now the various hash-entries thus created contain another reference to those same things, whose reference-count is now at least 2.   Perl automatically recognized $objs to be a hash, automatically created an element for 'widget1', then automatically caused that element to be another hash, and inserted 'widget' and 'object' elements into that.

    Note that the syntax $$objs{'widget1'} is exactly equivalent to $objs->{'widget1'}, as you prefer.

    This hashing technique now lets you build an arbitrary directory of entries which allow you to map any name that you receive to everything that you need to know about it.   It also allows you to recognize, through exists(), if you have encountered a name that you have no information about.   There are many, many ways to write this, but the differences are unimportant; the central idea is the same.

    (If the search needs to be case-insensitive, simply use lc()to lowercase the string before using it as a hash-key, and likewise ensure that all inserted keys are lowercased.)

      Yes, that's precisely what I'll do. I don't know why I didn't think of using a hash. As I say in my other post, I guess I was too close to the problem to see the obvious answer. Thank you for taking the time to respond!