4 ms·
> Having a blog about programming languages and formal methods I understand the basis of your disgust with PHP. In a perfect world all programming languages wou
by gdp 17y ago
> Having a blog about programming languages and formal methods I understand the basis of your disgust with PHP. In a perfect world all programming languages would use robust type systems and be capable of formal verification. PHP makes no attempt at either.
Way to straw-man, dude! Nowhere did I suggest anything about perfect worlds or what programming languages should be like. I said that this particular feature of this particular language is undesirable because it introduces unnecessary complexity and risky levels of unpredictability into code that probably doesn't need to use it.
> Out in user land there are all sorts of scenarios where dynamic invocation makes sense. Higher-order functions are the most obvious. Is mapping strtolower on an array of strings really spaghetti code?
What does "dynamic invocation" have to do with higher-order functions? Pretty much everything described in the article deals only with functions as first-class values and unrestricted indirection. There is nothing "higher order" about them. If you're talking about implementing higher-order functions, then the only requirement is the ability to pass around functions as values. There is certainly no requirement for indirection on strings!
If functions are first-class values, that's absolutely fine. I'm complaining about situations where you end up passing names of functions around (as strings), and they take on special meanings along the way. I characterise this as spaghetti code because it leads to a situation whereby control flow is embedded both within constructs in the language, and within computed values based on using indirection on strings-indexing-functions. That's just nasty.
Just so I'm not misinterpreted, let me furnish my complaint with an example to show what I am and am not complaining about:
...
$x = "hello$z$k$y";
$x($foobar);
vs.
...
$x = function() { echo "foo"; };
$x();
The latter is (mostly) fine. The former is completely bonkers, and is what I am complaining about - the ability to do ad hoc indirection based on calculated values. In the first case, functions are not values, and strings have become semantically significant. In the latter case, the function is a first-class value, and there is absolutely no magic going on - everything is hunky dory.
> Most uses for dynamic invocation are at the utility/framework level, not in application land.
I still can only think of a few restricted cases where indirection based upon strings (that values of which are not known until runtime) would be sensible or useful. The kinds of cases I can think of are where you would want to do something really dubious based on user-input. Keep in mind that I'm not railing against reflection here! Any sensible dynamic language should be able to provide you with the means to get a function value based on a name. This is not what you are describing. I think name-based reflection could have a use in utility or framework code, but relying on this kind of unrestricted indirection is really just a sign of deeper problems, I think.
> You're right, it's dangerous when used improperly
Which uh... was my point.
> but you should consider coming down from the theory clouds if you believe dynamic invocation and goto are in the same boat on the river styx.
Once again, you appear to be rebutting an argument I never made. Suggesting that I'm some sort of aloof theoretician is really a bit presumptuous. I developed an interest in all of those things you describe precisely because I am a programmer. Sure, I know a reasonable amount about theory, but I don't see that that should be used to discount any and all knowledge I have about practical programming too.
Let me make very clear my objection, once again. I am going to leave out exactly one definition from each of the following code snippets:
foobar(0);
vs.
$x(0);
I left out the definition of 'foobar' in the first snippet, and the definition of '$x' in the second. Can you tell me where program control goes in each case?
In the first case, you know that it goes to a function named "foobar" somewhere within scope.
In the second case, of course you can't! You have to go figure out how $x has been computed. You basically have to read most of the code in order to find out what value $x will have just to be able to predict what the program will do next! This is basically the same problem that goto-style code creates - it makes it considerably more difficult to mentally simulate the execution of the program.
Edit: This is getting down-voted? Really? I would love to know why.
- KrisJordan 17y agoDidn't intend to cause harm in "straw-man"ing. I think it's valuable to know where people are coming from. You care enough about programming languages and verification to have a blog on it, that's awesome. It's perspective. No where in the post is there an example advocating dynamic invocation based on computed strings. No where. In fact, the more I read your responses the less I believe what you're saying has anything to do with the contents and examples of the post. We're on the same page here: dynamic invocation with computed strings: bad. spaghetti code. evil like eval. > What does "dynamic invocation" have to do with higher-order functions? Everything? Whether you're rolling your own or making use of PHP's built-in higher order functions, like array_map http://us.php.net/array_map http://us.php.net/array_map, you're dynamically invoking something: a lambda, a function, an instance method, or a static method. Unfortunately these are distinct things in PHP. So with array_map its first argument is a callback, or something that returns true to is_callable as described in the post. What you're arguing is that you should never send a string name of a function to array_map, but should instead wrap the invocation in a lambda. So.. array_map(function($s) { return strtolowwer($s); }, $array); Is preferable to: array_map('strtolowwer', $array); Point blank, it's just not in PHP. It's more than twice as slow, it takes more than twice the memory, and, most importantly is every bit as unsafe. Notice I misspelled lower with an extra w? Let's imagine that's a bug, a programmer's typo. Neither case will error out until array_map is executed which means both parse and generate opcode just fine. Reconsider the function call wrapped with in a lambda. What must it mean deep down for PHP to be able to generate valid opcodes on a pure method call to a method that doesn't exist? It means the internal opcode must simply store the method name as a string waiting to be executed. So once we hit the op a table lookup based on a string in your code happens. Both ways. One string is wrapped in quotes, the other in a far more elaborate construct. As for reflection, I'm all for it but in PHP a reflected function or method object is not a callable, thus cannot be passed to a function like array_map. Even if you could, I do not believe that, in PHP, the following is any less evil: array_map(new ReflectionFunction('strtolowwer'), $array); Again, more memory, more code to execute, won't error out until runtime. I really don't think you or I disagree on anything in terms of "best programming practices". The only thing we seem to disagree on is what this post was about and trying to demonstrate/advocate.
- 17y ago