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
-rw-r--r--test/t/nil.rb9
5 files changed, 98 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 59d4b9b0f..5a33ed3c5 100644
--- a/mrblib/enum.rb
+++ b/mrblib/enum.rb
@@ -75,8 +75,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
@@ -91,9 +91,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
}
@@ -109,8 +109,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
@@ -123,8 +123,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
@@ -144,8 +145,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
@@ -206,7 +207,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
@@ -235,7 +237,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
@@ -261,7 +264,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
@@ -296,11 +300,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]
@@ -315,8 +319,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
@@ -377,8 +381,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
diff --git a/test/t/nil.rb b/test/t/nil.rb
index 443178c81..971ce2e8e 100644
--- a/test/t/nil.rb
+++ b/test/t/nil.rb
@@ -5,6 +5,15 @@ assert('NilClass', '15.2.4') do
assert_equal Class, NilClass.class
end
+assert('NilClass', '15.2.4.1') do
+ assert_equal NilClass, nil.class
+ assert_false NilClass.method_defined? :new
+end
+
+assert('NilClass superclass', '15.2.4.2') do
+ assert_equal Object, NilClass.superclass
+end
+
assert('NilClass#&', '15.2.4.3.1') do
assert_false nil.&(true)
assert_false nil.&(nil)