【一人 vimrc advent calendar 2017】第7回 学生エンジニア限定LT大会!!!で Vim を布教してきた【9日目】

一人 vimrc advent calendar 2017 9日目の記事になります。
学生ではないんですが、学生エンジニア限定LT大会で発表してきました。
と、いうか前日まで行くかどうするか悩みまくって申し訳ない

Vim の布教

https://osyo-manga.github.io/slide-gakusei_LT-vim/#/

LTが5分ということで簡単なネタなんですが、ちょっと話してきました。
と、いうかいろいろと書きたいことが多くて Vim の話を 5分でまとめるのむずかしい…。
モードの話や operator、textobj なんかの話をもっとしたかった
今回のスライドも結構書き直したりしているのでかなり書くのに時間がかかってしまいました…。

しかし、世の中には
『来るときの電車の中で書いた』
『仕事中の移動時間に書いた』
『発表中に書いた』
みたいな人がいてこわい。
わたしなんて書いてあることすら喋ることができないのでもっとスライドを書いてしゃべり慣れていきたい…。

所感

みんな若くてつらかった(こなみかん。
いやー今はあんな若い人がプログラミングやっているんですねー。
まさかあんな人やこんな人がいるなんてー(棒。

それはそれとして、完全にアウェイというか場違いかと思ったんですが皆さん優しくて、いろいろお話することができて楽しかったです。
思ったよりもフォロワーの人が来ていたっぽくてぼっちにならずにすんでよかった…。
若いエネルギーを貰ったのでやる気が出てきますね…!
と、いうかフォロワーの人とは気づかずに普通に話していて『フォローしてくださいね』って言ってしまったのはギャグですね。完全に申し訳なく
や、会場に来ていたのは知っていたんですがまさか本人をは夢にも思わず…。
登壇者も次の発表が始まるまでに誰がしゃべっていたか忘れるしちかたないね(´・_・`)

次回の参加はどうしようか決めかねているんですが、ひとつネタが思いついてしまったので元気をもらいにまた行ってみようかな…。

あ、ちなみに Ruby の簡単なネタも話してきました。

https://osyo-manga.github.io/slide-gakusei_LT-07-case-when/#/

【一人 Ruby Advent Calendar 2017】クラス名+メソッド名をいい感じに出力する【9日目】

一人 Ruby Advent Calendar 2017 9日目の記事になります。

デバッグ出力として "クラス名#メソッド名" を出力したい

デバッグを行っている際に次のように "クラス名#メソッド名" を文字列で出力したいことがあります。

class X
    def homu
        # クラス名#メソッド名
        p "X#homu"
    end
end

うーん、機械的に生成したいですね。

__method__ を使う

Ruby では __method__ で『現在の』メソッド名を取得することができます。 これを利用することで次のように機械的に生成することができます。

class X
    def homu
        # クラス名#メソッド名
        p "#{self.class.name}##{__method__}"
    end
end

モジュールの場合ちょっと問題がある

先ほどのコードをモジュールのメソッドで使用する場合問題があります。

module Mod
    def homu
        p "#{self.class.name}##{__method__}"
        # => X#homu
    end
end

class X
    include Mod
end

self.class.name をモージュルのメソッドで使用した場合、『mixin したクラスの名前』になってしまいます。

Method#owner を利用する

self.class.name ではなくて Method#owner を利用して定義しているクラス(モジュール)名を取得します。

module Mod
    def homu
        p "#{method(__method__).owner}##{__method__}"
        # => Mod#homu
    end
end

class X
    include Mod
end

これでおっけーです。

【一人 vimrc advent calendar 2017】markdown 内のコードをハイライトする【8日目】

一人 vimrc advent calendar 2017 8日目の記事になります。 今回のネタは前から設定は知っていたけど放置してて、いざ設定してみたらめちゃくちゃ便利だたというやつです。

markdown 内のコードをハイライトする

さて、markdown では以下のようにコードを記述してハイライトすることができます。

```ruby
module Mod

end

class X
    # モジュールを mixin
    include Mod
end

# include したモジュールが X の次に追加される
p X.ancestors
# => [X, Mod, Object, Kernel, BasicObject]
```

これを Vim 上でもいい感じにハイライトしたい場合、g:markdown_fenced_languages という設定が利用できます。

g:markdown_fenced_languages を設定する

以下のようにハイライトしたい filetypeg:markdown_fenced_languages へと列挙します。

let g:markdown_fenced_languages = [
\  'css',
\  'erb=eruby',
\  'javascript',
\  'js=javascript',
\  'json=javascript',
\  'ruby',
\  'sass',
\  'xml',
\  'cpp',
\]

適用前

適用適用後

標準でこういう機能が使えるので便利ですね。

参照

【一人 Ruby Advent Calendar 2017】表参道.rb #29 ~ Module ~【8日目】

一人 Ruby Advent Calendar 2017 8日目の記事になります。
今日は表参道.rb #29 ~ Module ~参加して LT してきたのでそのスライドでも。
今回もご飯が美味しかった

mixin と module について

https://osyo-manga.github.io/slide-omotesandorb-29-mixin/#/

今回は『module がどのように mixin されているのか』みたいな内容を話してきました。 まあ Ruby に詳しい人なら当たり前のような内容なのでそこまで真新しいものではないと思いますが…。 後半で消化したデコレータみたいなのは Rubyprepend を活かしたような実装なのでこれは書いていて楽しかったですね。

補足

スライドの中で

def plus a, b
    a + b
end
decorate :plus, &print_args

みたいなデコレータの紹介をしていたのですが、参加後に 『decorate の第一引数(:plus)を省略したいよね…』 みたいな意見を頂いたのですが、実はこれは下記のように記述することが出気ます。

decorate def minus a, b
    a - b
end, &print_args

上記は何をやっているのかというと def の戻り値が『メソッド名』なのでそれを直接 decorate メソッドの引数として渡している感じになります。
実はこれ、ライブコーディングで紹介しようと思っていたのですが、途中でめんどくさくなってしまい(ry。
ま、まあスライドには書いてあるから…。


そんなわけで LT してきましたー。
運営の方々、発表を聞いてくださった皆様、ありがとうございました。
今回は『発表が面白かった』などの感想を頂いたので嬉しかったです。
またいろいろと Ruby の意見なんかも聞くことができたので有意義な時間でした。 次回も機会があれば参加してみたいです。

【一人 Ruby Advent Calendar 2017】クラスとモジュールの違い【7日目】

一人 Ruby Advent Calendar 2017 7日目の記事になります。
今回はクラスとモジュールの違いを簡単にまとめてみました。

クラス

  • class でクラスを定義
  • .new でクラスのインスタンスオブジェクトを生成
  • 異なるクラスを継承する事が出来る
  • クラスは1つのクラスしか継承する事ができない
  • クラスを mixin することはできない

Ruby のクラスは『任意のインスタンスを生成する為』のオブジェクトとして定義します。

# クラスの定義
class Person
    attr_accessor :name, :age

    def initialize name, age
        self.name = name
        self.age  = age
    end

    def to_s
        "name:#{name}, age:#{age}"
    end
end

# クラスのインスタンスオブジェクトを生成
homu = Person.new "homu", 14
mami = Person.new "mami", 15

puts homu
# => name:homu, age:14

puts mami
# => name:homu, age:14

モジュール

  • module でモジュールを定義
  • モジュールはインスタンス化できない
  • include などを使用することで任意のクラスやモジュールに対して mixin することが出来る
  • mixin は何個でも出来る
  • モジュールは継承できない

定義したモジュールを mixin することでそのモジュールのメソッドを使用することができます。

module Twice
    def twice
        self + self
    end
end


class X
    # モジュールを取り込む
    include Twice

    attr_reader :value

    def initialize value
        @value = value
    end

    def + other
        X.new(value + other.value)
    end

    def to_s
        @value.to_s
    end
end


x = X.new 42

# mixin したモジュールのメソッドが使用できる
puts x.twice
# => 84

puts x.twice.twice
# => 168

まとめ

  • クラスはインスタンス化出来る
  • モジュールはインスタンス化できない
  • クラスは継承して拡張できる
  • モジュールは mixin することで機能を取り込むことが出来る


こんな感で Ruby におけるクラスとモジュールは似ているようで違い、違っているようで似ている感じになります。
使い分けるコツとしては

  • インスタンスオブジェクトを生成したい場合はクラス
  • 機能として切り出したい場合はモジュール

というような感じでしょうか。

【一人 vimrc advent calendar 2017】ディレクトリをオプションに設定した場合にディレクトリも生成する【7日目】

一人 vimrc advent calendar 2017 7日目の記事になります。

'backupdir''undodir' などでディレクトリを設定する場合の注意

さて、、Vim では 'backupdir''undodir' などディレクトリを設定するオプションがいくつかあります。

"バックアップファイルを作るディレクトリ
set backupdir=$HOME/vimbackup

" undo ファイルを保存するディレクトリ
set undodir=$HOME/vimundo

しかし、上記のようなディレクトリを設定するオプションは『ディレクトリが存在しなかった場合』に自動でディレクトリを作成しません。
なので自前でディレクトリを作る必要があります。
また、設定したディレクトリが存在しなくても特にエラーは出力されません。

vimrc 内でディレクトリも作成する

自前でいちいちディレクトリを作成するのはめんどくさいので簡単な Vim script で対応してみましょう。

" ネストしたディレクトリを作成する関数
function! s:mkdir(dir)
    if !isdirectory(a:dir)
       " "p" を渡すことでネストしたディレクトリ全てが作成される
        call mkdir(a:dir, "p")
    endif
endfunction


"バックアップファイルを作るディレクトリ
set backupdir=$HOME/vimbackup
" 設定したディレクトリを生成する
" & をつけてオプションの値を渡していることに注意
call s:mkdir(&backupdir)

" undo ファイルを保存するディレクトリ
set undodir=$HOME/vimundo
call s:mkdir(&undodir)
set undofile

このように vimrc に記述しておけば 'backupdir' などを変更した場合でも自動でディレクトリが生成されます。
ただし、あくまでも vimrc 上でディレクトリを生成しているのでコマンドライン等で 'backupdir'ディレクトリを変更した場合は反映されないので注意してください。
この辺りは autocmd OptionSet を使えばいい感じに自動生成してくれそうですがうーん。

まとめ

  • 'backupdir''undodir' などのディレクトリは Vim 側で自動生成されない
  • めんどくさいことは vimrc で自動化してしまおう


まあ、めんどくさいことは Vim script をさくっと書いてしまうとよいですね。

【一人 Ruby Advent Calendar 2017】Ruby における真と偽【6日目】

一人 Ruby Advent Calendar 2017 6日目の記事になります。

Ruby おける真と偽

Ruby では『false もしくは nil 』は偽、『それ以外以外の全てのオブジェクト』は真になります。
なので、0 という数値も Ruby では真となります。

result = if 0
    42
end

p result
# => 42

他の言語では 0 が偽として扱われることも多いので Ruby を使う場合は注意する必要があります。

Ruby でビット演算する場合の注意

さて、例えば C++ で『任意のビットが立っているかどうか』を判定する為に & 演算子を使うことがあります。

// n に対して 0b0001 ビットが立っているかどうか判定する
if( n & 0b0001 ){
    std::cout << "ok" << std::endl;
}

これは n & 0b0001 の結果が 0 であれば『n0b0001 ビットが立っていない』と判定できるためです。
これをそのまま Ruby で書くと以下のようになると思います。

if n & 0b0001
    "OK"
end

ですが、上記のコードでは正しく動作しません。
なぜなら『C++ では 0 が偽』として扱われますが、『Ruby では 0 が真』として扱われるためです。
つまり C++ では『0b0000 & 0b01010 を返すので偽』となりますが、 Ruby では『0b0000 & 0b01010 を返しても真』となってしまうからです。

def check n
    if n & 0b0001
        "OK"
    else
        "NG"
    end
end

p check 0b1111
# => "OK"
p check 0b1100
# => "NG"

これを正しく動作させるためにはビット演算だけではなくて『結果が 0 かどうか』も判定する必要があります。

def check n
    if n & 0b0001 != 0
        "OK"
    else
        "NG"
    end
end

p check 0b1111
# => "OK"
p check 0b1100
# => "NG"

ちなみにこれを回避するために Integer#anybits? みたいなメソッドを入れるかどうかみたいな議論がされていたりします。

まとめ

  • Ruby では falsenil が偽
  • Ruby では falsenil 以外が真
  • 0 も真として扱われる
  • 0 を偽と扱うようなコードを記述する場合は注意する必要がある


真理値以外を返す比較演算子もあるので注意しましょう。

参照