programming in handstand
DESCRIPTION
My talk at PHPMeetup Budapest about doing the FizzBuzz kata with some weird constraints, such as not using loops, if statements and ternaries, and what can be learnt from such an exercise. (Slides are in Hungarian but most of them contains nothing but code.)TRANSCRIPT
Programozz kézenállva!
Magyar Attila (@athoshun)PHP Meetup, 2013. 02. 26.
FizzBuzz
Write a program that iterates through the numbers between 1 and 100:
For multiples of 3 print "Fizz" For multiples of 5 print "Buzz" For numbers which are multiples of both 3 and 5
print "FizzBuzz" For others, print the number itself
FizzBuzz
Write a program that iterates through the numbers between 1 and 100:
For multiples of 3 print "Fizz" For multiples of 5 print "Buzz" For numbers which are multiples of both 3 and 5
print "FizzBuzz" For others, print the number itself
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, ...
Triviális megoldás
for ($i = 1; $i <= 100; ++$i) { if ($i % 3 == 0) print "Fizz"; if ($i % 5 == 0) print "Buzz"; if ($i % 3 && $i % 5) print $i; print ", ";}
Ciklus nélkül!
Ciklus nélkül!
Ciklus nélkül!
function fizzbuzz($i = 1){ if ($i > 100) return;
if ($i % 3 == 0) print "Fizz"; if ($i % 5 == 0) print "Buzz"; if ($i % 3 && $i % 5) print $i; print ", ";
fizzbuzz($i + 1);}
Ciklus nélkül!
function fizzbuzz($i = 1){ if ($i > 100) return;
if ($i % 3 == 0) print "Fizz"; if ($i % 5 == 0) print "Buzz"; if ($i % 3 && $i % 5) print $i; print ", ";
fizzbuzz($i + 1);}
PHP Fatal error: Maximumfunction nesting levelof '100' Reached, aborting!
Ciklus nélkül!
Ciklus nélkül!
Ciklus nélkül!
$fizzbuzz = function ($i) { if ($i % 3 == 0) print "Fizz"; if ($i % 5 == 0) print "Buzz"; if ($i % 3 && $i % 5) print $i; print ", ";};
array_map($fizzbuzz, range(1, 100));
Elágazás nélkül!
Elágazás nélkül!
$id = function ($x) { return $x; };
Elágazás nélkül!
$id = function ($x) { return $x; };
$fizz = function ($x) { return "Fizz"; };$buzz = function ($x) { return "Buzz"; };$fizzbuzz = function ($x) { return "FizzBuzz";};
Elágazás nélkül!
$functions = array( $fizzbuzz, $id, $id, $fizz, $id, $buzz, $fizz, $id, $id, $fizz, $buzz, $id, $fizz, $id, $id);array_map( function ($x) use ($functions) { print $functions[$x % 15]($x) . ", "; }, range(1, 100));
Redundancia
$id = function ($x) { return $x; };
$fizz = function ($x) { return "Fizz"; };$buzz = function ($x) { return "Buzz"; };$fizzbuzz = function ($x) { return "FizzBuzz";};
Redundancia
$id = function ($x) { return $x; };
$fizz = function ($x) { return "Fizz"; };$buzz = function ($x) { return "Buzz"; };$fizzbuzz = function ($x) { return "FizzBuzz";};
Redundancia
$id = function ($x) { return $x; };
$fizz = function ($x) { return "Fizz"; };$buzz = function ($x) { return "Buzz"; };$fizzbuzz = function ($x) { return "FizzBuzz";};
function const_($const) { return function ($x) use ($const) { return $const; };}
Redundancia
$id = function ($x) { return $x; };
$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = const_("FizzBuzz");
function const_($const) { return function ($x) use ($const) { return $const; };}
Redundancia
$id = function ($x) { return $x; };
$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = const_("FizzBuzz");
DON'T REPEAT YOURSELF!!!
Redundancia
$id = function ($x) { return $x; };
$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = const_("FizzBuzz");
function concat($f, $g){ return function ($x) use ($f, $g) { return $f($x) . $g($x); };}
Redundancia
$id = function ($x) { return $x; };
$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = concat($fizz, $buzz);
function concat($f, $g){ return function ($x) use ($f, $g) { return $f($x) . $g($x); };}
$id = function ($x) { return $x; };$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = concat($fizz, $buzz);$functions = array( $fizzbuzz, $id, $id, $fizz, $id, $buzz, $fizz, $id, $id, $fizz, $buzz, $id, $fizz, $id, $id);array_map( function ($x) use ($functions) { print $functions[$x % 15]($x) . ", "; }, range(1, 100));
$id = function ($x) { return $x; };$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = concat($fizz, $buzz);$functions = array( $fizzbuzz, $id, $id, $fizz, $id, $buzz, $fizz, $id, $id, $fizz, $buzz, $id, $fizz, $id, $id);array_map( function ($x) use ($functions) { print $functions[$x % 15]($x) . ", "; }, range(1, 100));
3 többszörösei
function multiples_of_3(){ return array_map( function ($x) { return $x * 3; } range(1, 10) );}
var_dump( multiples_of_3() );// 3, 6, 9, 12, 15, 18, 21, 24, 27, 30
3 többszörösei
function multiples_of_3(){ return array_map( function ($x) { return $x * 3; } range(1, 10) );}
var_dump( multiples_of_3() );// 3, 6, 9, 12, 15, 18, 21, 24, 27, 30
3 többszörösei
function multiples_of_3(){ return array_map( multiply_by_3(), range(1, 10) );}function multiply_by_3(){ return function ($x) { return $x * 3; }}
3 többszörösei
function multiples_of_3(){ return array_map( multiply_by_3(), range(1, 10) );}function multiply_by_3(){ return function ($x) { return $x * 3; }}
3 többszörösei
function multiples_of_3(){ return array_map( multiply_by(3), range(1, 10) );}function multiply_by($n){ return function ($x) use ($n) { return $x * $n; }}
3 többszörösei
function multiples_of($n){ return array_map( multiply_by($n), range(1, 10) );}function multiply_by($n){ return function ($x) use ($n) { return $x * $n; }}
3 többszörösei
function multiples_of($n){ return array_map( multiply_by($n), range(1, 10) );}
var_dump( multiples_of(5) );// 5, 10, 15, 20, 25, 30, 35, 40, 45, 50
A 3 első öt többszöröse
function take($n, array $from){ return array_slice($from, 0, $n);}
A 3 első öt többszöröse
function take($n, array $from){ return array_slice($from, 0, $n);}
var_dump( multiples_of(3) );// 3, 6, 9, 12, 15, 18, 21, 24, 27, 30
var_dump( take(5, multiples_of(3)) );// 3, 6, 9, 12, 15
A többi szám
function subtract(array $from, array $what){ return array_diff($from, $what);}
A többi szám
function subtract(array $from, array $what){ return array_diff($from, $what);}
var_dump( subtract( range(1, 15), take(5, multiples_of(3)) ));
// 1, 2, 4, 5, 7, 8, 10, 11, 13, 14
4 halmaz, modulo 15
$multiples_of_3 = take(4, multiples_of(3));$multiples_of_5 = take(2, multiples_of(5));$multiples_of_both = array(0);$others = subtract( range(1, 14), array_merge($multiples_of_3, $multiples_of_5));
4 halmaz, modulo 15
$multiples_of_3 = take(4, multiples_of(3));$multiples_of_5 = take(2, multiples_of(5));$multiples_of_both = array(0);$others = subtract( range(1, 14), array_merge($multiples_of_3, $multiples_of_5));
var_dump( array_merge( $multiples_of_3, $multiples_of_5, $multiples_of_both, $others ));// 3, 6, 9, 12, 5, 10, 0, 1, 2, 4, 7, 8, 11, 13, 14
Érték → tömb
function repeat($value, $times){ return array_fill(0, $times, $value);}
var_dump( repeat(42, 4) );
// 42, 42, 42, 42
Érték → tömb
function repeat($value, $times){ return array_fill(0, $times, $value);}
var_dump( repeat(function () {}, 4) );
// object(Closure)#1 (0) {},// object(Closure)#1 (0) {},// object(Closure)#1 (0) {},// object(Closure)#1 (0) {}
( Tömb, tömb ) → tömb
( Tömb, tömb ) → tömb
$keys = array(42, 43, 44);$values = array( "Fortytwo", "Fortythree", "Fortyfour");
var_export(array_combine($keys, $values));
// array (// 42 => 'Fortytwo',// 43 => 'Fortythree',// 44 => 'Fortyfour',// )
( Tömb, függvény ) → tömb
function for_all(array $values, $function) { return array_combine( $values, repeat($function, count($values)) );}
( Tömb, függvény ) → tömb
function for_all(array $values, $function) { return array_combine( $values, repeat($function, count($values)) );}
$items = array(42, 43, 44);$do_something = function () {};var_dump( for_all($items, $do_something) );
// array(3) {// [42] => object(Closure)#1 (0) {}// [43] => object(Closure)#1 (0) {}// [44] => object(Closure)#1 (0) {}// }
Hol is tartunk?
$id = function ($x) { return $x; };$fizz = const_("Fizz");$buzz = const_("Buzz");$fizzbuzz = concat($fizz, $buzz);$functions = array( $fizzbuzz, $id, $id, $fizz, $id, $buzz, $fizz, $id, $id, $fizz, $buzz, $id, $fizz, $id, $id);array_map( function ($x) use ($functions) { print $functions[$x % 15]($x) . ", "; }, range(1, 100));
Hol is tartunk?
$multiples_of_3 = take(4, multiples_of(3));$multiples_of_5 = take(2, multiples_of(5));$multiples_of_both = array(0);$others = subtract( range(1, 14), array_merge($multiples_of_3, $multiples_of_5));
$functions = for_all($multiples_of_3, $fizz) + for_all($multiples_of_5, $buzz) + for_all($multiples_of_both, $fizzbuzz) + for_all($others, $id);
Függvény → kiírás
function print_($function){ return function ($x) use ($function) { print $function($x); };}
Alakul...
$functions = for_all($multiples_of_3, print_($fizz)) + for_all($multiples_of_5, print_($buzz)) + for_all($multiples_of_both, print_($fizzbuzz)) + for_all($others, print_($id));
array_map( function ($x) use ($functions) { print $functions[$x % 15]($x); print ", "; }, range(1, 100));
Alakul...
$functions = for_all($multiples_of_3, print_($fizz)) + for_all($multiples_of_5, print_($buzz)) + for_all($multiples_of_both, print_($fizzbuzz)) + for_all($others, print_($id));
array_map( function ($x) use ($functions) { $functions[$x % 15]($x); print ", "; }, range(1, 100));
Alakul...
$them = $id;
$functions = for_all($multiples_of_3, print_($fizz)) + for_all($multiples_of_5, print_($buzz)) + for_all($multiples_of_both, print_($fizzbuzz)) + for_all($others, print_($them));
array_map( function ($x) use ($functions) { $functions[$x % 15]($x); print ", "; }, range(1, 100));
A végeredmény
for_all($multiples_of_3, print_($fizz)) + for_all($multiples_of_5, print_($buzz)) + for_all($multiples_of_both, print_($fizzbuzz)) + for_all($others, print_($them));
A végeredmény
for_all($multiples_of_3, print_($fizz)) + for_all($multiples_of_5, print_($buzz)) + for_all($multiples_of_both, print_($fizzbuzz)) + for_all($others, print_($them));
A végeredmény
for all multiples of 3 print fizz for all multiples of 5 print buzz for all multiples of both print fizzbuzz for all others, print them
DON'T TRY THIS AT HOME!
Memória pazarló Lassú
TRY THIS AT HOME!
Más szemlélet Mellékhatások nélkül → determinisztikus Trükkök:
Lazy evaluation (lazy iterators) Cache-elés Tail call optimization
Többszálúság? (Párhuzamos algoritmusok, skálázás)
Köszönöm a figyelmet!
Másik változat :-)
function fizzbuzz(){ $functions = array( const_("FizzBuzz"), const_("Buzz"), const_("Fizz"), id() ); array_map( function ($x) use ($functions) { print $functions[ !!($x % 3) + 2 * !!($x % 5) ]($x) . ", "; }, range(1, 100) );}
Harmadik változat :-)
function fizzbuzz(){ array_map( function ($x) { print array_reduce( array( when(divisable_by(3), append(const_("Fizz"))), when(divisable_by(5), append(const_("Buzz"))), when(neither(), append(id())), ), apply_filter_with($x), ”” ) . ", "; }, range(1, 100) );}