0

mapcarRubyでLispを実装したい。

希望に満ちた構文:

mul = -> (*args) { args.reduce(:*) }

mapcar(mul, [1,2,3], [4,5], [6]) would yield [24, nil, nil].

これが私が考えることができる解決策です:

arrs[0].zip(arrs[1], arrs[2]) => [[1, 4, 6], [2, 5, nil], [3, nil, nil]]

次に、次のことができます。

[[1, 4, 6], [2, 5, nil], [3, nil, nil]].map do |e| 
  e.reduce(&mul) unless e.include?(nil)
end

=> [24, nil, nil]

しかし、私はそのzip部分にこだわっています。入力が の場合[[1], [1,2], [1,2,3], [1,2,3,4]]zipパーツは次のように変更する必要があります。

arrs[0].zip(arrs[1], arrs[2], arrs[3])

2 つの入力配列の場合、次のように記述できます。

def mapcar2(fn, *arrs)
  return [] if arrs.empty? or arrs.include? []
  arrs[0].zip(arrs[1]).map do |e|
    e.reduce(&fn) unless e.include? nil
  end.compact
end

しかし、2 つ以上の配列を超える方法がわかりません。

def mapcar(fn, *arrs)
  # Do not know how to abstract this
  # zipped = arrs[0].zip(arrs[1], arrs[2]..., arrs[n-1])
  # where n is the size of arrs
  zipped.map do |e| 
    e.reduce(&fn) unless e.include?(nil)
  end.compact
end

誰かアドバイスはありますか?

4

2 に答える 2

0

toro2k によると、Ruby での mapcar の可能な実装の 1 つ:

def mapcar(fn, *arrs)
  return [] if arrs.empty? or arrs.include? []
  transposed = if arrs.all? { |a| arrs.first.size == a.size }
                 arrs.transpose
               else
                 arrs[0].zip(*arrs.drop(1))
               end
  transposed.map do |e|
    e.collect(&fn) unless e.include? nil
  end.compact!
end
于 2014-05-11T14:05:45.933 に答える