方向を間違えた件

昨日の記事babieさんが反応 してくださったけれど、

[64, 65, 66].map(&(:succ * :chr * :to_sym)) って前から作用するのかぁ、* だと順番がよくイメージできないなぁ。そんなもん?

うわあぁぁぁ。方向を間違えて実装した件。合成をそうやって定義する流儀もあるけど、マイナーだよね。少なくとも、私の意図や『圏論の基礎』とは違う。なぜサンプルを書いてる時点で気づかなかったんだろう。穴があったら入りたい。

実装(改)

Procを混ぜられるようにも意図してたんだけれど、Procが左辺の場合を忘れていたのでそれも含めて修正。

class Symbol
  unless instance_methods.include?("to_proc")
    def to_proc
      Proc.new{|obj, *args| obj.__send__(self, *args)}
    end
  end

  def * rhs
    MethodComposition.new([rhs.to_proc, self.to_proc])
  end

  def ** num
    MethodComposition.new(Array.new(num, self.to_proc))
  end
end

class Proc
  def * rhs
    MethodComposition.new([rhs.to_proc, self])
  end

  def ** num
    MethodComposition.new(Array.new(num, self))
  end
end

class MethodComposition
  def initialize(elements = [])
    @chain = elements
  end

  def * rhs
    MethodComposition.new(@chain.dup.unshift(rhs.to_proc))
  end

  def ** num
    MethodComposition.new(@chain * num)
  end

  def to_proc
    Proc.new{|receiver|
      @chain.inject(receiver) {|obj, proc| proc.call(obj) }
    }
  end
end

class Object
  def callcomp(proc = nil)
    unless proc
      self
    else
      proc.to_proc.call self
    end
  end
end

実行例

(0...3).map(&(:to_sym * :chr * :succ**64))                          # => [:A, :B, :C]

無意味に結合律を試してみたり。

(0...3).map &((:intern * :succ) * (:chr * :succ**32) * :succ**32)   # => [:A, :B, :C]

lambdaを混ぜてみたり

(0...3).map &(lambda{|x| "#{x}#{x.length}"}**3 * :chr * :succ**65)  # => ["A123", "B123", "C123"]

便利だか便利でないんだか分からなかったり

"".callcomp(:inspect ** 3)    # => "\"\\\"\\\\\\\"\\\\\\\"\\\"\""

遊んでみたり

(0..4).map &( :inspect * ObjectSpace::method(:_id2ref)) 
  # => ["false", "0", "true", "1", "nil"]


(0..4).map &( lambda{|x| class<<x; self; end}**2 * :class * ObjectSpace::method(:_id2ref) ) 

  # => [#<Class:#<Class:FalseClass>>, #<Class:#<Class:Fixnum>>, 
        #<Class:#<Class:TrueClass>>, #<Class:#<Class:Fixnum>>, #<Class:#<Class:NilClass>>]

もう、無茶苦茶

(-4..0).map &( :succ**((?z-?s)*(1+26)) * (:to_s * lambda{|x| class<<x; self; end} * :class) * 
               ObjectSpace::method(:_id2ref) * :-@)

  # => ["#<Class:NilClazz>", "#<Class:Fixobt>", 
        "#<Class:TrueClazz>", "#<Class:Fixobt>", "#<Class:FalseClazz>"]