LT at PHP Conference Fukuoka 2016
PerlʹൺͯPHP͕ෆศʢओ؍Ͱ͢ʣ͋͋…͔ͩΒ…• date: 20160521• at: PHPΧϯϑΝϨϯεԬ 2016• speaker: uzulla
View Slide
ࣗݾհ• ౦ͷํͷ͏ͣΒ(uzulla)Ͱ͢• ମܕతʹʮLʢΤϧʣʯͳํͰ͢• ʢԬͷudzura͞ΜମܕʮRʢϨΪϡϥʔʣʯͰ͢Ͷʣ• Perlք۾ͰPHPͷਓͱ͍ΘΕ·͕͢ɺPHPք۾ͰPerlͷਓͱ͍ΘΕ͍ͯΔؾ͕͠·͢
PerlʹൺͯPHP͕ෆศʢओ؍Ͱ͢ʣ
ʮPerlͷΧοίΠΠϠπʢओ؍ʣΛPHPͰ͔͍͍ͭͨͧʂʂʯ
͋͋…͔ͩΒ…
ΠΤʔΠʂ
yay• h#ps://github.com/marcioAlmada/yay• Yay is a high level PHP preprocessor• Not ready for real world usage yet !
ϓϦϓϩηοαͱʁ• Cͱ͔Ͱ͓ೃછΈ• ίϯύΠϧ࣌ʹίʔυΛಈతʹม• ఆɺϚΫϩஔ• yayPHPίʔυΛม͠ɺPHPίʔυͱͯ͠ग़ྗ͢ΔτϥϯεύΠϥΈ͍ͨͳͷ• ࠓճPHPͷߏจΛվ͢Δͷʹ͔͍ͭ·͢
ͱΓ͋͑ͣࢼ͢πʔϧ• github.com/uzulla/yay-tester.php• evalͯ͠ΔͷͰةݥͰ͢!खݩͰ͔͍ͭ·͠ΐ͏• ʮ҆શͳϨϯαόͳΒ͏͔͍͍ͯ͝͠…ʁʯʢԥΒΕͦ͏ͳͷͰࣗॏ͠·ͨ͠ʣ• PHP>=7ʢevalΛtryʙcatch (\Throwable $e) {}Ͱଈࢮճආʣ
say• say "hogehoge";• sayechoΑΓҰจࣈগͳ͍ʂ• վߦ͕͘ͷ͕࠷ߴʹศརʂ• ʮPerl6͡ΌΜʯʮp5Ͱuse feature 'say'͢Ε…ʯ
# ͜ͷʮmacroʯͱ͍͏ॴΛyay͕ࢀর͢Δmacro { say ·string()·message } >> {echo ·message;echo PHP_EOL;}# ͜͜·Ͱmacrosay "say!";say "yes!";
say "say!";say "yes!";// ↓echo "say!";echo PHP_EOL;echo "yes!";echo PHP_EOL;
say!yes!
unless• unless($flag){}• if(!$flag){}ͱಉ͡• ʮ!Λॻ͚͍͍͡Όͳ͍ʯʮif( ! isKakin())Έ͍ͨͳͷࢁଓ͘ͱͭΒ͍…ʯʮisHikakin()Λͭ͘Ε͑͑ΜʯʮͳΔ΄Ͳʁʯ
macro {unless (···expression) { ···body }} >> {if (! (···expression)) { ···body }}$isSuccess = true;unless($isSuccess){echo('failed');}
$isSuccess = true;unless($isSuccess){echo('failed');}// ↓$isSuccess = false;if (! ($isSuccess)) {echo('failed');}
failed
range ԋࢉࢠ• for(1 .. 10){ print $_; }• ਖ਼͔ͳΓཉ͍͠
macro {foreach ( T_LNUMBER·S .. T_LNUMBER·Eas T_VARIABLE·INDEX ){ ···body }} >> {foreach ( range(T_LNUMBER·S , T_LNUMBER·E)as T_VARIABLE·INDEX ){ ···body }}foreach( 1 .. 10 as $_ ){ echo $_; }
foreach( 1 .. 10 as $_ ){echo $_;}// ↓foreach ( range(1 , 10) as $_ ){echo $_;}
12345678910
range ԋࢉࢠ ͦͷ̎• ʮrange()Ͱforeachͱ͔μϝͰ͠ΐʯʮ͍ʯ• ʢੲͷPerlPHPಉ༷ʹڊେྻ͕Ͱ͖͍ͯͨʢΒ͍͠ʣʣ• ʢࠓճ࣮͠ͳ͍͚Ͳ('a' .. 'z')ͳͲ
macro {foreach ( T_LNUMBER·S .. T_LNUMBER·Eas T_VARIABLE·INDEX ){ ···body }} >> {$__itelatorGenerator =itelatorGenerator(T_LNUMBER·S, T_LNUMBER·E);foreach ( $__itelatorGenerator as T_VARIABLE·INDEX ){ ···body }}function itelatorGenerator($init, $fin){$num = $init;while(1){if( $fin < $num ) { return $num++; }yield $num++;}}foreach( 1 .. 10 as $_ ){ echo $_; }
function itelatorGenerator($init, $fin){$num = $init;while(1){if( $fin < $num ) { return $num++; }yield $num++;}}// ͜͜·Ͱڞ௨foreach( 1 .. 10 as $_ ){ echo $_; }// ↓$__itelatorGenerator·cfcd208495d565ef66e7dff9f98764da= itelatorGenerator(1, 10);foreach ( $__itelatorGenerator·cfcd208495d565ef66e7dff9f98764da as $_ ){ echo $_; }
ਖ਼نදݱϚονͱஔ• Ϛον• if( "123" =~ /2/ ){ }• ஔ• $abc =~ s/a/A/;• ݸਓతʹ݁ߏ͖• ʮPerlه߸ଟਿʯʮperlopͰάάΕʯ
macro {T_VARIABLE·A =~ /T_STRING·B/} >> {preg_match('/'. ··stringify(T_STRING·B) .'/u',T_VARIABLE·A)}if($abc =~ /a/){ echo 1; }
if($abc =~ /a/){echo 1;}// ↓if(preg_match( '/'. 'a' .'/u' ,$abc )){echo 1;}# օ͞Μ͕͍͍͍ͨ͜ͱղΔ
macro {T_VARIABLE·A =~ s/T_STRING·B/T_STRING·C/} >> {T_VARIABLE·A =preg_replace('/'. ··stringify(T_STRING·B) .'/u',··stringify(T_STRING·C) ,T_VARIABLE·A)}$abc = 'abc';$abc =~ s/a/v/;echo $abc;
$abc =~ s/a/v/;// ↓$abc = preg_replace('/' . 'a' . '/u','v' ,$abc);
༨ஊ:JS෩ਖ਼نදݱϚον• if($abc./a/){ ... }• ʮOOPͬΆ͍ʂʯʮݩʑΦϒδΣΫτࢦݴޠ͔ͩͧͬ͠Γ͠Ζʯ• ʮPHPͳΒ −>Ͱʁʯʮͤͳʯ
macro {if( T_VARIABLE·A./T_STRING·B/ ){ ···body }} >> {if( preg_match('/'. ··stringify(T_STRING·B) .'/u' ,T_VARIABLE·A ) ){ ···body }}$abc = 'abc';if($abc./a/){echo 1;}
if($abc./a/){ echo 1; }// ↓if( preg_match('/'. 'a' .'/u' ,$abc)){ echo 1; }
yadayada• ...• ʮޙͰ࣮͢Δ͔Β...ʯͱ͍͏࣌ͷʮ...ʯ• ౸ୡ͢Δͱɺྫ֎্͕͕Δ• //TODOΑΓΘ͔Γ͍͢…͔…͠Εͳ͍
macro { ... } >> {throw new \Exception ('Unimplemented');}if(1){...}
if(1){...}// ↓if(1){throw new \Exception ('Unimplemented');}
block scope• {ʙ}• ϒϩοΫͷதͰείʔϓ͕ग़དྷΔ• ͋ΔҙຯҰ൪ϚΫϩͬΆ͍• ΊͬͪΌ΄͍͠ʂʂʂ
macro { { ···body } } >> {( function( $arg ) {extract( $arg );···body} ) ( get_defined_vars() ) ;}$abc = 'abc';{$abc = 'def';echo $abc, PHP_EOL;}echo $abc, PHP_EOL;
{$abc = 'def';}// ↓( function( $arg·cfSNIPda ) {extract( $arg·cfSNIPda );$abc = 'def';} ) ( get_defined_vars() ) ;
defabc
use• ʮPHPͷuseͬͯͳΜͳͷɺಡΈࠐΜͰ͘Εͳ͍ͷΑ͘Θ͔Βͳ͍Μ͚ͩͲ…ʯʢ༑ਓͷJVMܥϓϩάϥϚஊʣʮͨɺ͔ͨ͠ʹ…ʯ• useͰຊʹrequire_once͢Εղܾ
macro {use ·ns()·type ;} >> {use ·type ;__require( ··stringify(·type) ) ;}function __require($class){$array = explode('\\', ltrim($class, '\\'));$path = implode('/', $array);$filename = $path.'.php';require_once($filename);}use \This\Is\Test;
use \This\Is\Test;// ↓use \This\Is\Test ;__require( '\This\Is\Test' ) ;
use strict;use warnings;• ͍ܰΤϥʔͰऴྃ͢Δ• ͍͋͠ॴͰܯࠂ͢Δ• ʢຊ͏ͪΐͬͱҙຯ͕͋Δʣ• ʢηοτ͍ͯ͠ΔΤϥʔϋϯυϥ࡞๏ݸਓతझຯͰ͢ʣ
macro { use strict; } >> {set_error_handler(function($errno, $errstr, $errfile, $errline){throw new \Error($errstr);});}macro { use warnings; } >> { error_reporting(-1); }use strict;use warnings;echo $a;
use strict;use warnings;// ↓set_error_handler(function($errno·cfSNIPda,$errstr·cfSNIPda,$errfile·cfSNIPda,$errline·cfSNIPda){throw new \Error($errstr·cfSNIPda);});error_reporting(-1);
·ͱΊ• yayͬͯ݁ߏศརͰʂʢʁʣ• ʮҰਓϓϩδΣΫτझຯͳΒͳʂʯ• ஔͱ͔Ͱͳ͍ͷͰɺʢͪΌΜͱॻ͚ʣ͔ͳΓյΕͮΒ͍• ग़ྗ͞ΕΔͷɺຊͷPHPͳͷͰ҆৺ʢʁʣ• ୯७ͳϧʔλʔఆٛͷDSLͳΒͭ͘Ε·ͨ͠
ຊʹΔਓͷίϝϯτ• yayɺυΩϡϝϯτ͕ςετίʔυ͔͠ͳ͍ͷͰௐΔͷ͕େม• τʔΫϯछͷT_VARIABLEgithub/nikic/PHP-Parser• ύʔαʔͷ·lsgithub/marcioAlmada/yay/src/parsers.php• ʮͱʹ͔࣮͘ͱςετίʔυΛݟΔΜͩʯ
• ·ͱ.ͱɾΛؒҧ͑ͯେม• middle dot• ʮ·(00B7)ͬͯɺීஈͲ͏ͬͯೖྗ͢ΔΜ…ʯ• ʮதࠇΛ·(00B7)ʹม͢Δpreprocessor͕ඞཁͰʯ
__END__
__halt_compiler();
ʮyapc8oji Ͱάάͬͯ͘ΕཔΉʯτʔΫԠืͯ͘͠Εʂʂ̍
͓·͚ɿshort closure• ( )->{ }
macro {(···condition) -> { ···body }} >> {function ( ···condition ) { ···body }}$a = ($v)->{ echo $v; };$a('abc');
$a = ($v)->{ echo $v; };// ↓$a = function ( $v ) { echo $v; };
Defined-Or, //= ԋࢉࢠ• $a //= 'default';• ʢ//??ͱಉ͡ʣ• ຊؾͰཉ͍͠• 7.xͰདྷΔʢ͚ͲઌऔΓͱ͍͏͜ͱͰʣ=> https://wiki.php.net/rfc/null_coalesce_equal_operator
macro { T_VARIABLE·A ??= } >> {T_VARIABLE·A = T_VARIABLE·A ??}$a ??= 123;echo $a;
$a ??= 123;echo $a;// ↓$a = $a ?? 123;echo $a;
splitͱjoin• ʮͲ͏ͯ͠Explode/Implode͕׳Εͳ͍ʯʮ׳ΕΖʯʮͳͥจࣈΛ૿͢ํʹߦͬͨͷ͔ʯʮఘΊΖʯ• PHP7Ͱ͍ͭʹফ໓͠·ͨ͠Ͷ
macro { split } >> { mb_split }macro { join } >> { implode }print_r( split(",", "a,b,c") );print_r( join(",", ["a","b","c"]) );# PHP7Ͱsplit()͕ͳ͘ͳͬͯ# mb_splitͷ͍ͬͯ͜ΔΜͩΑͳ͋…
split(",", "a,b,c");join(",", ["a","b","c"]);// ↓mb_split(",", "a,b,c");implode(",", ["a","b","c"]);