CoderDojoKC Curriculum Director
KC PHP UG Co-leader
@eric_poe
info@ericpoe.com
http://ericpoe.com
substr("stuff", 2, 1);
// string("u")
"stuff"[2];
// string("u")
<?php
$str = "Hello, World";
for ($i = 0; $i < strlen($str); $i++) {
echo $str[$i] . " ";
}
// "H e l l o , W o r l d "
<?php
$str = "Hello, World";
foreach ($str as $char) {
echo $char . " ";
}
// PHP Warning: Invalid argument supplied for
// foreach() in /path/to/this/bad/foreach.php
// on line 5
It has, as types:
#include "stdio.h"
int main(void) {
int nums[] = {1, 2, 3}; // [1, 2, 3]
int length = sizeof(nums) / sizeof(nums[0]);
// length = int(3)
for (int i = 0; i < length; i++) {
printf("%i ", nums[i]);
}
return 0;
}
// output: "1 2 3 "
#include "stdio.h"
int main(void) {
char word[] = "stuff";
int length = sizeof(word) / sizeof(word[0]);
printf("Length is: %i\n", length);
// "Length is: 6"
for (int i = 0; i < length; i++) {
printf("%c ", word[i]);
}
return 0;
}
// "s t u f f "
<?php
declare(strict_types=1);
namespace IteratingThings\Iterator;
class ForeachString implements \Iterator
{
protected $str;
protected $ptr;
public function __construct(string $str) {
$this->str = $str;
$this->ptr = 0;
}
/** Return the current element */
public function current() : string {
return $this->str[$this->ptr];
}
/** Move forward to next element */
public function next() : void {
$this->ptr++;
}
/** Return the key of the current element */
public function key() : int {
return $this->ptr;
}
/** Checks if current position is valid */
public function valid() : bool {
return $this->ptr < strlen($this->str);
}
/** Rewind the Iterator to the first
* element */
public function rewind() : void {
$this->ptr = 0;
}
}
<?php
include(__DIR__ . "/../../../vendor/autoload.php");
use \IteratingThings\Iterator\ForeachString;
$text = isset($argv[1])
? new ForeachString($argv[1])
: new ForeachString("Hello, world!");
foreach ($text as $char) {
echo $char . " ";
}
echo PHP_EOL;
Source: a text from my wife
$ php examples/InnerIterator/Custom/basicIterator.php
"how's the chicken teriyaki?"
h o w ' s t h e c h i c k e n t e r i y a k i ?
Source: a text from my daughter
$ php examples/InnerIterator/Custom/basicIterator.php
"😻🎎🐕🐥🐲🐢🦂🐡🍒🍋🍫🍬🍭🎨🌌🌉♨⛺🌁🌃🌄⛺⛲🎻🎻💻🎼🎸🎹🎷
I love you Daddy 💞💝💜💛💚💙💗💟"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
I l o v e y o u D a d d y ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
Source: Chinese Lorem Ipsum
http://generator.lorem-ipsum.info/_chinese
混検混応予中核菜級測宮一有報祭右道芸葉。
$ php examples/InnerIterator/Custom/basicIterator.php
"混検混応予中核菜級測宮一有報祭右道芸葉。"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ?
1 Byte per Character
1 - 4 Bytes per Character
Assumptions to change:
class ForeachUtf8String implements \Iterator
{
protected $encoding;
protected $str;
protected $ptr;
public function __construct(string $str) {
$this->encoding = 'UTF-8';
$this->str = mb_convert_encoding($str, $this->encoding);
$this->ptr = 0;
}
public function current() : string {
return mb_substr(
$this->str, $this->ptr, 1, $this->encoding
);
}
public function valid() : bool {
return $this->ptr < mb_strlen($this->str);
}
...
}
use \IteratingThings\Iterator\ForeachUtf8String;
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String("This is fine. ☕");
foreach ($text as $char) {
echo $char . " ";
}
echo PHP_EOL;
// Input: "Ok😀";
// Output: "O k 😀 "
// Input: "恭禧發財"
// Output: "恭 禧 發 財 "
// Default: "T h i s i s f i n e . ☕ "
class ForeachString implements \IteratorAggregate
{
/** @var string */
protected $str;
public function __construct(string $str) {
$this->str = $str;
}
/** Something that implements \Iterator */
public function getIterator() : ForeachStringIterator {
return new ForeachStringIterator($this->str);
}
}
class ForeachUtf8String implements \IteratorAggregate
{
/** @var string */
protected $encoding;
/** @var string */
protected $str;
public function __construct(string $str) {
$this->encoding = 'UTF-8';
$this->str = mb_convert_encoding($str, $this->encoding);
}
/** Something that implements \Iterator */
public function getIterator() : ForeachUtf8StringIterator {
return new ForeachUtf8StringIterator($this->str);
}
}
An actual object that provides 24 methods out-of-the-box!
Very useful
class ForeachUtf8String implements \IteratorAggregate
{
/** @var string */
protected $encoding;
/** @var array */
protected $str;
public function __construct(string $str) {
$this->encoding = 'UTF-8';
$this->str = preg_split(
'//u', mb_convert_encoding($str, $this->encoding),
0, PREG_SPLIT_NO_EMPTY
);
}
public function getIterator() : \ArrayIterator {
return new \ArrayIterator($this->str);
}
}
<?php
$SplIterators = [
"AppendIterator",
"ArrayIterator",
"CachingIterator",
"CallbackFilterIterator",
'DirectoryIterator (extends "SplFileInfo")',
"EmptyIterator",
"FileSystemIterator",
"FilterIterator",
"GlobIterator",
"InfiniteIterator",
...
"RecursiveFilterIterator",
"RecursiveIterator",
"RecursiveIteratorIterator",
"RecursiveRegexIterator",
"RecursiveTreeIterator",
"RegexIterator",
"SeekableIterator",
];
echo "The SPL Iterators are: " . PHP_EOL;
$it = new \ArrayIterator($SplIterators);
foreach ($it as $key => $line) {
echo $key +1 . ": " . $line . PHP_EOL;
}
The SPL Iterators are:
1: AppendIterator
2: ArrayIterator
3: CachingIterator
4: CallbackFilterIterator
5: DirectoryIterator (extends "SplFileInfo")
6: EmptyIterator
7: FileSystemIterator
8: FilterIterator
9: GlobIterator
10: InfiniteIterator
...
25: RegexIterator
26: SeekableIterator
public seek (int $position) : void
class SeekableForeachString
extends ForeachString
implements \SeekableIterator
{
public function seek($position) : void
{
if (!isset($this->str[$position])) {
throw new \OutOfBoundsException(
"invalid seek position ($position)"
);
}
$this->ptr = $position;
}
}
function iterate(iterable $thing) : void {
foreach (getIterator($thing) as $item) {
echo $item . " ";
}
echo PHP_EOL;
}
$obj = new ForeachUtf8String("Howdy!");
iterate($obj);
// "H o w d y ! "
function getIterator(iterable $it) : \Traversable {
$iterator = null;
switch ($it) {
case is_array($it):
$iterator = new \ArrayIterator($it);
break;
case $it instanceof ForeachUtf8String:
$iterator = $it;
break;
default:
echo "Unknown Iterator" . PHP_EOL;
$iterator = new \EmptyIterator();
}
return $iterator;
}
$obj = new \ArrayObject(range(1, 5));
iterate($obj);
// "Unknown Iterator"
$obj = [1, 2, 3, 4, 5];
iterate($obj);
// "1 2 3 4 5 "
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String(
"The meetings will continue until morale improves.");
$it = $text->getIterator();
$phpCeoMessage = new class($it) extends IteratorIterator {
public function current()
{
return mb_strtoupper(parent::current());
}
};
foreach ($phpCeoMessage as $char) {
echo $char;
}
echo PHP_EOL;
// THE MEETINGS WILL CONTINUE UNTIL MORALE IMPROVES.
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String(
"The quick brown fox jumps over the lazy dogs"
);
$it = $text->getIterator();
// Start iterating on the 5th char and stop after 11 chars
foreach (new LimitIterator($it, 4, 11) as $char) {
echo $char;
}
echo PHP_EOL;
// quick brown
$ path/to/infiniteIterator.php "Eric Poe is Awesome! "
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String(
"The quick brown fox jumps over the lazy dogs "
);
$it = $text->getIterator();
$infiniteIt = new InfiniteIterator($it);
foreach ($infiniteIt as $char) {
echo $char;
}
REM This is the first program I ever wrote
10 PRINT "Eric Poe is Awesome! "
20 GOTO 10
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String(
"The quick brown fox jumps over the lazy dogs "
);
$it = $text->getIterator();
$infiniteIt = new InfiniteIterator($it);
// Print over and over again, but stop after 95 chars
foreach (new LimitIterator($infiniteIt, 0, 95) as $char) {
echo $char;
}
echo PHP_EOL;
The quick brown fox jumps over the lazy dogs The quick brown fo
x jumps over the lazy dogs The q
array_filter( array $arr, callable $callback ) : array
$nums = range(1, 100);
$divisibleBySeven = array_filter($nums, function ($num) {
return 0 === $num % 7;
});
printf(
"%d integers between 1 and 100 are divisible by 7:\n",
count($divisibleBySeven)
);
foreach ($divisibleBySeven as $value) {
echo $value . " ";
}
// 14 integers between 1 and 100 are divisible by 7:
// 7 14 21 28 35 42 49 56 63 70 77 84 91 98
$text = isset($argv[1])
? new ForeachUtf8String($argv[1])
: new ForeachUtf8String(
"The quick brown fox jumps over the lazy dogs"
);
$vowels = mb_convert_encoding("aeiou", 'UTF-8');
$it = $text->getIterator();
$consonants = new \CallbackFilterIterator(
$it, function ($char) use ($vowels) {
return false === mb_strpos(
$vowels, mb_strtolower($char, 'UTF-8'), 0, 'UTF-8'
);
}
);
foreach ($consonants as $char) {
echo $char;
}
echo PHP_EOL;
// Th qck brwn fx jmps vr th lzy dgs
But not today
A container library which attempts to treat arrays and strings as
First Class Citizens
public function count()
{
return mb_strlen($this->str);
}
public function current()
{
return mb_substr(
$this->str, $this->ptr, 1, $this->encoding
);
}
public function next()
{
++$this->ptr;
}
Continued ...
public function key()
{
return $this->ptr;
}
public function valid()
{
return $this->ptr < $this->count();
}
public function rewind()
{
$this->ptr = 0;
}
public function read() : void
{
$filesystem = new Filesystem(new Local(__DIR__));
$this->rawTriangleCandidates = (
new HString($filesystem->read("input.txt"))
)
->toHArray("\n")
->filter(function ($lines) {
return !empty($lines);
})
->map(function($lines) {
return $this->trimNumbers($lines);
});
}
// Input
801 791 693
572 150 74
644 534 138
191 396 196
860 92 399
Slides & Code for this talk:
https://joind.in/talk/3e558