Created
January 19, 2012 13:48
-
-
Save aerosol/1640124 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| +---------------------------------------------------+ | |
| | The following takes place between 03:00 and 04:30 | | |
| +---------------------------------------------------+ | |
| 03:00 * toxik snickers | |
| 03:02 < toxik> [in #php] | |
| 03:02 < toxik> <@toxik> PHP -- one of few languages where a string can be false | |
| without being empty. | |
| 03:02 < toxik> <@toxik> And that's a god damn feature. :-) | |
| 03:02 < toxik> < Seph> a string should be neither true nor false, it should be | |
| a damn string unless explicitly converted | |
| 03:02 < toxik> <@toxik> Yes, explicit is better than implicit. But practicality | |
| beats purity. | |
| 03:12 < tappi> right | |
| 03:12 < tappi> what does string being true or false mean | |
| 03:12 < toxik> In PHP, if ("0") { ... } will never execute the inside. | |
| 03:13 < buster> omg | |
| 03:13 < buster> and thats intended? | |
| 03:13 < toxik> Yes. | |
| 03:13 < buster> lol. | |
| 03:13 < tappi> string is a string unless converted, either explicitely or | |
| implicitely :P | |
| 03:14 < toxik> However, if (array(0)) { ... } -will- execute, don't ask me. | |
| 03:14 < buster> haha.. like testing some inutstringsfrom websites and feiling | |
| if the user entered 0 | |
| 03:14 < buster> hahahaha | |
| 03:14 < buster> *failing | |
| 03:15 < toxik> Oh yeah, but they have an operator for that. | |
| 03:15 < toxik> if ($x === "0") and you'll know if it _really_ is "0". | |
| 03:16 < buster> lol@ === | |
| 03:16 < buster> if( 8===D ) | |
| 03:16 < buster> <3 | |
| 03:16 < tappi> :D | |
| 03:16 < toxik> That actually works | |
| 03:16 < toxik> If you define the constant D first. | |
| 03:17 < buster> and thats why php actually stands for penis horsepower | |
| 03:18 < toxik> You know what's handy though? You can define a class named D, a | |
| function named D, and a constant named D, and be able to refer | |
| to them the exact same way without having to worry. Anywhere in | |
| your code! | |
| 03:18 < toxik> Like so: $D = new D(D(), D); | |
| 03:18 < tappi> yes, i so like it when a language allows me to shoot me in my foot | |
| 03:18 < buster> omfg | |
| 03:19 < buster> no i begin to hate php, toxik, thanks | |
| 03:19 < toxik> But I'm not even started! | |
| 03:20 < buster> i always thought of it like "oh well, looks creepy, wont use | |
| that.. but it's so widely sed, should have some good things" | |
| 03:20 < buster> :F | |
| 03:20 < buster> *used | |
| 03:20 < buster> i''ve read some articles about how bad php is | |
| 03:20 < toxik> Let's move on to one of the larger WTFs -- echo and print. | |
| 03:20 < buster> mostly they complain about classes and stuff | |
| 03:20 < buster> but thats some basic stuff which is really really sucky | |
| 03:21 < toxik> echo, its syntax is simple: echo "foo"; | |
| 03:21 < toxik> Notice how it's not a function? Well, we can accept that. Python | |
| had the print statement and all. It's relics. | |
| 03:21 < toxik> So then. print, simple: print("foo"); | |
| 03:22 < toxik> So, you might be asking, what does print return? int(0). | |
| 03:22 < toxik> Now what on Earth is wrong with that, you ask. | |
| 03:22 < toxik> I'll show you. | |
| 03:22 < toxik> $ php -r 'var_dump(function_exists("print"));' | |
| 03:22 < toxik> bool(false) | |
| 03:22 < toxik> print isn't a function. | |
| 03:22 < toxik> It has the exact same syntax. It has a return value. But it's not. | |
| 03:23 < buster> wtf | |
| 03:23 < buster> hey, so you can overwrite print | |
| 03:23 < toxik> They could _easily_ replace it with a real function and have the | |
| language be a lot cleaner (as you could use it in callbacks) -- but no. | |
| 03:23 < toxik> Oh, no. | |
| 03:23 < toxik> God no. | |
| 03:23 < toxik> PHP's parser treats print and echo like their own tokens-- | |
| because they're so-called language constructs. | |
| 03:24 < toxik> If you try to do function print() {}, you'll get a parse error. | |
| 03:24 < toxik> After all, why would you be trying to print in the middle of a | |
| function definition? | |
| 03:24 < buster> hahaha | |
| 03:24 < buster> those are really scary things | |
| 03:25 < toxik> So yeah, that's some of the finer parts of PHP. | |
| 03:25 < buster> and that they didnt "fix" this stuff in all those years.. | |
| somehow.. i think php doesnt come forward :F | |
| 03:25 < toxik> Oh no no no, don't think that. PHP is evolving! Into Java. | |
| 03:25 < toxik> PHP has type hinting. Really. You can do: | |
| function foo(TheClass $foo) { ... } | |
| 03:26 < buster> :o | |
| 03:26 < toxik> However, you can't really do that with array, string, int, or | |
| any other basic type. Because they're that: types, their own | |
| tokens. So why would you be declaring an array or a string | |
| before an argument, the parser asks. | |
| 03:26 < buster> hahahaha | |
| 03:26 < buster> ROFL | |
| 03:26 < buster> thats awesome | |
| 03:27 < buster> can't be true | |
| 03:27 < buster> lies! | |
| 03:27 < toxik> PHP /is/ awesome. | |
| 03:27 < buster> roflrofl | |
| 03:27 < toxik> Want to hear about PHP references? | |
| 03:27 < toxik> Because those are a great story, too. | |
| 03:27 < buster> also, wasn't there some discussion abotu some new operator? and | |
| they chose like the shittiest character available? :o | |
| 03:27 < toxik> Oh yeah, but I'll save that for later. | |
| 03:27 < buster> <3 | |
| 03:28 < toxik> References first. They're funny business. | |
| 03:28 < buster> toxiks bedtimestories | |
| 03:28 < toxik> :> | |
| 03:28 < toxik> I'm preparing examples for this one, 2 ticks. | |
| 03:28 < buster> ye | |
| 03:30 < toxik> <?php | |
| function my_fun1($x) { $x[] = "foo"; } | |
| function my_fun2(&$x) { $x[] = "bar"; } | |
| // Note how the array "type" has its own unique syntax. <3 | |
| $innocent_array = array(hello => "world"); | |
| my_fun1($innocent_array); var_dump($innocent_array); | |
| /* array(1) { | |
| ["hello"]=> | |
| string(5) "world" | |
| } */ | |
| my_fun2($innocent_array); var_dump($innocent_array); | |
| /* array(2) { | |
| ["hello"]=> | |
| string(5) "world" | |
| [0]=> | |
| string(3) "bar" | |
| } */ | |
| ?> | |
| 03:30 < toxik> PHP is programming with potentially hidden side-effects. | |
| 03:30 < toxik> Note my_fun2, the argument has been declared as "a reference". | |
| 03:31 < buster> i see | |
| 03:31 < toxik> Note how my_fun2 can mutilate the array in any way it likes, | |
| without the code at line 22 knowing about it. | |
| 03:31 < toxik> Now, this is what we're used to in Python. | |
| 03:31 < toxik> Because we _always_ pass by reference. | |
| 03:32 < toxik> However, in PHP, this isn't common at all. In fact, I'm fairly | |
| sure they've deprecated it. | |
| 03:32 < toxik> That, or the other way around -- see PHP can also force a | |
| function to take a reference. | |
| 03:32 < toxik> Consider my_fun1(&$innocent_array);, its effect is that of line 22. | |
| 03:32 < buster> ye | |
| 03:33 < toxik> Now, I know, you're thinking: this isn't much of a WTF. | |
| 03:33 < buster> actually | |
| 03:33 < toxik> But I'm not done. Because this has to do with their "OOP". | |
| 03:33 < buster> i dont get why fun1 doesnt do shit to the array | |
| 03:33 < buster> :p | |
| 03:33 < toxik> Oh, PHP copies the entire memory area. | |
| 03:33 < buster> ahhh, ok, i get it | |
| 03:33 < buster> it writes into the copy | |
| 03:33 < buster> yeyeye | |
| 03:34 < toxik> (Actually I recall ekneuss telling me how smart they've made PHP | |
| about that, it only copies if you modify it, so in our example, | |
| it should.) | |
| 03:34 < toxik> But before I go into OOP, think about that for a second. | |
| 03:34 < buster> not used to that anymore | |
| 03:34 < toxik> PHP copies every value passed if you modify it. | |
| 03:34 < toxik> Can you even imagine the performance wreakage if you pass | |
| marginally large datasets? | |
| 03:34 < buster> ye | |
| 03:35 < toxik> Allocate, copy, free, repeat. | |
| 03:35 < toxik> Insanity. | |
| 03:35 < toxik> Anyway. | |
| 03:35 < toxik> So, as you might've noticed, PHP's built with pass-by-value, | |
| just like VB6. Though not a very wise choice, they made it. | |
| 03:35 < tappi> lol :P | |
| 03:35 < toxik> Now ponder that for two seconds. | |
| 03:35 < toxik> What does that mean if you pass objects? | |
| 03:36 < buster> wait | |
| 03:36 < buster> i bet objects/classes are passed by refernce always | |
| 03:36 < buster> :p | |
| 03:36 < buster> no? | |
| 03:36 < toxik> Let's go back a few years to PHP 4, when OOP was introduced. | |
| 03:36 < toxik> "For real" | |
| 03:36 < buster> :> | |
| 03:36 < toxik> Let me give you an example of the generic PHP OOP. | |
| 03:37 < toxik> class Klass { ... } | |
| // Important to note: THIS IS NOT &=. That means "binary and". | |
| // This is "Set to reference of". | |
| $my_obj =& new Klass(); | |
| fun($my_obj); | |
| 03:38 < toxik> Now that's already a WTF in itself and I don't see how they | |
| couldn't see that themselves, but anyway. | |
| 03:38 < buster> :o | |
| 03:38 < toxik> Note how $my_obj now is a... reference variable? What? | |
| 03:38 < buster> so my obj is the pointer to a new klass | |
| 03:39 < toxik> No no, line 9 there is the PHP equivalent of "my_obj = Klass()" | |
| 03:39 < toxik> So, if you missed doing =& instead of =, you'd be having your | |
| object copied _all over the place_, like really. | |
| 03:40 < toxik> Or, alternatively, if you typed &=, you'd be doing binary and | |
| between an uninitialized variable and a new object. Meaningful? | |
| No. Did it stop scripts? No. Because that's non-fatal in PHP. | |
| 03:40 < buster> hha :> | |
| 03:40 < toxik> (That, by the way, is another _major_ WTF in PHP. Error handling.) | |
| 03:40 < buster> thats all so retarded stuff :> | |
| 03:40 < toxik> Forward to PHP 5, current stable. | |
| 03:41 < toxik> Same example, only now $my_obj = new Klass(); will suffice, for | |
| $my_obj will become a reference anyway. Is that consistent? No. | |
| Is that expected? No. | |
| 03:41 < toxik> At least they stopped reallocating memory all over the place. | |
| 03:42 < buster> i see | |
| 03:42 < buster> lol :> | |
| 03:42 < buster> ?? php | |
| 03:42 < buster> :> | |
| 03:42 < toxik> So that's how PHP's implicit reference variables came to be, and | |
| I hope you'll understand when you read PHP code that makes no | |
| logical sense. | |
| 03:43 < toxik> And now, let's discuss pseudo-variables. | |
| 03:43 < buster> :o | |
| 03:43 < toxik> PHP has this very, very awkward way of dynamically looking up | |
| variable names. | |
| 03:43 < toxik> If you do $x = "a"; $z = "x"; echo $$z; you'll get "a". | |
| 03:43 < buster> actually i started with php and webprogramming, like everyone | |
| else i guess.. bu ti don't remember much of it | |
| 03:44 < buster> what? | |
| 03:44 < buster> whats $$? | |
| 03:44 < buster> oic | |
| 03:44 < toxik> Further, if you also did $a = "z"; you could do: | |
| $$$$$$$$$$$$$$$$$$$$$$$$$$$z | |
| 03:44 < buster> the variable with the name of the content of the second one... | |
| if it would be like that :p | |
| 03:44 < toxik> $ php -r '$x = "a"; $z = "x"; $a = "z"; echo $$$$$$$$$$$$$$$$z;' | |
| 03:44 < toxik> x | |
| 03:45 < toxik> Now, you might feel it's a little bit over the top to implement | |
| a language feature just to do this (locals() anyone?) but the | |
| PHP team made | |
| their decision. | |
| 03:45 < toxik> So, as fate has it, this often turns out to be moderately useful | |
| in templating engines. | |
| 03:46 < toxik> Now, quick reminder of PHP OOP: | |
| class X { function meth() { echo $this->blah; } } | |
| 03:46 < buster> aye | |
| 03:46 < toxik> Fair enough, you say. | |
| 03:46 < toxik> Well, what if I were to make it: | |
| function meth() { $x = "this"; echo $$x->blah; } | |
| 03:46 < toxik> Would it work? | |
| 03:46 < toxik> No. | |
| 03:47 < toxik> Why? Guess why. | |
| 03:47 < buster> wtf | |
| 03:47 < buster> dunno :< | |
| 03:47 < toxik> Come on, I dare you. | |
| 03:48 < toxik> Take a moment, and brace yourself: $this is not a variable. | |
| 03:48 < buster> because.. String has no bla | |
| 03:48 < buster> :F | |
| 03:48 < toxik> $this. is. not. a. fucking. variable. | |
| 03:48 < toxik> It's _pseudo-variable_. | |
| 03:49 < buster> oh, so $this is just another hacked in stuff thing | |
| 03:49 < toxik> Exactly. | |
| 03:49 < buster> nice :) | |
| 03:49 < toxik> I'm not even going to discuss PHP's upcasting mechanism (super). | |
| 03:49 < toxik> It's... Impolitely weird. | |
| 03:50 < toxik> So, where were we. Oh right, the funny operator. | |
| 03:50 < buster> do you think this should work? all the $$x crap? its scary | |
| 03:50 < toxik> Oh but it does work. | |
| 03:50 < buster> yeah, the namespace separator. i remembered :p | |
| 03:50 < toxik> But not with this. | |
| 03:50 < buster> well.. dunno.. it just cries for bugs and exploitable code i guess | |
| 03:51 < toxik> Well yeah, but it's PHP. Come on. It has register_globals. | |
| 03:52 < buster> wanst that some scary stuff that is highly recommended to be | |
| turned off? :p | |
| 03:52 < buster> i remember years ago when every fucking php software brocke | |
| when you followed the recommendation | |
| 03:52 < toxik> Yeah, it was a very, very bad idea from the start. | |
| 03:53 < toxik> But let me show you one fun example of pseudo-variable $this. | |
| 03:53 < buster> :) | |
| 03:53 < toxik> class K { function m() { $x = "this"; var_dump($$x); } } | |
| new K(); -- doesn't work, right. I showed you before. | |
| 03:54 < toxik> (It works though, just prints NULL. See, referencing inexistant | |
| variables is non-fatal, but you know that.) | |
| 03:54 < buster> i see | |
| 03:54 < toxik> Now... The version that does work: | |
| class K { function k() { $z = $this; $x = "z"; var_dump($$x); } } | |
| 03:55 < toxik> If you just assign $this to another variable, you can reference | |
| that instead. | |
| 03:55 < toxik> Weird? Yes. | |
| 03:55 < buster> lol | |
| 03:55 < buster> yes get it | |
| 03:55 < buster> hah | |
| 03:55 < toxik> So maybe you're thinking, "What, but just do $this = $this;" | |
| 03:55 < toxik> But NO! FATAL ERROR! | |
| 03:55 < toxik> Fatal error: Cannot re-assign $this in /home/toxik/- on line 4 | |
| 03:56 < buster> wtf | |
| 03:56 < buster> mh | |
| 03:56 < toxik> So, get this: in order to get $$x to work in my example, you | |
| have to call an outside plain function and pass it $this as an | |
| argument. | |
| 03:56 < toxik> YAY OOP! | |
| 03:57 < buster> :> | |
| 03:57 < toxik> And another piece of brokeness. | |
| 03:58 < toxik> Suppose you have object $car with attribute "color", | |
| $car->color, right. | |
| 03:58 < buster> yep | |
| 03:58 < toxik> With the dynamic reference thing, you could do, | |
| $x = "color"; echo $car->$x; -- not that weird, expected in a way. | |
| 03:59 < toxik> If you had a class Car with class constant numWheels, you could do | |
| Car::numWheels, right. | |
| 03:59 < buster> i find it creepy | |
| 03:59 < buster> ye | |
| 03:59 < toxik> BUT! You couldn't do the equivalent: $x = "numWheels"; echo Car::$x; | |
| 03:59 < toxik> Because you just fucking can't. | |
| 03:59 < buster> rofl | |
| 04:00 < buster> i like that, php sounds like an adventure, everytimeyou think | |
| you get it, another thing comes up, you'll never stop learning | |
| and advancing | |
| 04:00 < buster> like a labyrinth | |
| 04:00 < toxik> Yeah. | |
| 04:01 < toxik> I think it's their strategy: make it so convoluted that once you | |
| learn, everything else gets too easy to remember. | |
| 04:01 < toxik> You need the challenge, dammit! | |
| 04:01 < buster> haha, yes | |
| 04:01 < toxik> Fuck binary trees and any interesting topic, the language should | |
| pose the bigger challenge! | |
| 04:01 < buster> also, can you have numWheels as variable and function? | |
| 04:01 < toxik> Of /course/ | |
| 04:01 < toxik> (Actually need to double-check that one.) | |
| 04:02 < buster> so i suppose php doesnt have the python thingy variable() | |
| 04:02 < buster> you know.. dunno whats it called to call a method "in a variable" | |
| 04:02 < buster> :p | |
| 04:02 < toxik> Ah, yeah. You can. | |
| 04:02 < toxik> Day is saved. | |
| 04:02 < buster> and what does it call then? :o | |
| 04:03 < buster> the variable or the method? | |
| 04:03 < toxik> I meant this: | |
| class K { | |
| var $m = "HI!"; | |
| function m() { echo $this->m; } | |
| } | |
| $t = new K(); $t->m(); | |
| 04:03 < buster> sounds like fun! | |
| 04:03 < toxik> Prints "HI!" | |
| 04:03 < toxik> But buster, sigh. You can't reference methods or functions like that. | |
| 04:04 < toxik> If you mean to do the function call equivalent of dynamic | |
| variable thingy, you do it using strings for functions. | |
| 04:04 < toxik> Like so: function x() { ... } $k = "x"; $k(); | |
| 04:04 < buster> yeah | |
| 04:04 < toxik> The reason is that in PHP, functions are part of a global | |
| registry consisting only of their name. | |
| 04:05 < toxik> Just like in C: flat namespace. | |
| 04:05 < buster> yes | |
| 04:05 < toxik> Only in C you can actually get addresses of functions and that. | |
| 04:05 < toxik> So PHP's actually more inflexible on that front, but eh. | |
| 04:05 < toxik> Hard to beat a new-thinking language like C. | |
| 04:05 < toxik> I suppose. | |
| 04:06 < buster> haha | |
| 04:06 < toxik> Anyhow, so. buster, guess how you'd do the $k() thing for | |
| methods on instances! | |
| 04:07 < buster> $k = "instance->x"; ? | |
| 04:07 < toxik> Nope. Sorry. | |
| 04:07 < toxik> It's... *tension rises* ... $k = array($instance, "meth"); $k(); | |
| 04:08 < buster> that doesnt make the slightest sense | |
| 04:08 < buster> like | |
| 04:08 < toxik> Nope! | |
| 04:08 < buster> not at all | |
| 04:08 < buster> wtf =D | |
| 04:09 < toxik> At least you can call static methods with: | |
| $k = array("Klass", "smeth"); $k(); | |
| 04:09 < buster> acually i can imagine how many people use this stuff because | |
| they think it's some advanced optimized php stuff and to show | |
| their mad skills | |
| 04:09 < buster> creepy | |
| 04:09 < toxik> I used to. | |
| 04:09 < buster> omg | |
| 04:10 < buster> i'd kill you if i were to read sour sources | |
| 04:10 < toxik> But uno mas. | |
| 04:10 < buster> *your | |
| 04:10 < toxik> You know of Python's f(*args), right? | |
| 04:10 < buster> ye | |
| 04:10 < toxik> Try the equivalent in PHP. | |
| 04:11 < buster> i bet * isn't allowed because it multiplies stuff | |
| 04:11 < buster> :> | |
| 04:11 < toxik> I understand if you had no idea how to do it. | |
| 04:11 < toxik> The answer is, ironically, a function this time. | |
| 04:11 < toxik> call_user_func_array("f", $args); | |
| 04:11 < buster> hu? | |
| 04:12 < toxik> Were you to do it on a method, you'd have a pretty nice long | |
| line right there. | |
| 04:12 < buster> call_user_.... is a builtin or what? | |
| 04:12 < toxik> Yup. | |
| 04:12 < toxik> http://se.php.net/call_user_func_array | |
| 04:12 < buster> haha | |
| 04:12 < buster> amazing | |
| 04:12 < toxik> Its other cousin, call_user_func, is less useful. | |
| 04:12 < toxik> It actually has no use at all. | |
| 04:12 < toxik> All it does is $k($x1, $xN...); | |
| 04:13 < buster> how can one come up with thi sshit if one designs a language? i | |
| mean.. it has been solved in every language before | |
| 04:13 < toxik> The name I have no idea they chose. Something like "call" and | |
| "call_args" would've been fine, but no. | |
| 04:14 < toxik> And as I said, call_user_func($callback, ...) is a mimic of | |
| $callback(...). | |
| 04:14 < toxik> Only it's even worse. | |
| 04:14 < buster> hehehe | |
| 04:14 < toxik> If you read the manual you'll note that you can't use our | |
| beloved references with call_user_func. | |
| 04:14 < buster> lol | |
| 04:14 < toxik> For that, they recommend call_user_func_array($callback, array(&$arg)); | |
| 04:14 < buster> you youll copy everything with it | |
| 04:14 < buster> :> | |
| 04:14 < toxik> And yes-- array indices can actually be references! | |
| 04:15 < toxik> Now let's discuss lambdas. | |
| 04:15 < toxik> Just briefly. | |
| 04:16 < toxik> Lambdas have their issues. | |
| 04:16 < toxik> But PHP's implementation is just... dirty. | |
| 04:16 < toxik> Classically it's known as create_function(). | |
| 04:16 < toxik> It returns "a callback" | |
| 04:16 < toxik> Which is actually a string of random letters assigned as a name | |
| for a generated function. | |
| 04:16 < toxik> So all they do is make a new function with a random name. | |
| 04:17 < toxik> Not very anonymous at all, you'd argue. | |
| 04:17 < buster> yes | |
| 04:17 < toxik> And I can't counter that. | |
| 04:17 < buster> :p | |
| 04:17 < buster> actually i have headaches like hell | |
| 04:17 < buster> but that cheered me up | |
| 04:17 < buster> \o/ | |
| 04:18 < buster> nerdtalk | |
| 04:18 < toxik> \o/ | |
| 04:18 < toxik> (Now please post log kthx.) | |
| 04:19 < toxik> There are actually many more things in PHP which I could rant | |
| about, like the terribly broken error reporting or the | |
| namespaces, but I really need to sleep. :< | |
| 04:19 < buster> have to get it from lurky i guess, one moment | |
| 04:20 < toxik> One of the fundamentally broken things I've been angry about is | |
| the type hinting too. | |
| 04:21 < toxik> You know, they took the idea from Java and the likes. Only they | |
| neglected one fine detail: Java is a strongly typed fucking | |
| language. In Java, types matter. In PHP, "0" is false. | |
| 04:23 < toxik> An elementary usecase: In Java, you could say "I expect a | |
| collection of integers in this argument." | |
| 04:23 < toxik> In PHP, you don't have that typing. At best (but you can't | |
| because of previously mentioned parsing issues), you'd be able | |
| to say "I want an array." | |
| 04:23 < toxik> At which point you lost the whole point in type hinting. | |
| 04:24 < toxik> How could they not see that this is funda-fucking-mentally broken? | |
| That concludes the rant, but it doesn't exhaustively list everything that's | |
| wrong with PHP. Far from it. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment