RubyでHaskell風のリスト操作
30分プログラム、その622。RubyにHaskell風のリスト操作を移植しました。
Rubyでコードを書いてるときに、take_whileとかが欲しくなることが何度かあったので、実装してみました。
メソッド内部で副作用を使っているのが何個かありますが、外から見たらちゃんとFunctionalなので許してください。
使い方
p (1..4).take(2) p (1..4).drop(2)
ソースコード
#! /opt/local/bin/ruby -w # -*- mode:ruby; coding:utf-8 -*- # # prelude.rb - # # Copyright(C) 2009 by mzp # Author: MIZUNO Hiroki / mzpppp at gmail dot com # http://howdyworld.org # # Timestamp: 2009/07/17 22:46:58 # # This program is free software; you can redistribute it and/or # modify it under MIT Lincence. # module Enumerable def and() self.inject {|x,y| x && y } end def or() self.inject {|x,y| x || y } end def sum() self.inject{|x,y| x + y } end def product() self.inject{|x,y| x * y } end def scan(init=nil,&f) ys = [] accum = init self.each do|x| if accum == nil accum = x else accum = f.call(accum,x) end ys << accum end ys end def take(n) xs = [] self.each do|x| if n == 0 then break end xs << x n -= 1 end xs end def drop(n) xs = [] self.each do|x| if n > 0 then n -= 1 next end xs << x end xs end def split_at(n) xs = [] ys = [] self.each do|x| if n > 0 then n -= 1 xs << x next end ys << x end [xs,ys] end def take_while(&f) xs = [] self.each do|x| if not f.call(x) then break end xs << x end xs end def drop_while(&f) xs = [] self.each do|x| if f.call(x) then next end xs << x end xs end def span(&f) xs = [] ys = [] self.each do|x| if f.call(x) then xs << x else ys << x end end [xs, ys] end end class Array def init self[0...-1] end end p [1,2,3].init p [true,true,true].and p [true,true,false].or p((1..4).sum) p((1..4).product) p((1..4).scan {|x,y| x+y}) p (1..4).take(2) p (1..4).drop(2) p (1..4).split_at(2)