2月に読んだ本やマンガ

2月の読書メーター
読んだ本の数:15
読んだページ数:2699
ナイス数:0

法華経 2018年4月 (100分 de 名著)法華経 2018年4月 (100分 de 名著)
読了日:02月03日 著者:
エイジ’87 1 (1巻) (ヤングキングコミックス)エイジ’87 1 (1巻) (ヤングキングコミックス)
読了日:02月03日 著者:上山 道郎
武の心 (文春文庫)武の心 (文春文庫)
読了日:02月07日 著者:津本 陽
甘々と稲妻(12) (アフタヌーンKC)甘々と稲妻(12) (アフタヌーンKC)
読了日:02月07日 著者:雨隠 ギド
バキ外伝 疵面-スカーフェイス-(8) (チャンピオンREDコミックス)バキ外伝 疵面-スカーフェイス-(8) (チャンピオンREDコミックス)
読了日:02月08日 著者:板垣恵介,山内雪奈生
フェイト/エクストラ CCC (4) (角川コミックス・エース)フェイト/エクストラ CCC (4) (角川コミックス・エース)
読了日:02月12日 著者:ろび~な
海と陸をつなぐ進化論 気候変動と微生物がもたらした驚きの共進化 (ブルーバックス)海と陸をつなぐ進化論 気候変動と微生物がもたらした驚きの共進化 (ブルーバックス)
読了日:02月15日 著者:須藤 斎
はぐれアイドル地獄変 (8) (ニチブンコミックス)はぐれアイドル地獄変 (8) (ニチブンコミックス)
読了日:02月19日 著者:高遠 るい
ベタープログラマ ―優れたプログラマになるための38の考え方とテクニックベタープログラマ ―優れたプログラマになるための38の考え方とテクニック
読了日:02月19日 著者:Pete Goodliffe
3×3EYES 鬼籍の闇の契約者(4) (ヤンマガKCスペシャル)3×3EYES 鬼籍の闇の契約者(4) (ヤンマガKCスペシャル)
読了日:02月21日 著者:高田 裕三
入門 監視 ―モダンなモニタリングのためのデザインパターン入門 監視 ―モダンなモニタリングのためのデザインパターン
読了日:02月22日 著者:Mike Julian
NHK「100分de名著」ブックス道元 正法眼蔵―わからないことがわかるということが悟りNHK「100分de名著」ブックス道元 正法眼蔵―わからないことがわかるということが悟り
読了日:02月23日 著者:ひろ さちや
オーバーロード (11) (角川コミックス・エース)オーバーロード (11) (角川コミックス・エース)
読了日:02月26日 著者:深山 フギン,大塩 哲史
オーバーロード 不死者のOh! (4) (角川コミックス・エース)オーバーロード 不死者のOh! (4) (角川コミックス・エース)
読了日:02月26日 著者:じゅうあみ
NHK「100分de名著」ブックス 荘子NHK「100分de名著」ブックス 荘子
読了日:02月26日 著者:玄侑 宗久

読書メーター

RubyのRefinementでモジュールincludeやalias定義はどうなるか

確認してみた結果、refineincludeしたモジュールのメソッドや定義したエイリアスは、refinementをusingしたときだけ有効になった。

refineincludeしたモジュールはusingしても見えないがメソッドは有効になるようだ。

確認コード:

module IncludeMethod
  def include_method
    :include
  end
end

module RefineMethod
  refine Object do
    include IncludeMethod

    def refine_method
      :refine
    end

    alias refine_method_alias refine_method
  end
end

p Object.include? IncludeMethod

begin
  refine_method
rescue
  p $!
end

begin
  refine_method_alias
rescue
  p $!
end

begin
  include_method
rescue
  p $!
end

using RefineMethod

p Object.include? IncludeMethod
p refine_method
p refine_method_alias
p include_method

確認結果:

$ ruby ex_refine.rb
false
#<NameError: undefined local variable or method `refine_method' for main:Object
Did you mean?  define_method>
#<NameError: undefined local variable or method `refine_method_alias' for main:Object
Did you mean?  define_method>
#<NameError: undefined local variable or method `include_method' for main:Object>
false
:refine
:refine
:include

Emacs-Lispのリスト用関数

よく知られたmapcar以外にもリスト操作のための関数がないか探したら、seq-系の関数が該当するようだ。

www.gnu.org

