Skip to content

Instantly share code, notes, and snippets.

@n1215
Last active August 29, 2015 14:19
Show Gist options
  • Save n1215/0b4bc8a973b111c483f4 to your computer and use it in GitHub Desktop.
Save n1215/0b4bc8a973b111c483f4 to your computer and use it in GitHub Desktop.
PHPでFizzBuzz 関数合成風味
<?php
namespace Compose;
/**
* 関数を合成
* pipe(f, g, h) なら h(g(f))
*
* @return callable
*/
function pipe()
{
$callables = func_get_args();
if(count($callables) < 2) {
throw new \InvalidArgumentException('\Compose\pipe() expects at least 2 callables');
}
return array_reduce($callables, function ($carry, callable $func) {
if ($carry === null) {
return function () use ($func) {
return call_user_func_array($func, func_get_args());
};
}
return function () use ($carry, $func) {
return call_user_func($func, call_user_func_array($carry, func_get_args()));
};
});
}
/**
* 配列用の関数に変換
*
* @param callable $func 元の関数
* @return callable
*/
function map(callable $func)
{
return function(array $arr) use ($func) {
return array_map($func, $arr);
};
}
/**
* pipe()のテスト
*/
function testPipe()
{
$plus = function($x, $y) { return $x + $y;};
$multiply = function($x, $y, $z) { return $x * $y * $z;};
$double = function($x) { return 2 * $x;};
$triple = function($x) { return 3 * $x;};
$func1 = pipe($double, $triple);
assert($func1(2) === 12);
$func2 = pipe($plus, $double);
assert($func2(10, 3) === 26);
$func3 = pipe($multiply, $triple);
assert($func3(2, 3, 4) === 72);
$func4 = pipe($plus, $double, $triple);
assert($func4(100, 11) === 666);
}
/**
* map()のテスト
*/
function testMap()
{
$func = map(function($x) { return $x * 2;});
assert($func(array(1, 2, 3)) === array(2, 4, 6));
}
testPipe();
testMap();
<?php
namespace FizzBuzz;
require_once './Compose.php';
function main()
{
$displayAsHtml = false; // 表示の切り替え用
$decorate = $displayAsHtml ? 'FizzBuzz\decorateHtml' : 'FizzBuzz\decorate';
$fizzBuzz = \Compose\pipe(
'\range', // 入力となる整数配列を生成
\Compose\map('FizzBuzz\evaluate'), // 配列の要素それぞれをFizzBuzzのルールで評価
$decorate, // 配列を表示用の文字列に変換
function($str) { echo $str; }  // 文字列を出力
);
$fizzBuzz(1, 30);
}
function evaluate($num)
{
return array_first(
array(15 => 'FizzBuzz', 5 => 'Buzz', 3 => 'Fizz'),
function ($divisor, $str) use ($num) { return $num % $divisor === 0; },
strval($num)
);
}
function decorate($array)
{
return \join(' ', $array) . PHP_EOL;
}
function decorateHtml(array $arr)
{
return '<ul>' . PHP_EOL ."\t<li>"
. \join('</li>' . PHP_EOL . "\t<li>", $arr)
. '</li>' . PHP_EOL . '</ul>'
. PHP_EOL;
}
function array_first($array, $callback, $default)
{
foreach($array as $key => $value)
{
if (call_user_func($callback, $key, $value)) {
return $value;
}
}
return $default;
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment