Hacker News new | comments | show | ask | jobs | submit login

What makes ME sad is no keyword arguments. Helper/wrapper functions either get an annoying and difficult-to-grok-at-glance associative-array for it's params (bad), or a huge list of rarely-used parameters (worse), or a huge set of wrapper functions to set their own paramters (even worse), or outright duplicated functions for similar-but-not-quite tasks (worst).

This happens to me while producing something like a jqGrid, or other javascript/html hybrid stuff that need a few extra options sometimes.

Django/Python? No problem! Just use the keywords you need.

(More Info: The difference between a single associative param standing in for keywords arguments, or a huge list of regular arguments is a choice in complexity/readability IN the function vs. calling it.

For the single dictionary approach, you lost the built-in parameter defaults nicety, which means you need to handle the case of a missing parameter manually. This kind of sucks, especially if you hate seeing PHP Notices during development (which kill JSON/XML output anyway). This makes your function often twice as big (or more) than it needs to be.

For the other approach, you wind up with calling

  foo("","","","real value", true, true, 2, false, false, "option I want");*
which just about invites all sorts of hard-to-find bugs, and you have to look at the function definition every time you want to change an option. Also, it's flat-out rude if you aren't the one calling the function.)



compact() + extract() is the closest you get.

  $foo = 123;
  $bar = getSomeBar();

  myFunction(compact('foo', 'bar'));


  function myFunction($kwargs) {
    $foo = SOME_DEFAULT_VALUE;
    extract($kwargs);
    if ($foo > 5) {
       ...
    }
  }

If you want to `sanitize' which arguments can be passed that way, use extract(array_intersect_key($allowed, $kwargs)); ((EDIT: or use EXTR_IF_EXISTS)).

Nb., extract() works on any associative array, you don't have to use compact().


Why would this be any better than just passing in a map of the parameters as the sole parameter?

  myFunction($parms=array()) {
     ...
  }
  
  $parms = array('foo' => 'bar',
                 'baz' => 'yaz');
  test($parms);


Concise. Documented, standard and configurable handling of existing variables (may be used for default values etc.) via EXTR_OVERWRITE, EXTR_SKIP, etc. Documented, standard behavior of compact() in regard to missing variables. No manual associating of foo with $foo -- less places for mundane errors.

Oh, and there's even that EXTR_IF_EXISTS -- so my silly idea to sanitize with array_intersect_keys() was totally unneeded. Make it

  $foo = 123;
  $bar = getSomeBar();
  $coot = 'boot';
  myFunc(compact('foo', 'bar', 'coot'));

  function myFunc($kwargs) {
    $foo = 1;
    $bar = 'xyz';
    extract($kwargs, EXTR_IF_EXISTS); /* sanitization: $coot will NOT get extracted 
        because the function doesn't expect / support that argument */
    ...
  }


In case you weren't sure on this, it is exactly the same. Compact takes a list of variables names in the local scope and returns an associative array containing their values.


You can use the @ symbol to suppress errors when you're aware that the variable may be empty and you've considered the possible effects. When I used to write PHP, I'd often write something like

    do_something(@$_GET['foobar']);
There are ways to suppress PHP notices without just turning off the E_NOTICE output.


It shouldn't be ok to write code that is known to throw an error, and handle it by suppressing that error. Silently failing code is just a bug waiting to happen.

It's also making the interpreter do unnecessary error handling work when a simple "if ($_GET['foobar'])" would suffice.


It should be ok (the poor PHP implementation aside). Auto-vivification is something that's very useful in Perl and I miss it greatly in the languages I program in now. Being able to do this:

    $one->{ two }->{ three } = [ $four ]
Without having to check every link for definedness makes for cleaner code, IMO. Making it optional "suppressing that error" would be a good middle-ground.

Coffeescipt has the existential operator, not quite on a par with Perl's autovivification, which allows:

    zip = lottery.drawWinner?().address?.zipcode


The Coffeescript ? operator is certainly quite handy. I suppose it's explicit nature is what helps, as information on the error you're trying to mask is built into the syntax. With @ in PHP however, you simply don't know what it's trying to stop, and what undesirable affects it may cause, which I think is the main objection to it.


It's inefficient to do that, as from what I understand PHP actually sets the error level to none, processes that line, sets it back, and continues. Also it would suppress any other warnings from that line, which could be unrelated to the supplied argument value.

Instead, I use a 'get or else' function, as in some functional languages. For arrays, it goes

    function get_or_else($array,$key,$default=null)
       { return isset($array[$key]) ? $array[$key] : $default; }
This avoids any warnings, and also allows you to specify a default.


I wasn't aware of that implementation detail. Hey, now I respect PHP even less than I did before.

Your solution makes for some good boilerplate, but things like that are exactly why I use Python for everything it makes sense for: these things are baked into the language (in Python it would be array.get(key, default) ).


Yeah, it's part of Scala's type system, too - (Option, and Some or None. Better language designers go to great lengths to make simple things like null values well covered). Python will throw a fatal error and exits on reference to a nonexistent Dictionary key, but PHP blithely fills in the value with something falsy and continues.

I'd rather be using Python too, but for some apps we have to work with a lot of PHP legacy code, so I do what I can.


To be fair, Python doesn't throw a fatal error. It throws an Exception, which most people know to handle. The idiom is use a try/except block, but if you're clever you can usually avoid the need.

Scala borrows the option types from SML (or, at least, SML has them and is much older). I love SML for its strict semantics (if something passes through the type system it most likely works as expected), but sadly design really doesn't inform platform choice (case in point: C++ is still common. I don't hate it as much as some people do, but it can't be said to be particularly well designed).


Hey, in case you are interested I constructed a reply to your post here: http://commonphp.blogspot.com/2011/05/keyword-functions-in-p...

In a nut shell though it's essentially a write up of my library which allows for creating keyword function wrappers so you can do stuff like:

   myStrPos(
       needle, 'peter', 
       haystack, 'is peter in here?'
   );


Isn't a wrapper function the solution to this? Or even... a wrapper function that takes an associative array of options as an argument.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | DMCA | Apply to YC | Contact

Search: