6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Okinawa.rbAdvent Calendar 2016

Day 11

Ruby Python JavaScript C どの言語でも動くコードを書こう

Posted at

Okinawa.rb Advent Calendar 2016 11日目

1つのソースでいろんな環境で動かさなきゃいけないときの参考になれば、と思い、Ruby Python JavaScript C どの言語としても解釈できるコードを書いてみました。

Ruby: 2.3.1
Python: 3.5
JavaScript: node v6.0.0
GCC: Apple LLVM version 8.0.0 (clang-800.0.38)

RubyとPythonの違い

rubyには%i(xxx yyy zzz)[:xxx, :yyy, :zzz]という記法がありますが、
同じことを %i|xxx yyy zzz|%i+xxx yyy zzz+ とも書けます。

i %i+i;#+

このコードは、Rubyだとiメソッドに配列を渡している i([:"i;#"]) と解釈されます(変数iが定義されてる場合は別)
一方Pythonだと、普通に i % i + i と解釈されます

これとRubyの__END__、Pythonの """複数行文字列""" を組み合わせたRubyでもPythonでも動くコードがこちら

1 or i %i+i;"""#+
  ruby_code
__END__
"""
python_code

CとJavaScriptの違い

CもJavaScriptも // /**/ の2種類のコメントが使えますが、\を入れた時の若干解釈が違うようでした
(ここはコンパイラで変わったりするかも?)

//\
/*
c_code, javascript_comment
//*/

コメントの違いとCのマクロを組み合わせたCとJavaScript両方で動くコードがこちら

//\
/*
  c_code
#define s(s) 0
int b = s(//*/
  javascript_code
//\
(0
);
//\
/*
  c_code
#define s(s) 0
int b = s(//*/
  javascript_code
//\
(0
);

最後に、Ruby or Python と C or JavaScriptで分岐させることができれば、4言語全てで動くコードを作れます

a=1//1;"""/.__id__;%
;
  js or c
/*
]#"""
  ruby or python
#*/
a=1//1;"""/.__id__;%[
;
  js or c
/*
]#"""
  ruby or python
#*/

C, JavaScriptでは///* */がコメントとして
Pythonでは 整数での除算1//1"""複数行文字列"""
Rubyでは 1 / (正規表現).__id__%[複数行文字列]
として解釈されてます。
(Cでa=1;は型を書いてないのでwarningが出ますが、intということにされて動く)

全部まとめた完成形がこちら

$ ruby hello.rb.py.js.c && python hello.rb.py.js.c && node hello.rb.py.js.c && gcc hello.rb.py.js.c && ./a.out && echo OK
a=1//1;"""/.__id__;%[\
/*
;//c code
#include <stdio.h>
int main(){
  for(int i=0;i<10;i++)printf("c %d\n",i);
  printf("hello c\n");
}
#define s(s) 0
b=s(//*/
//javascript code
for(var i=0;i<10;i++)console.log("js "+i);
console.log("hello js");
//\
(0
);/*]#"""
1 or i %i+i;"""+
#ruby code
10.times{|i|puts "ruby #{i}"}
puts 'hello ruby'
__END__
"""
#python code
for i in range(10):
    print("python "+str(i))
print("hello python")
#*/

本当はもうちょっと増やしたかったけど断念。
go→package swift→let var perl→$ @ % php→$ あたりが難しそう

個人的には i %i+xxx#+ の解釈がローカル変数iが定義されてるかどうかで変わるのが面白かった。

[1] pry(main)> i %i+xxx#+
# i([:"+xxx#"])と解釈されて
# NoMethodError: undefined method `i' for main:Object
[2] pry(main)> i=1
=> 1
[3] pry(main)> i %i+xxx#+
# i変数があると i % i + xxxと解釈されて
# NameError: undefined local variable or method `xxx' for main:Object
6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?