(seq-elt sequence index)
(seq-length sequence)
(seqp sequence)
(seq-drop sequence n)
(seq-take sequence n)
(seq-take-while predicate sequence)
(seq-drop-while predicate sequence)
(seq-do function sequence)
(seq-map function sequence)
(seq-map-indexed function sequence)
(seq-mapn function &rest sequences)
(seq-remove predicate sequence)
(seq-reduce function sequence initial-value)
(seq-some predicate sequence)
(seq-find predicate sequence &optional default)
(seq-every-p predicate sequence)
(seq-empty-p sequence)
(seq-count predicate sequence)
(seq-sort function sequence)
(seq-sort-by function predicate sequence)
(seq-set-equal-p sequence1 sequence2 &optional testfn)
(seq-position sequence elt &optional function)
(seq-uniq sequence &optional function)
(seq-subseq sequence start &optional end)
(seq-concatenate type &rest sequences)
(seq-mapcat function sequence &optional type)
(seq-partition sequence n)
(seq-intersection sequence1 sequence2 &optional function)
(seq-difference sequence1 sequence2 &optional function)
(seq-group-by function sequence)
(seq-into sequence type)
(seq-min sequence)
(seq-max sequence)
(seq-doseq (var sequence) body...)
(seq-let arguments sequence body...)
(seq-random-elt sequence)

たいていのことは出来そうだ。

RubyのRefinementされたメソッドの性能

通常のメソッドと比べて性能に差があるのかどうか比べてみた。

require 'benchmark'

class Integer
  def to_comma
    to_s.reverse.scan(/\d\d?\d?/).join(',').reverse
  end
end

def method_no_args
end

module RefineMethod
  refine Object do
    def refine_method_no_args
    end
  end
end

n = ARGV.shift || '1_000_000'
n = n.to_i
puts "#{n.to_comma} times."

Benchmark.bm(45) do |x|
  x.report('method_no_args') {
    n.times do
      method_no_args
    end
  }
  x.report('refine_method_no_args') {
    using RefineMethod
    n.times do
      refine_method_no_args
    end
  }
end

結果、まったく差がなかった。

1,000,000 times.
                                                    user     system      total        real
method_no_args                                  0.549699   0.000000   0.549699 (  0.550169)
refine_method_no_args                           0.500810   0.000000   0.500810 (  0.501193)

性能のことは気にせずRefinementを使おう。

Rubyのaccept_nonblock(exception: false)

Rubyのサーバーソケットのaccept_nonblockは、IOread_nonblockと同様にexception: falseIO::WaitReadableを投げないようにできる。

例外を投げる場合と投げない場合で、どれくらい差があるものなのか実験してみた。

require 'benchmark'
require 'socket'

class Integer
  def to_comma
    to_s.reverse.scan(/\d\d?\d?/).join(',').reverse
  end
end

repeat_num = Integer(ARGV.shift || '1_000_000')
puts "repeat: #{repeat_num.to_comma}"

s = TCPServer.new(0)
Benchmark.bm(35) do |x|
  x.report('accept_nonblock') do
    repeat_num.times do
      begin
        s.accept_nonblock
      rescue IO::WaitReadable, Errno::EINTR
        # nothing to do.
      end
    end
  end

  x.report('accept_nonblock(exception: false)') do
    repeat_num.times do
      begin
        if (r = s.accept_nonblock(exception: false)) then
          if (r != :wait_readable) then
            r
          end
        end
      rescue Errno::EINTR
        # `exception: false'で捕捉されるのは
        # EAGAIN/EWOULDBLOCK,ECONNABORTE,EPROTOだけなので、例外EINTRの
        # 捕捉は必要。
      end
    end
  end
end

結果:

$ ./benchmark_socket_accept_nonblock.rb
repeat: 1,000,000
                                          user     system      total        real
accept_nonblock                      20.477151   7.877416  28.354567 ( 29.273192)
accept_nonblock(exception: false)     2.606960   6.471008   9.077968 (  9.108173)

exception: falseの方が3倍速い。 しかし差がつくのはそもそも接続が来ないときなんだよな。 使ったほうがよいのかどうか迷う。

Emacsのimenuで選択される関数名の横幅をもっと広くする

Emacsでプログラミングするときにhelm-imenuでよく関数定義へジャンプするのだが、デフォルトだとimenuの候補に出てくる関数名が60文字でぶった切られて、長い関数名が隠れてしまう。名前空間がネストしたり分かりやすいクラス名やメソッド名をつけると60文字を超えてしまうこともよくあるので不便だった。

imenu.elを調べたらimenu-max-item-lengthで長さを設定できることが分かった。

(setq imenu-max-item-length 256)

これで解決。