Ruby-like iterators in PHP

I’ve started playing with Ruby recently, and one of the things that got my attention in Ruby were iterators. They are different inside from regular loops but work in a similar way, and looks like people (at least ones that write tutorials and code examples ;) ) like to use them. For example, you can have:

arr = {"one" => 1, "two" => 2, "three" => 3}
arr.each do |key, val|
print "#{key}: is #{val}\n"
end

which iterates over a Ruby hash and prints:

three: is 3
two: is 2
one: is 1

So it got me thinking – suppose I wanted to do something like this in PHP (suppose I don’t like regular loop-y iterators for some weird reason). Naturally, I wouldn’t get it in the same concise form as Ruby does, since I can’t change the syntax. But I could get the essence. Let’s try it. First, the main iterator:

class RubyIterator {
  protected $_body;

  public function __construct($body) {
    if(!is_callable($body)) {
      throw new Exception("Iterator body should be a callable");
    }
    $this->_body = $body;
  }
  public function yield()
  {
    $args = func_get_args();
    call_user_func_array($this->_body, $args);
  }
}

Next, less try to make some class that uses it:

class RubyArray {
    protected $_arr;
    public function __construct(array $a)
    {
        $this->_arr $a;
    }

    public function each($body) {
        $iter = new RubyIterator($body);
        foreach($this->_arr as $k => $v) {
            $iter->yield($k$v);
        }
    }
}

and then:

/*
arr = {"one" => 1, "two" => 2, "three" => 3}
arr.each do |key, val|
    print "#{key}: is #{val}\n"
end
*/
    
$arr = new RubyArray(array("one" => 1"two" => 2"three" => 3));
$arr->each(function($key$val) { echo "$key: is $val\n"; });

and the result the same, of course. Or, let’s try with ranges:

class RubyRange {
    protected $_from$_to;
    public function __construct($from$to) {
        $this->_from $from;
        $this->_to $to;
    }
    public function each($body) {
        $iter = new RubyIterator($body);
        for($i=$this->_from$i<=$this->_to$i++) {
            $iter->yield($i);
        }
    }
    
}

and use it:

/*
r = 1..10;
r.each do |i|
    print "#{i*i}\n"
end
*/

$rr = new RubyRange(110);
$rr->each(function($i) { echo $i*$i."\n"; });

which indeed produces:

1
4
9
16
25
36
49
64
81
100

And so on – if one wanted, whole set of iterator methods could be implemented (I’m of course too lazy to do that :) ). I wonder if there are use cases that we can’t do there.

5.2->5.3 migration script

Wrote an article on DevZone about migration script from php 5.2 to 5.3. This little script can save some time when you consider to move your codebase to run under 5.3 (which you should :) ).

This script doesn’t do everything I’d like it to do – specifically, I’d like to make it try to figure out all kinds of messy reference scenarios, but I’m not sure how yet. And if you have other idea, please comment there or here. It’s on public git, so you can take it and modify if you wish.

5.3!!!

After a long string of delays, PHP 5.3 is finally out.  On the course of last 2 years, I was pretty sure a number of times that it will happen next month the latest, but there always were good reasons to postpone it. Now finally it’s officially out. I think it’s a huge step for PHP. Download it and try it!

Some major new features in 5.3:

  1. Namespaces! They didn’t end up exactly as I thought they would but they are a major feature PHP was missing for a long time, and I’m very curious to see how it works out in big projects.
  2. Closures and anonymous functions! PHP now has first-class functions, and you can do all kinds of crazy stuff with it. Or just make your code easier to read and maintain :)
  3. Garbage collection. PHP engine, being refcount-based, always has had a slight problem with reference loops. Even though usually it was not a big issue since at the end of the request everything is cleaned up, for long-running PHP applications not based on short request pattern it became a problem. Not anymore – now the engine knows to clean up such loops.
  4. Late static binding – it’s somewhat exotic thing for people that never encountered it, but was very burning issue for people that did need it. Basically, when class Foo extends class Bar, and the method func() defined in Foo is called as Bar::func(), there was no way to distinguish it from Foo::func(). Now there is. This allows to implement all kinds of cool patterns like ActiveRecord.
  5. Intl extension in core – lots of functions to allow you to internationalize your application.
  6. Phar in core – now you can pack all the application in one neat file and still be able to run it!

Also in 5.3:

  1. Nowdocs – same as heredocs, but doesn’t parse variables. Excellent feature for somebody that wants to include bing chunk of text into the script which can happen to have $’s etc. in it.
  2. ?: shortcut. That’s simple – $a?:$b is $a if $a is true, otherwise it’s $b.
  3. goto. Yes, I know. But now we have it too. Deal with it. :)
  4. mysqlnd – native PHP-specific mysql driver.

Last but definitely not least – tons of performance improvements, bug fixes, etc. Download it today! :)

5.3!

The PHP 5.3 release process has officially started with alpha1. Which hopefully means we’d have release in about 2-3 monthes.

This 5.3 release has two huge features that I think will have big influence on the future of PHP – namespaces and closures. There’s also late static binding, which allows to do all kinds of cool tricks, new cool extensions, new faster re2c-based parser, and many other smaller improvements.

Big thanks to everyone who helped to create it, provided feedback, helped with tests, documentation, etc. I think this version will be very successful. And separate thanks to Lukas who made this release from “erm… sometime soon” into “full speed ahead”!