u16suzuの blog

日々学んだことのメモブログです。

「Rubyのしくみ」(Ruby Under a Microscope)を読んだ

Rubyのしくみ」(Ruby Under a Microscope)を読みました。

Rubyのしくみ -Ruby Under a Microscope-

Rubyのしくみ -Ruby Under a Microscope-

Rubyの内部における実行の流れを調べる

字句解析、構文解析コンパイルが実際にどう行われているかを Rubyに添付されている、Rubyプログラムのパーサである Ripperクラス で調査することができます。その方法を説明します。

Ruby実行の流れは 1.8.xと1.9.xで大きく異なります。 1.9.xからYARV(Yet Another Ruby Virtual Machine)が導入されました。

  • v1.8.X

[Rubyコード] 字句解析 => 構文解析 => 実行

  • v1.9.Xより上のバージョン

[Rubyコード] =字句解析=> [トークン列] =構文解析=> [AST] =コンパイル=> [YARV命令文] => YARVで実行される

ASTは構文解析木(Abstract syntax tree)の略です。 まずは字句解析からです。 Rubyソースコードの読み込み処理です。

字句解析

require "ripper"
require "pp"

code = <<STR
10.times do |n|
  puts n
end
STR

puts code
pp Ripper.lex(code)
  • 実行結果
[[[1, 0], :on_int, "10"],
 [[1, 2], :on_period, "."],
 [[1, 3], :on_ident, "times"],
 [[1, 7], :on_sp, " "],
 [[1, 8], :on_kw, "do"],
 [[1, 10], :on_sp, " "],
 [[1, 11], :on_op, "|"],
 [[1, 12], :on_ident, "n"],
 [[1, 13], :on_op, "|"],
 [[1, 14], :on_ignored_nl, "\n"],
 [[2, 0], :on_sp, "  "],
 [[2, 2], :on_ident, "puts"],
 [[2, 6], :on_sp, " "],
 [[2, 7], :on_ident, "n"],
 [[2, 8], :on_nl, "\n"],
 [[3, 0], :on_kw, "end"],
 [[3, 3], :on_nl, "\n"]]

続いて、構文解析です。

構文解析

require "ripper"
require "pp"

code = <<STR
10.times do |n|
  puts n
end
STR

puts code
pp Ripper.sexp(code)
  • 実行結果
[:program,
 [[:method_add_block,
   [:call, [:@int, "10", [1, 0]], :".", [:@ident, "times", [1, 3]]],
   [:do_block,
    [:block_var,
     [:params, [[:@ident, "n", [1, 12]]], nil, nil, nil, nil, nil, nil],
     false],
    [[:command,
      [:@ident, "puts", [2, 2]],
      [:args_add_block, [[:var_ref, [:@ident, "n", [2, 7]]]], false]]]]]]]

最後にYARV実行命令です。

コンパイル(YARV命令を表示)

code = <<END
puts 2+2
END

puts RubyVM::InstructionSequence.compile(code).disasm
  • 実行結果
10.times do |n|
  puts n
end
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putself
0003 putobject        2
0005 putobject        2
0007 opt_mult         <callinfo!mid:*, argc:1, ARGS_SKIP>
0009 opt_send_simple  <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP>
0011 leave

KPTふり返りのテンプレート

最近、MTGのファッシリテーションをするようになったので、すぐに使い回せるようにテンプレート化しておく。

スケジュールのメール文フォーマット

お疲れ様です。 以下のフォーマットで、KPTふり返りMTGを行います。 もし、KPTに関してご存じない場合、参考資料に目を通しておいてください。

会議フォーマット

  • 全体で60分
  • 時間を計測しながら行う

タイムスケジュール

  • はじめのことば、 KPTのやり方の説明 5分

  • K 書き出し 5分

  • K ディスカッション 10分

  • P 書き出し 5分

  • P ディスカッション 15分

  • T 書き出し 5分

  • T ディスカッション 15分

参考資料

cssのパディングとマージン

パディングとマージンどっちがどっちかよく忘れるのでメモしておく。

f:id:u16s:20160216182202p:plain

コード

<html>
<head>
<style type="text/css">
div  {
  padding : 10px; /* 要素とボーダーラインのあいだの距離 */
  border : 5px solid maroon; /* ボーダーラインの幅 */
  margin : 10px; /* ボーダーラインと画面の端の距離 */
  background-color : lightgreen;
}
</style>
</head>
<body>
  <div class="hoge">
    hoge
  </div>
</body>
</html>

ちなみにcssでは // をコメントに使えないので /* */ を使う必要がある。

Swiftでクラスからインスタンスを生成する

インスタンス化するクラスを定義

class Hoge {
    required init(){
    }
    
    class func newInstance()->Hoge {
        return Hoge.init()
    }
}

呼び出し

let hogeClass: Hoge.Type = Hoge.self
let hogeObject = hogeClass.init()

Rubyで行列とベクトルの演算

固有ベクトルは任意の行列m を適用した際に,向きが変わらないベクトルのこと

require 'matrix'

m = Matrix[
  [2,1],
  [1,2]
]

v1 = Vector[1, 1]
v2 = Vector[1, -1]

# v1は m の eigen vecotr
p m * v1 # => Vector[3, 3]

# v2 is eigen vector of matrix m too.
# eigen value is 1
p m * v2 # => Vector[1, -1]

参考