
Underscore.php - j-ashkenas
http://brianhaveri.github.com/Underscore.php/
======
yahelc
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.

~~~
bkudria
> PHP will start to look a lot like Perl.

You had a typo, there.

~~~
jerf
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...](http://blog.n-sch.de/2010/11/27/fun-with-monad-
comprehensions/)

------
fooyc
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.

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

~~~
skrebbel
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.

~~~
bwh2
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');

------
KevBurnsJr
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.

~~~
enaeseth
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.

------
erikpukinskis
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).

~~~
judofyr
Also be aware that anonymous functions do _not_ close over variables unless
you specify so: <http://php.net/manual/en/functions.anonymous.php>

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

~~~
fooyc
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.

------
courtewing
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.

~~~
Ezku
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.

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

------
Ezku
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.

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

~~~
j-ashkenas
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.

~~~
michaelchisari
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.

~~~
bwh2
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.

~~~
michaelchisari
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.

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

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

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

------
Domenic_S
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?

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

------
JoelMcCracken
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.

------
andrewhare
Will the real Jeremy Ashkenas please stand up?

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

~~~
rudenoise
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.

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

