summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--mrbgems/mruby-enum-ext/mrblib/enum.rb47
-rw-r--r--mrblib/array.rb12
-rw-r--r--mrblib/enum.rb48
-rw-r--r--test/t/enumerable.rb16
4 files changed, 89 insertions, 34 deletions
diff --git a/mrbgems/mruby-enum-ext/mrblib/enum.rb b/mrbgems/mruby-enum-ext/mrblib/enum.rb
index f250d39f1..90f321596 100644
--- a/mrbgems/mruby-enum-ext/mrblib/enum.rb
+++ b/mrbgems/mruby-enum-ext/mrblib/enum.rb
@@ -161,4 +161,51 @@ module Enumerable
h
end
+ ##
+ # call-seq:
+ # enum.sort_by { |obj| block } -> array
+ #
+ # Sorts <i>enum</i> using a set of keys generated by mapping the
+ # values in <i>enum</i> through the given block.
+ def sort_by(&block)
+ ary = []
+ orig = []
+ self.each_with_index{|e, i|
+ orig.push(e)
+ ary.push([block.call(e), i])
+ }
+ if ary.size > 1
+ __sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1) do |a,b|
+ a <=> b
+ end
+ end
+ ary.collect{|e,i| orig[i]}
+ end
+
+ NONE = Object.new
+ ##
+ # call-seq:
+ # enum.first -> obj or nil
+ # enum.first(n) -> an_array
+ #
+ # Returns the first element, or the first +n+ elements, of the enumerable.
+ # If the enumerable is empty, the first form returns <code>nil</code>, and the
+ # second form returns an empty array.
+ def first(n=NONE)
+ if n == NONE
+ self.each do |e|
+ return e
+ end
+ return nil
+ else
+ a = []
+ i = 0
+ self.each do |e|
+ break if n<=i
+ a.push e
+ i += 1
+ end
+ a
+ end
+ end
end
diff --git a/mrblib/array.rb b/mrblib/array.rb
index aa50ac181..f3c7967cb 100644
--- a/mrblib/array.rb
+++ b/mrblib/array.rb
@@ -97,6 +97,18 @@ class Array
ret
end
end
+
+ # internal method to convert multi-value to single value
+ def __svalue
+ case self.size
+ when 0
+ return nil
+ when 1
+ self[0]
+ else
+ self
+ end
+ end
end
##
diff --git a/mrblib/enum.rb b/mrblib/enum.rb
index 53f2119b0..ea032524e 100644
--- a/mrblib/enum.rb
+++ b/mrblib/enum.rb
@@ -81,8 +81,8 @@ module Enumerable
return to_enum :collect unless block_given?
ary = []
- self.each{|val|
- ary.push(block.call(val))
+ self.each{|*val|
+ ary.push(block.call(*val))
}
ary
end
@@ -97,9 +97,9 @@ module Enumerable
# ISO 15.3.2.2.4
def detect(ifnone=nil, &block)
ret = ifnone
- self.each{|val|
- if block.call(val)
- ret = val
+ self.each{|*val|
+ if block.call(*val)
+ ret = val.__svalue
break
end
}
@@ -115,8 +115,8 @@ module Enumerable
# ISO 15.3.2.2.5
def each_with_index(&block)
i = 0
- self.each{|val|
- block.call(val, i)
+ self.each{|*val|
+ block.call(val.__svalue, i)
i += 1
}
self
@@ -129,8 +129,9 @@ module Enumerable
# ISO 15.3.2.2.6
def entries
ary = []
- self.each{|val|
- ary.push val
+ self.each{|*val|
+ # __svalue is an internal method
+ ary.push val.__svalue
}
ary
end
@@ -150,8 +151,8 @@ module Enumerable
# ISO 15.3.2.2.8
def find_all(&block)
ary = []
- self.each{|val|
- ary.push(val) if block.call(val)
+ self.each{|*val|
+ ary.push(val.__svalue) if block.call(*val)
}
ary
end
@@ -214,7 +215,8 @@ module Enumerable
flag = false
result = args[0]
end
- self.each{|val|
+ self.each{|*val|
+ val = val.__svalue
if flag
# push first element as initial
flag = false
@@ -243,7 +245,8 @@ module Enumerable
def max(&block)
flag = true # 1st element?
result = nil
- self.each{|val|
+ self.each{|*val|
+ val = val.__svalue
if flag
# 1st element
result = val
@@ -269,7 +272,8 @@ module Enumerable
def min(&block)
flag = true # 1st element?
result = nil
- self.each{|val|
+ self.each{|*val|
+ val = val.__svalue
if flag
# 1st element
result = val
@@ -304,11 +308,11 @@ module Enumerable
def partition(&block)
ary_T = []
ary_F = []
- self.each{|val|
- if block.call(val)
- ary_T.push(val)
+ self.each{|*val|
+ if block.call(*val)
+ ary_T.push(val.__svalue)
else
- ary_F.push(val)
+ ary_F.push(val.__svalue)
end
}
[ary_T, ary_F]
@@ -323,8 +327,8 @@ module Enumerable
# ISO 15.3.2.2.17
def reject(&block)
ary = []
- self.each{|val|
- ary.push(val) unless block.call(val)
+ self.each{|*val|
+ ary.push(val.__svalue) unless block.call(*val)
}
ary
end
@@ -385,8 +389,8 @@ module Enumerable
# ISO 15.3.2.2.19
def sort(&block)
ary = []
- self.each{|val| ary.push(val)}
- unless ary.empty?
+ self.each{|*val| ary.push(val.__svalue)}
+ if ary.size > 1
__sort_sub__(ary, ::Array.new(ary.size), 0, 0, ary.size - 1, &block)
end
ary
diff --git a/test/t/enumerable.rb b/test/t/enumerable.rb
index 844251b06..4fa615a8f 100644
--- a/test/t/enumerable.rb
+++ b/test/t/enumerable.rb
@@ -11,17 +11,13 @@ assert('Enumerable#all?', '15.3.2.2.1') do
a = [2,4,6]
all = a.all? do |e|
- if e % 2 == 0
- true
- end
+ e % 2 == 0
end
assert_true(all)
a = [2,4,7]
all = a.all? do |e|
- if e % 2 == 0
- true
- end
+ e % 2 == 0
end
assert_false(all)
end
@@ -32,17 +28,13 @@ assert('Enumerable#any?', '15.3.2.2.2') do
a = [1,3,6]
any = a.any? do |e|
- if e % 2 == 0
- true
- end
+ e % 2 == 0
end
assert_true(any)
a = [1,3,5]
any = a.any? do |e|
- if e % 2 == 0
- true
- end
+ e % 2 == 0
end
assert_false(any)
end