Standard library for php.
php
is not my primary language, but when I use it occasionally, I always miss a consistent standard library. Therefore I've created this one for my needs.
stdphp
provides a set of basic classes and utility functions. It's mostly modeled after python, with some additions from javascript and ruby.
Some examples of what stdphp
looks like.
print str('foo bar baz')->split()->map('strtoupper')->sort()->join(','); /// BAR,BAZ,FOO
$str = str('Gänsefüßchen');
print count($str); /// 12
print $str['5:8']; /// 'füß'
print $str->upper(); /// 'GÄNSEFÜßCHEN'
$dupes = [4,1,3,2,4,1,4,2,3,3,1,2];
print set($dupes); /// [4,1,3,2]
$numbers = a(0,11,22,33,44,55,66,77,88,99);
print $numbers['::2']->reduce(operator('+')); /// 220
$x = lst(xrange(31));
$x['::3'] = repeat('Fizz');
$x['::5'] = repeat('Buzz');
$x['::15'] = repeat('FizzBuzz');
print $x['1:']; /// [1,2,"Fizz",4,"Buzz","Fizz",7,8,"Fizz","Buzz",11,"Fizz",13,14,"FizzBuzz",16,17,"Fizz",19,"Buzz","Fizz",22,23,"Fizz","Buzz",26,"Fizz",28,29,"FizzBuzz"]
If you know python, this is zip(*[iter(xs)]*n)
:
$a = [1,2,3,11,22,33,101,102,103];
print lst(zipargs(repeat(iter($a), 3))); /// [[1,2,3],[11,22,33],[101,102,103]]
The whole library is one single php file, std.php
:
include 'std.php';
$someList = lst("abc");
There's also a "local" version stdl.php
, which keeps stdphp
functions namespaced:
include 'stdl.php';
$someList = std\lst("abc");
stdphp
requires php 5.4+
Objects, like strings or lists, are created with factories:
$someList = lst([1,2,3]);
$someString = str("abc");
This has two advantages: conciseness and ability to override default classes with inherited ones:
class MyList extends std\Lst
{
function myNewMethod() { return $this->join(' me '); }
}
std\_setclass('Lst', 'MyList');
// now, all library functions that return a list, will return MyList:
print str('foo bar')->split()->myNewMethod(); /// foo me bar
stdphp
follows the pythonic concept of "iterables". Functions that iterate through their arguments don't enforce a particular type. Therefore you can pass any "iterable", including stdphp
objects, native php arrays and strings, and generic Traversable
objects:
$a = a(0,1,2,3);
$b = "abcd";
$c = array(9,8,7,6);
print lst(zip($a, $b, $c)); /// [[0,"a",9],[1,"b",8],[2,"c",7],[3,"d",6]]
There are several built-in iterator constructors for different purposes:
filter
map
repeat
xrange
zip
The following creates a "lazy" list of palindromic numbers. Since filter
, map
and xrange
are iterators, this list uses constant memory:
$xs = filter(
function($s) { return $s == $s['::-1']; },
map('str',
xrange(300000)));
Another example is an "endless" repeat
iterator that plays nicely with zip
:
print lst(zip('abcd', repeat('-'))); /// [["a","-"],["b","-"],["c","-"],["d","-"]]
The higher-order function getter
returns a closure that picks an item from a string or associative array.
// fetch the 2nd char from each string:
print a('ab','cd','ef')->map(getter(1)); /// ["b","d","f"]
getter
(alias by
) is especially useful with sort
, which, like in python, uses a functional key
argument to extract a comparison key.
$popularNames = [
['name' => 'Alfie' ,'rank' => 7],
['name' => 'Charlie' ,'rank' => 4],
['name' => 'Harry' ,'rank' => 1],
['name' => 'Jack' ,'rank' => 3],
['name' => 'Jacob' ,'rank' => 5],
['name' => 'Oliver' ,'rank' => 2],
['name' => 'Riley' ,'rank' => 8],
['name' => 'Thomas' ,'rank' => 6],
['name' => 'William' ,'rank' => 9]
];
// print top 3 names by rank
print lst($popularNames)->sort(by('rank'))->map(getter('name'))->get(':3'); /// ["Harry","Oliver","Jack"]
Similarly, attr
picks an attribute from an object argument:
class User {
function __construct($name) {
$this->name = $name;
}
}
$a = [new User("Harry"), new User("Oliver"), new User("Jack")];
print lst($a)->map(attr('name'))->join(','); /// Harry,Oliver,Jack
method
creates a closure that calls a specific method on the argument:
// call `String::reverse` on each element:
print s("Hello Foo Bar")->split()->map(method('reverse')); /// ["olleH","ooF","raB"]
Here's a brief overview, for a complete list of methods refer to the API documentation.
Lists are created using constructors a()
or lst()
and provide the usual repertoire of methods:
print a('foo', 'bar', 'baz')->map('strtoupper')->join('-'); /// FOO-BAR-BAZ
Lists support python-alike slicing:
$a = a(0,1,2,3,4,5,6,7);
print $a[-3]; /// 5
print $a['1::3']; /// [1,4,7]
and slice assignments:
$a = a(0,1,2,3,4,5);
$a['2:4'] = 'abcd';
print $a; /// [0,1,"a","b","c","d",4,5]
Strings are unicode-aware (source encoding is assumed to be utf8, unless specified otherwise):
$a = s('fuß');
print count($a); /// 3
$b = s("fu\xDF", 'latin1');
$a == $b; /// true
Slicing works too, but not slice assignments: strings are immutable! Note: mb
extension is required for encoding and case conversions.
Dicts are associative arrays. There are several dict
constructors:
print d('a', 1, 'b', 2); /// {"a":1,"b":2}
print dict(['a' => 1, 'b' => 2]); /// {"a":1,"b":2}
print pairdict([['a',1], ['b',2]]); /// {"a":1,"b":2}
print keydict('abc', 42); /// {"a":42,"b":42,"c":42}
In addition to standard pythonic methods, dicts can be also mapped and filtered:
$a = dict(['a'=>'foo', 'b'=>'bar']);
print $a->map('strtoupper'); /// {"a":"FOO","b":"BAR"}
Sets are just like python sets:
$a = set([1,2,3,4,5]);
print $a->intersection([5,3,9,1]); /// [1,3,5]
re
creates a regular expression object. Unlike php, delimiters are not required, and flags can be passed as a second argument:
$r = re('[a-z]+', 'i');
print $r->sub('*', 'a1B2c3'); /// *1*2*3
find
and findall
return strings:
print re('[a-z]+')->findall('ab cd ef'); /// ["ab","cd","ef"]
match
and matchall
return "match objects":
print re('([a-z]+)(\d+)')->match('abc123')->group(2); /// 123
std.php
is generated from the src
directory using small c-alike preprocessor CPP
(in tools
dir). doxytest
runs tests which are embedded in the code and enclosed in @code...@endcode
or @test...@endtest
.
- wrappers for all php array/string functions
- iterable files and streams, as in
foreach (textfile('foo.txt', 'utf8')) as $line)...
itertools
methods likeproduct
orcombinations