Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
221
Help us understand the problem. What is going on with this article?
@supermomonga

PHPとしても実行できるRubyの書きかた

More than 3 years have passed since last update.

はじめに

まずはこちらのFizzBuzzをご覧ください。

php.rb
p <<PHP_VERSION
<?php
PHP_VERSION
;print "\033[1F\033[1M";
//.tap{ define_method :range, -> s,e { s.upto e } }
//.tap{ define_method :array_map, -> f,seq { seq.map{ |x| f.(x) } } }
//.tap{ define_method :function, -> x,&b { -> x { $x=x;b.call } } }
array_map(function($x){
  print $x % 15 == 0 ? 'FizzBuzz' : ($x % 3 == 0 ? 'Fizz' : ($x % 5 == 0 ? 'Buzz' : $x));
  print "\n";
}, range(1,100));

ruby php.rbもしくはphp php.rbで動作します。

「PHPとしてもRubyとしても実行できるアプリケーションを作ってください!」という案件が入ってくることはよくあります1ので、この様にPHPとしてもvalidなRubyの書き方を身につける事でそういった案件にも対応していけるようになりましょう。

<?phpをどうするか

phpでは、コードを書く前にまず<?phpという何かを書かなくてはいけません。ですがrubyにおいて<?phpという記述はシンタックスエラーになります。

そこで、まずはrubyとしてvalidな形式で<?phpを記述する方法が必要となります。

Ruby
p <<PHP_VERSION
<?php
PHP_VERSION
;print "\033[1F\033[1M";

まず、rubyとしてこのコードを解釈すると、ヒアドキュメントにて<?phpという文字列を標準出力に書きだした後、「一行前に戻り、行全体を削除する」という内容のansicodeをprintメソッドに渡しています。

PHP
p <<PHP_VERSION
<?php
PHP_VERSION
;print "\033[1F\033[1M";

次にphpとしてこのコードを解釈してみます。まず1行目については通常のテキストとして標準出力に書きだされます。2行目はそのまま、<?phpなのでphpの処理開始を意味します。3行目はPHP_VERSIONという定数を評価する(単に評価して捨てるだけ)処理、4行目はrubyの時と同じく「一行前に戻り、行全体を削除する」という内容のansicodeをprintメソッドに渡し、1行目で出力された「p <<PHP_VERSION」という文字列を削除しています。

ポイントは、4行目最初の;です。PHPでは文と文の間に;を書く必要がありますが、必ずしも行末に書く必要はありません。そして、rubyのヒアドキュメントは、識別子の後に;を書くとシンタックスエラーになってしまいます。この2言語間の差異を吸収するために、;を4行目の最初に置いています。

標準出力の方法

print "\033[1F\033[1M";

printを使いましょう。

コメントアウトの利用

//.tap{ define_method :range, -> s,e { s.upto e } }
//.tap{ define_method :array_map, -> f,seq { seq.map{ |x| f.(x) } } }
//.tap{ define_method :function, -> x,&b { -> x { $x=x;b.call } } }

phpにおいて、行内の//以降はコメントとして解釈されます。一方rubyでは//は単に正規表現リテラルです。これを利用することでrubyでのみ実行される処理を記述することができます。

上記コードは

//.tap{ ... }

でなく

//; ...

と書くこともできます。

変数の利用

array_map(function($x){
  print $x % 15 == 0 ? 'FizzBuzz' : ($x % 3 == 0 ? 'Fizz' : ($x % 5 == 0 ? 'Buzz' : $x));
  print "\n";
}, range(1,100));

phpにおいて変数名には$プレフィクスが必要です。rubyにおいて$プレフィクス付きの変数はグローバル変数として扱われます。つまり、基本的にphpとしても実行可能なrubyのコードを書く際、変数は全てグローバル変数を使用します。グローバル変数の名前領域がガンガン汚染されていきますので本当に最高ですね。破綻しないように気合いでなんとかしてください。

まとめ

PHPもRubyもだいすき!

2015/1/29追記

コメントを頂きました。

p <<'PHP_VERSION;'

なるほど、この様にすることで;を含めて識別子として認識させることができますね。

p <<'PHP_VERSION;'
<?php
PHP_VERSION;
print "\033[1F\033[1M";

良い。


  1. ない 

221
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
supermomonga
ヾ(  l   _   l  〃)ノ゙ドン☆

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
221
Help us understand the problem. What is going on with this article?