elfs: (Default)
[personal profile] elfs

I was reading through the Wordpress source code, trying to figure out a problem for a contractor, when I saw the function compact().  When I saw it I boggled, read the description, and shook my head.

Compact() takes a list of variable names as strings, and returns a hash of those variable names and their values.   So if you have something like:

$title = "My blog";
$link = "foo";
$h = compact('title', 'link');

You get back a hash of array(’title’ => ‘My blog’, ‘link’ => ‘foo’).

That, to my thinking, is completely messed up.  You’re giving this function, which has its own scope, explicit permission to twiddle with variables in the current scope and create a new variable.  It’s one of those things that convinces me that PHP is an unholy mess of silliness.

And then my brain reminded me that, hey, you can do the exact same thing in python.  So, I have:

import inspect
def compact(*args):
    return dict([(i, inspect.currentframe().f_back.f_locals.get(i, None))
                 for i in args])

def foo():
    a = "blargh"
    b = "bleah"
    c = ['1', '2', '3']
    return compact('a', 'b', 'c')

print foo()

And sure enough, this spits out: {’a': ‘blargh’, ‘c’: ['1', '2', '3'], ‘b’: ‘bleah’}

I hang my head in shame for giving Django developers one more thing around which they can develop bad habits.

This entry was automatically cross-posted from Elf's technical journal, ElfSternberg.com

Date: 2009-05-14 06:34 pm (UTC)
From: [identity profile] ziggadon.livejournal.com
Does compact() in PHP actually fiddle with the variables though? I.e. does it return a hash of references, or just values of whatever those variables are at the moment?
If the latter I don't see why it's quite so terrible ;)

Date: 2009-05-14 06:38 pm (UTC)
From: [identity profile] elfs.livejournal.com
The answer to that question seems to be, "It depends." If the thing referenced can be dereferenced to a scalar, it copies-by-value; if the thing referenced is an object, it presents the reference. But that's true of Perl and Python, too. Scalars and natives are usually copy-by-value; objects are often copy-by-reference.

Date: 2009-05-14 06:42 pm (UTC)
From: [identity profile] shockwave77598.livejournal.com
What's wrong with combining two strings together?

Date: 2009-05-14 06:43 pm (UTC)
From: [identity profile] ziggadon.livejournal.com
Yeah, that makes sense, having dabbled in the three Ps on occasion (though referencing and dereferencing I am still just about getting my head around).

I'm still not convinced it's an altogether bad thing, but like most thing could quite easily be turned to the purposes of the dark side used to make a horrific mess.

Date: 2009-05-14 07:45 pm (UTC)
From: [identity profile] aprivatefox.livejournal.com
It's not that it's combining the strings - it's that it's explicitly making use of data in the outer scope.

When we write
$title = 'My Blog';
we create a variable in local scope, called $title, with contents of 'My Blog'.

When we call compact, we're calling it with the string 'title', not the variable $title. Which means that $title is never passed in to that function - that function should have no way of knowing the contents of $variable (which, in this example, is 'My Blog'). And yet, at the end of the unholy mess, somehow the hash that came back out has the content of that variable. Which is extremely counter to the intuitive notion of how scope ought to work; the child scope really ought to have the variables passed in explicitly if it wants to know about them.

Date: 2009-05-15 12:39 am (UTC)
From: [identity profile] tehrasha.livejournal.com
When we call compact, we're calling it with the string 'title', not the variable $title.

I thougth that was odd as well. What I still dont get is why the results of B and C are transposed in the python output?

Date: 2009-05-15 12:43 am (UTC)
From: [identity profile] elfs.livejournal.com
Oh! It's the same thing as in Perl: dictionaries (hashes) in Perl and Python don't maintain insertion order. They're pure hashes; the order in which they appear on output is determined by the hash representation of the key. It's PHP that's weird in that it maintains the order of insertions into a hash. PHP's hashes are slower for it, but that probably doesn't matter much in production.

Date: 2009-05-15 02:50 am (UTC)
bolindbergh: (Default)
From: [personal profile] bolindbergh
use PadWalker
    qw(peek_my peek_our);

sub compact
{
    my(%result,%my_our,$pkg);

    $pkg=caller(0);
    %my_our=(%{peek_my(1)},%{peek_our(1)});
    foreach my $var (@_) {
        if ($var =~ /[:']/) {
            no strict 'refs';

            $result{$var}=$$var;
        } elsif (defined(my $ref=$my_our{"\$$var"})) {
            $result{$var}=$$ref;
        } else {
            no strict 'refs';

            $result{$var}=${"${pkg}::$var"};
        }
    }
    \%result;
}

Date: 2009-05-15 06:35 pm (UTC)
From: [identity profile] elfs.livejournal.com
"PHP is a minor evil perpetrated and created by incompetent amateurs, whereas Perl is a great and insidious evil, perpetrated by skilled but perverted professionals." - Jon Ribbens

Profile

elfs: (Default)
Elf Sternberg

December 2025

S M T W T F S
 12345 6
78910111213
14151617181920
21222324252627
28293031   

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jan. 8th, 2026 11:16 am
Powered by Dreamwidth Studios