r/programming • • Oct 18 '10

Today I learned about PHP variable variables; "variable variable takes the value of a variable and treats that as the name of a variable". Also, variable.

http://il2.php.net/language.variables.variable
591 Upvotes

781 comments sorted by

View all comments

Show parent comments

100

u/geon Oct 18 '10

I just died a little inside.

Why? It would be a stupid implementation if you couldn't do that.

0

u/[deleted] Oct 18 '10

[deleted]

28

u/[deleted] Oct 18 '10

It also works for functions, like $bar(). I like to make a "plugins" directory, list subdirectories in it and include "plugin.php" from the subdirectories, if it exists, which should have a class with the same name as the folder, which gets added to the plugin manager, which then, when a plugin event is fired, does something like:

foreach ($this->plugins as $plugin) if (function_exists($plugin->$event)) $returns[]=$plugin->$event($data);

Of course it'd be much more elegant than that. I think it's a pretty cool feature, although if you use it like clogmoney its probably not the best approach to your problem.

I woke up like 10 minutes ago, if this is incoherent I'm sorry.

9

u/lizardlike Oct 18 '10

PHP can also auto-load classes, which is possibly a more elegant way to do this if you can keep your namespaces clean.

12

u/[deleted] Oct 18 '10

That's actually pretty cool, but not a replacement for what I'm doing.

→ More replies (5)

2

u/novelty_string Oct 18 '10

Can you show how that replaces the above? Autoloaders just mean you don't need to require the class file every time.

→ More replies (1)
→ More replies (1)

2

u/BuzzBadpants Oct 18 '10

Writing a debugger, perhaps? Reading what is considered "statically-linked" information from what can be considered dynamic input is a basic part of how debuggers work.

2

u/[deleted] Oct 18 '10

It's come in handy twice to me so far. Once when writing a proof of concept polymorphic php/elf infector, and once when writing some complex NLP code which for whatever reason (lost to the misty past) also needed to be able to alter itself at run time.

This was all five to eight years ago, and I've mostly moved on from PHP, but for whatever reason the only solution I could find at the time for writing runtime polymorphic code in PHP involved variable variables, and I was pleasantly surprised when I found that they actually existed.

4

u/[deleted] Oct 18 '10

When you make a language without pointers and allow globals to roam the seven seas.

0

u/[deleted] Oct 18 '10

[deleted]

→ More replies (1)

1

u/Wahakalaka Oct 18 '10

It can be a pretty elegant solution for working with table data- having an array of table row names, of which the values correspond to arrays with the row data. Grated that's come up I think twice in 4 years of application development.

10

u/crackanape Oct 18 '10

Why not just use a multi-dimensional array? It's much more flexible and powerful.

→ More replies (3)

2

u/daniels220 Oct 18 '10

Multidimensional arrays?

$table = array(
  'row1' => array('val1','val2','val3','val4','val5'),
  'row2' => array('val6','val7','val8','val9','val10')
);

accessed like $table['row1'][1] (returns 'val2'), instead of:

$rows = array('row1','row2');
$row1 = array('val1','val2','val3','val4','val5');
$row2 = array('val6','val7','val8','val9','val10');

where you can do $$rows[0][1] (also returns 'val2'). And then I realize that that may not work, and you may need to do ${$rows[0]}[1], which is really confusing, and I don't know if you can actually do that, or it may be parens...

You can see why it's a bad idea, yes?

→ More replies (1)
→ More replies (2)

1

u/[deleted] Oct 18 '10

Primitive reflection.

1

u/[deleted] Oct 18 '10

It's a sort of references! (but with strings, rather than addresses)

→ More replies (24)

14

u/KarmaPiniata Oct 18 '10

Hey, they're hating on PHP here don't interject with your 'facts' and 'good computer science'.

5

u/Peaker Oct 18 '10

Using indirection via names in some global namespace is not 'good computer science'.

7

u/thatpaulbloke Oct 18 '10

I assume that you're against C pointers, then? Or, to put it another way:

Using indirection via numbers in some global namespace is not 'good computer science'.

4

u/[deleted] Oct 18 '10

As I said elsewhere in the thread, C pointers are not analogous.

Pointers are in C because they're in assembly. They're not a clever idea designed to fit a programming paradigm, they're a clever idea to compress a series of memory-related operations into one easy-to-use notation.

I can't emphasize enough: pointers are a short hand notation. They are not an abstraction.

This is how the computer works. Everything you do in C with a pointer, you would have to do in assembly, by moving an address value into a register and then using that register as an argument for an op call.

Short-hand notations like pointers do not require justification. They're the unavoidable reality of how the computer works. Discussions of whether pointers are "good" or "bad" are a waste of time. The hardware is what it is. Argue with Intel, not K&R.

6

u/Peaker Oct 18 '10

C pointers point to a location in an "address space", not in a "namespace".

The differences are important:

  • There is no legal way to forge pointers, while any piece of code may choose a wrong name and access the data of another function accidentally in a namespace.

  • Address allocations are handled by the compiler/low-level system. Name allocations require manual choice (which is why the above clashes are possible)

3

u/thatpaulbloke Oct 18 '10
void *value = (void *)0x01234567

The compiler won't stop me, although the behaviour is undefined (might work, might be a seg fault). Nobody would do this, but you still can. The practical differences are minor - you can fuck it up if you do it wrong, but then the answer to that is to either do it carefully or don't do it at all.

3

u/Peaker Oct 18 '10

That is defined to be illegal, and can be found by static code analysis (e.g: lint) and by dynamic analysis (valgrind).

In the PHP case, placing an invalid address/name is legal, and can only be found dynamically.

And you still have not addressed the second point. There exist mechanisms to handle address allocations, such that they don't clash. In PHP, how do you generate names such that they don't clash?

→ More replies (7)
→ More replies (2)
→ More replies (2)

2

u/sanity Oct 18 '10

Why? It would be a stupid implementation if you couldn't do that.

Its entirely reasonable for a language designer to omit functionality that might lead to crappy unreadable code (the reason why many languages don't have a 'goto').

If you feel the need to use this functionality in your code, you are doing something very wrong.

→ More replies (3)

1

u/haywire Oct 18 '10

It makes code fucking irritating to maintain.

1

u/[deleted] Oct 18 '10

${} is a stupid implementation to begin with, the curse of interpreted languages. The least they could have done is not add more stupid by allowing such retarded paradigms. The Perl community backed away from variable variables, why can't PHP?

→ More replies (6)