2016/7/27の日記
Rubyのメソッドに関する雑多なメモ
<< # 右ビットシフト `*2` と同じ意味 >> # 左ビットシフト `/2` と同じ意味 | # 論理和演算子. 0011|0101 => 0111 8.to_s(2) #=> "1000" : 2進数表現の文字列を取得 "0x4d2".hex #=> 1234 : 16進数を10進数に変換. 0xはなくてもあっても良い.
super
Rubyのsuperはオーバーライドしているメソッドを呼び出す.
注意点として、引数を省略してsuper
とコールすると、全ての引数を受け渡してコールしてしまう.
super()
と明示的に()をつけてコールすると、引数を渡さない.
このことは Effective Ruby でも書かれていた.
- 作者: Peter J.Jones
- 出版社/メーカー: 翔泳社
- 発売日: 2015/01/19
- メディア: Kindle版
- この商品を含むブログ (3件) を見る
クラスマクロを自分で定義してみる.
クラスマクロを使うことで、 attr_accessor
みたいなメソッドを定義できる.
完全にクラスメソッドだけど、こういう attr_accessor
っぽい宣言的な構文で記述が出来る奴をクラスマクロと言うらしい.
Railsの has_many
, belongs_to
もクラスマクロだ.
class User attr_accessor :name def self.attr_special_accessor( *key ) p key end def self.before_hoge_hoge(key) p key end def self.after_hoge_hoge(k) p k end end class Boy < User attr_special_accessor :name, :age before_hoge_hoge :foo after_hoge_hoge :bar end
このQiitaの記事がとても参考になった.
「Rubyのしくみ」(Ruby Under a Microscope)を読んだ
「Rubyのしくみ」(Ruby Under a Microscope)を読みました。
Rubyのしくみ -Ruby Under a Microscope-
- 作者: Pat Shaughnessy,島田浩二,角谷信太郎
- 出版社/メーカー: オーム社
- 発売日: 2014/11/29
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (4件) を見る
Rubyの内部における実行の流れを調べる
字句解析、構文解析、コンパイルが実際にどう行われているかを Rubyに添付されている、Rubyプログラムのパーサである Ripperクラス で調査することができます。その方法を説明します。
Ruby実行の流れは 1.8.xと1.9.xで大きく異なります。
1.9.xからYARV
(Yet Another Ruby Virtual Machine)が導入されました。
- v1.8.X
- 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
cssのパディングとマージン
パディングとマージンどっちがどっちかよく忘れるのでメモしておく。
コード
<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では //
をコメントに使えないので /* */
を使う必要がある。
2つの proc を合成して1つの proc にする
# 2つの proc を合成して1つの proc にする def foo(arg1, arg2) Proc.new do arg1.call arg2.call end end p1 = Proc.new { p 123} p2 = Proc.new { p 456} res = foo( p1, p2 ) res.call # => 123\n456
例外を投げるclosure
() throws ->(String) in
と書くと例外を投げるクロージャを定義できる
enum MyError : ErrorType { case Hoge } let c = {() throws ->(String) in throw MyError.Hoge } do { try c() } catch { print( "\(__FUNCTION__): L\(__LINE__)") }
Swiftでクラスからインスタンスを生成する
インスタンス化するクラスを定義
class Hoge { required init(){ } class func newInstance()->Hoge { return Hoge.init() } }
呼び出し
let hogeClass: Hoge.Type = Hoge.self let hogeObject = hogeClass.init()