Hacker News new | past | comments | ask | show | jobs | submit login
Underscore.php (brianhaveri.github.com)
142 points by j-ashkenas on Aug 9, 2011 | hide | past | favorite | 50 comments



This will be even more aesthetically pleasing once PHP 5.4 is released with support for array literals:

    __::map([1, 2, 3]), function($n) { return $n * 2; });
    __([1, 2, 3])->map(function($n) { return $n * 2; });
That, combined with array dereferencing (ie, explode(",",$str)[0] ), PHP will start to look a lot like JavaScript.


> This will be even more aesthetically

You're asserting it's currently pleasing...

And most of those functions generally are not used with array literals (because the array is the data you're workin on/transforming, just do the transformation statically if you have an array literal), so array literals don't have much value for such a library, it only improves the examples.


> PHP will start to look a lot like Perl.

You had a typo, there.


For all of its other sins, simple functional programming (that is, first-order functions and the basic uses thereof, rather than immutability and the other more modern FP characteristics) is easier than in most languages. In fact it's easier in Perl than in Erlang, a putatively-functional language!

    map { $_ * 2 } (1, 2, 3)                   - Perl
    lists:map(fun (X) -> X * 2 end, [1, 2, 3]) - Erlang
    map (*2) [1, 2, 3]                         - Haskell
The last one for comparison. Erlang can do better with a list comprehension, though:

    [X * 2 | X <- [1, 2, 3]]
which except for case also works for Haskell. But that exclusively works with only map and filter (in Erlang [1]), Erlang is still surprisingly klunkier than Perl for everything else (folds, actually passing functions around, etc).

[1]: Haskell recently re-added monad comprehensions, so comprehensions aren't as limited anymore. http://blog.n-sch.de/2010/11/27/fun-with-monad-comprehension...


This. is. not. reddit. No FTFY type of comments please.


Why not using namespaced functions instead of static methods all in the same class ? This would have allowed to add new functions. This would even have allowed to use the _ namespace.

With namespaces:

    namespace _;  
    function each() {
    }

    // chaining can be achieved with this:

    class Wrapper {
        private $coll;
        function __construct($coll) {
            $this->coll = $coll;
        }
        function __call($name, $args) {
            array_unshift($this->coll,$args);
            return new self(call_user_func_array('_\\'.$name, $args));
        }
    }

    function __($coll) {
        return new Wrapper($coll);
    }

    use _;  
    _\each(...);

    // or
  
    __($coll)->each(...);

    // I can add new functions

    namespace _;
    function something(){}

With static methods:

    class __ {  
        function each() {  
        }  
    }

    // throws strict errors

    __::each(...);

    // can't add functions
Also it seems that the normal way to use the library is to call isntance methods statically, which triggers many warnings with E_STRICT :(

https://github.com/lstrojny/functional-php also brings some functional stuff to php.


Also, the double underscore prefix is reserved for magic methods:

    PHP reserves all function names starting with __ as magical. It is
    recommended that you do not use function names with __ in PHP unless you
    want some documented magic functionality.
It's only explicitly reserved for functions, so you're technically ok here, but it still may cause confusion.

http://www.php.net/manual/en/language.oop5.magic.php


It was a bit of pick your poison between a gettext() alias collision, ugly namespace syntax, and potential confusion with magic methods. Hopefully too many people aren't confused.


You can always add functions via mixin. I'll see what I can do about the warnings.


But in a way, using the namespace like suggested is much more PHP-ish. After all, your class does not have sensible instances. There is not much OOP about it.

Where there is something not-much-OOP about something, PHP supplies global functions (compare md5() to 5 lines of Java code) instead of classes. So, using global functions would. in many ways, be much more PHP-ish than using static class methods (which is more Java-ish if you ask me).

Of course, you don't want to pollute the global namespace too much, so using the '_' namespace sounds excellent. I really like the idea.


Namespaces might be more PHP-ish, but I was primarily concerned with being Underscore-ish.

I'm also not entirely opposed to the namespace approach, but syntactically I would rather call:

  __::foo('bar');
than

  use _;  
  __\foo('bar');


How can I add a mixin to the __ class without editing it ?


Just copying this from the docs, but you can pass an array of functions to mixin:

  __::mixin(array(
    'capitalize'=> function($string) { return ucwords($string); }
  ));
  __::capitalize('moe'); // 'Moe'


This is terribly misguided.

You do know that PHP has built-in min and max functions, right?

  And array_map. 
  And array_walk. 
  And array_filter. 
  And array_reduce. 
  And array_slice. 
  And array_unique. 
  And array_search. 
  And range. 
  And empty. 
  And is_object. 
  And is_array.


All of the array_* functions, as their names suggest, only apply to arrays. Underscore methods work on arrays or any Traversable (Iterator or IteratorAggregate) object. It's nice to have.


If anyone else was surprised to see anonymous functions in PHP... apparently this is a new feature as of PHP 5.3.0 (released June last year).


Also be aware that anonymous functions do not close over variables unless you specify so: http://php.net/manual/en/functions.anonymous.php


And they can not close over $this, which is annoying.


It seems that it's fixed in PHP5.4; $this is the object in which you defined the closure by default, and you can re-bind it to any other object.


PHP 5.3.0 was released in June of 2009, not 2010.


Perhaps I'm missing something, but what is the benefit of using this? Much of the functionality seems to already be available in the PHP core.


It's available, but you might not be aware of how unintuitive PHP's array functions are. With inconcistencies and gotchas abound they are a chore to use. A wrapper such as this one can greatly enhance your productivity.


Even if it is all available somewhere, I conjecture that it’s a win for those who have a project mixing PHP and Javascript, there can be one consistent style across languages.


raganwald and Ezku hit the nail on the head. Most of my work spans PHP and JS, so having consistency (something the PHP array functions particularly lack) is a big win.


No hyperbole here, but Underscore.php might actually convince me to start taking on PHP projects again. I got spoiled by other languages.


It's great to see so many simple libraries taking advantage of closures in PHP cropping up. For comparison, here's my take on collections in PHP, inspired originally as much by Underscore.js as it was by Doctrine's version: https://github.com/xi-project/xi-collections

Unfortunately, there's not much in the way of documentation as of now, but a look at the API should prove illuminating. For starters, the API is meant to be inherently both chainable and extensible with room for implementations based on eg. SPL classes. The idea is for the collections not to be throwaways for intermediate processing but to instead grow into a part of your application's internal API. Although the code should be in perfect working order (we're using it in one production system currently), the concept is a bit experimental at this stage. I'd very much appreciate any comments you have.


Who is j-ashkenas? jashkenas's crazy uncle? http://news.ycombinator.com/user?id=jashkenas ;)


Nothing to see here ;) Just trying out a new account, as I think the old one might have been blacklisted. The fact that this managed to make the front page seems to confirm it.


It seems to me that, since a few weeks ago, posting more than once a week makes your posts harder to reach the first page (they need more upvotes in less time). People that barely post seem to reach the first page with 3 votes in one hour.


While I have your attention, I've long wondered if it's possible to do for PHP what CoffeeScript did for JS. A more aesthetically concise and pleasing syntax that compiles directly to PHP. There's a few projects (PHP-Snow, CoffeeScript for PHP, etc), but they all seemed to have been abandoned.


IMO CoffeeScript exists because we can't really avoid JS for web apps. But avoiding PHP is pretty straightforward - you just use python, ruby, or whatever.


In theory, yes. In practice, it's not so simple. Most developers using php do so not by choice, whether due to legacy code, or requiring php's ubiquity, or what have you.

You can't use ruby or python to build wordpress plugins, for instance.


Good point. I can see where something like CoffeeScript for PHP would be useful.


It doesn't use CoffeeScript's syntax, but I work on Pharen, which takes a Lisp dialect and compiles it to PHP: http://scriptor.github.com/pharen/


In the past I've had a rough time parsing PHP (for an rdoc-style project), despite PHP having some built in support for parsing itself: http://php.net/manual/en/function.token-get-all.php

Perhaps if one attempted to pull the parser out of Facebook's Hiphop and use that..




Awesome.. I was halfway through implementing the same thing. Thanks!


So was I some time ago when i suddenly realized I should google it (and found this). Not that I actually use it though.


So confused.

> Underscore is a utility-belt library for JavaScript that provides a lot of the functional programming support that you would expect in Prototype.js (or Ruby), but without extending any of the built-in JavaScript objects. It's the tie to go along with jQuery's tux.

Underscore is both a utility belt and a bowtie?


Batman's utility belt, Bruce Wayne's bowtie.


Awesome, but I'm interested in your username. Are you jashkenas?

Whenever I've done PHP, I've always used a hand-rolled functional library. I will certainly be using this now, though.


Will the real Jeremy Ashkenas please stand up?


I'm surprised that people who know the terms "right fold" and "left fold" are willing to write PHP.


I know these concepts, I program in FP languages when appropriate but use PHP too.

I can earn a living with PHP in my tool-kit that Scheme/Haskell/Clojure alone will not provide.


However, there are other options, such as Javascript, Ruby, and Python, which are used nowadays in a payful way.


Let me provide an explanation for this, hopefully so that you can avoid further downvotes. I perceive three implied assertions that your comment relies upon:

Assertion 1: people who understand right and left folding are fairly high on the scale of CS knowledge.

Assertion 2: a person with suitably advanced CS knowledge can find a well-paying job or start a project that is rewarding and grants them a high-level of autonomy -- i.e. they don't need to uninspiring shitwork.

Assertion 3: PHP is for shitwork, and people only develop in it when they don't have a choice.

I agree with these assertions, and the question makes sense to me.


1. I'm willing to write and, actually, like PHP.

2. I don't have a CS degree, I'm a glorified designer eager to learn.

3. Now I know what right and left folding are.


So you confirm the set of axioms then, since you admit that you don't have an understanding of CS. I would really encourage you to pick up a different language -- not because skills are conferred upon you by choice of language but because better languages have better communities surrounding them, from which you can learn better habits.

I wasn't saying that merely knowing what folding is means you have CS knowledge. I was saying that such knowledge is characteristic of knowledgeable programmers.


Would it be fair to say that you don't have a high level of understanding of other programming languages? PHP makes sense if it's all you know about programming. PHP tries hard, but it can't quite take away all of the joy of making a machine do your bidding, so it's understandable that people who know no other alternative like it.

But learn an alternative, and you're going to like programming even more.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: