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
Help us understand the problem. What is going on with this article?

完全RuboCop

More than 3 years have passed since last update.

完全RuboCop

by pocke
1 / 26

Dentoo.LT #16 での発表資料です。
https://atnd.org/events/85762


自己紹介


pocke.png

  • Pocke
  • Actcat inc. / Engineer
  • Ruby :two_hearts:
  • Twitter: @p_ck_
  • GitHub: @pocke

普段やってること


SideCI

自動コードレビュー

2017-03-08-213138_1198x616_scrot.png
170311124738.png


Shibart

GitHub の芝を Tシャツにする

1487946652.png
t-shirt.png


Agenda

RuboCop の完全さについて


RuboCop とは?

  • Ruby 用の静的解析ツール
    • スタイルチェッカ
    • Lint

例1

スタイルが崩れているのをチェックできる

  def foo
do_something
  end
test.rb:1:3: C: Indentation of first line in file detected.
  def foo
  ^^^
test.rb:2:1: C: Use 2 (not -2) spaces for indentation.
do_something
^^

例2

バグの元を検査できる

# Ruby では 0 < x && x < 20 のように書かないと死ぬ
if 0 < x < 20
  do_something
end
test.rb:2:4: W: Use the && operator to compare multiple values.
if 0 < x < 20
   ^^^^^^^^^^

本日のメイン


Auto Correct

  • RuboCop には Auto Correct という便利機能がある
  • 名前のとおり、自動修正

例1 おかしいコードを自動で修正できる

  def foo
  bar
end
$ rubocop
Inspecting 1 file
C

Offenses:

test.rb:1:3: C: [Corrected] Indentation of first line in file detected.
  def foo
  ^^^
test.rb:2:1: C: [Corrected] Use 2 (not 4) spaces for indentation.
    bar
^^^^
test.rb:2:3: C: [Corrected] Use 2 (not 0) spaces for indentation.
  bar


1 file inspected, 3 offenses detected, 3 offenses corrected

$ cat test.rb
def foo
  bar
end

例2 ループできる

def foo
  if cond
    bar
  else
    nil
  end
end

else節は省略出来る

def foo
  if cond
    bar
  end
end

else節が存在せず body が1行のifは後置で書ける

def foo
  bar if cond
end

これを一発で変換してくれる!


メリット

RuboCop の使用者

  • 雑にコードを書いて RuboCop が整形!

RuboCop の実装者

  • ループするから、多少雑に Auto-Correct を実装しても ok
    • 「不要な空白が出来てしまったらー」とか考えなくてよい

しくみ

  1. 問題のあるコードを探す
  2. 問題のあるコードがなければ終了
  3. 問題のあるコードを直す
  4. 1に戻る

仕組みの要点

  • ループがある
  • コードを直せる
    • 状態が変わる

つまり、ループの中で状態を変化できる


なんでもできそうな気がしてきましたね?


やってみた

RuboCop の Auto-Correct で Brainfuck インタプリタの実装

pocke/rubocop-brainfuck


Brainfuck とは

  • 難解プログラミング言語の一種
  • チューリング完全
    • つまり、Brainfuck を実装できる言語はチューリング完全

言語仕様

出来る操作は以下の8つのみ

  • ポインタのインクリメント、デクリメント(>, <)
  • ポインタが示す値のインクリメント、デクリメント(+,-`)
  • ポインタが示す値を出力(.)
  • ポインタが指す先に入力を代入(,)
  • ポインタが指す値が0なら、対応する]の直後にジャンプ([)
  • 対応する[にジャンプ(])

Hello, world!

Brainfuck の Hello World 例

+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
------------.<++++++++.--------.+++.------.--------.>+.


RuboCop で実行

class Program < BrainFuck
  PC = 0
  Code = <<-EOS
    +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
    ------------.<++++++++.--------.+++.------.--------.>+.
  EOS
  Memory = []
  Stdout = ''
  Stdin = ''
  Pointer = 0
end
$ rubocop -r rubocop/brainfuck  --only Brainfuck/Interpreter -a
Inspecting 1 file
C

Offenses:

test.rb:1:1: C: [Corrected] Interpreting the brainfuck code...
class Program < BrainFuck ...
^^^^^^^^^^^^^^^^^^^^^^^^^

1 file inspected, 1 offense detected, 1 offense corrected

after

class Program < BrainFuck
  PC = 119
  Code = <<-EOS
    +++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.
    ------------.<++++++++.--------.+++.------.--------.>+.
  EOS
  Memory = [0, 72, 100, 33]
  Stdout = "Hello, world!"
  Stdin = ''
  Pointer = 3
end

実装

See https://github.com/pocke/rubocop-brainfuck/blob/master/lib/rubocop/cop/brainfuck/interpreter.rb


まとめ

  • RuboCop の Auto-Correct はチューリング完全である
    • とはいえループ以外は Ruby を書いているだけなので、当たり前とも言える
  • いろんなもので Brainfuck を実装してチューリング完全であることを証明しよう!
  • 例: https://cpplover.blogspot.jp/2013/10/blog-post_20.html
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