1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* enum.c (enum_min_by): new method Enum#min_by. added Enum#max_by

as well.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@6629 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 2004-07-14 14:51:42 +00:00
parent 1a760a6f76
commit 6c6a24826c
7 changed files with 113 additions and 25 deletions

View file

@ -1,3 +1,8 @@
Wed Jul 14 23:49:30 2004 Yukihiro Matsumoto <matz@ruby-lang.org>
* enum.c (enum_min_by): new method Enum#min_by. added Enum#max_by
as well.
Wed Jul 14 18:05:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org> Wed Jul 14 18:05:21 2004 GOTOU Yuuzou <gotoyuzo@notwork.org>
* ext/openssl/ossl_asn1.c (ossl_asn1cons_to_der): fix type of * ext/openssl/ossl_asn1.c (ossl_asn1cons_to_der): fix type of

102
enum.c
View file

@ -677,20 +677,6 @@ enum_min(obj)
return result; return result;
} }
/*
* call-seq:
* enum.max => obj
* enum.max {| a,b | block } => obj
*
* Returns the object in <i>enum</i> with the maximum value. The
* first form assumes all objects implement <code>Comparable</code>;
* the second uses the block to return <em>a <=> b</em>.
*
* a = %w(albatross dog horse)
* a.max #=> "horse"
* a.max {|a,b| a.length <=> b.length } #=> "albatross"
*/
static VALUE static VALUE
max_i(i, memo) max_i(i, memo)
VALUE i; VALUE i;
@ -756,6 +742,92 @@ enum_max(obj)
return result; return result;
} }
static VALUE
min_by_i(i, memo)
VALUE i;
NODE *memo;
{
VALUE v;
v = rb_yield(i);
if (NIL_P(memo->u1.value)) {
memo->u1.value = v;
memo->u2.value = i;
}
else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) < 0) {
memo->u1.value = v;
memo->u2.value = i;
}
return Qnil;
}
/*
* call-seq:
* enum.min_by {| obj| block } => obj
*
* Returns the object in <i>enum</i> that gives the minimum
* value from the given block.
*
* a = %w(albatross dog horse)
* a.min_by {|x| x.length } #=> "dog"
*/
static VALUE
enum_min_by(obj)
VALUE obj;
{
VALUE result;
NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
rb_iterate(rb_each, obj, min_by_i, (VALUE)memo);
result = memo->u2.value;
rb_gc_force_recycle((VALUE)memo);
return result;
}
static VALUE
max_by_i(i, memo)
VALUE i;
NODE *memo;
{
VALUE v;
v = rb_yield(i);
if (NIL_P(memo->u1.value)) {
memo->u1.value = v;
memo->u2.value = i;
}
else if (rb_cmpint(rb_funcall(v, id_cmp, 1, memo->u1.value), v, memo->u1.value) > 0) {
memo->u1.value = v;
memo->u2.value = i;
}
return Qnil;
}
/*
* call-seq:
* enum.max_by {| obj| block } => obj
*
* Returns the object in <i>enum</i> that gives the maximum
* value from the given block.
*
* a = %w(albatross dog horse)
* a.max_by {|x| x.length } #=> "albatross"
*/
static VALUE
enum_max_by(obj)
VALUE obj;
{
VALUE result;
NODE *memo = rb_node_newnode(NODE_MEMO, Qnil, 0, 0);
rb_iterate(rb_each, obj, max_by_i, (VALUE)memo);
result = memo->u2.value;
rb_gc_force_recycle((VALUE)memo);
return result;
}
static VALUE static VALUE
member_i(item, memo) member_i(item, memo)
VALUE item; VALUE item;
@ -933,6 +1005,8 @@ Init_Enumerable()
rb_define_method(rb_mEnumerable,"any?", enum_any, 0); rb_define_method(rb_mEnumerable,"any?", enum_any, 0);
rb_define_method(rb_mEnumerable,"min", enum_min, 0); rb_define_method(rb_mEnumerable,"min", enum_min, 0);
rb_define_method(rb_mEnumerable,"max", enum_max, 0); rb_define_method(rb_mEnumerable,"max", enum_max, 0);
rb_define_method(rb_mEnumerable,"min_by", enum_min_by, 0);
rb_define_method(rb_mEnumerable,"max_by", enum_max_by, 0);
rb_define_method(rb_mEnumerable,"member?", enum_member, 1); rb_define_method(rb_mEnumerable,"member?", enum_member, 1);
rb_define_method(rb_mEnumerable,"include?", enum_member, 1); rb_define_method(rb_mEnumerable,"include?", enum_member, 1);
rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0); rb_define_method(rb_mEnumerable,"each_with_index", enum_each_with_index, 0);

View file

@ -365,7 +365,6 @@ class CGI
raise ArgumentError, "session_id `%s' is invalid" % id raise ArgumentError, "session_id `%s' is invalid" % id
end end
@path = dir+"/"+prefix+id @path = dir+"/"+prefix+id
@path.untaint
unless File::exist? @path unless File::exist? @path
@hash = {} @hash = {}
end end
@ -413,7 +412,8 @@ class CGI
# Close and delete the session's FileStore file. # Close and delete the session's FileStore file.
def delete def delete
File::unlink @path File::unlink @path
rescue Errno::ENOENT
end end
end end

View file

@ -711,7 +711,13 @@ class Date
alias_method :__#{id.to_i}__, :#{id.to_s} alias_method :__#{id.to_i}__, :#{id.to_s}
private :__#{id.to_i}__ private :__#{id.to_i}__
def #{id.to_s}(*args, &block) def #{id.to_s}(*args, &block)
(@__#{id.to_i}__ ||= [__#{id.to_i}__(*args, &block)])[0] if @__#{id.to_i}__
@__#{id.to_i}__
elsif ! self.frozen?
@__#{id.to_i}__ ||= __#{id.to_i}__(*args, &block)
else
__#{id.to_i}__(*args, &block)
end
end end
end; end;
end end

View file

@ -69,7 +69,7 @@ class Mutex
# Returns +true+ if this lock is currently held by some thread. # Returns +true+ if this lock is currently held by some thread.
# #
def locked? def locked?
@locked @locked && true
end end
# #
@ -80,7 +80,7 @@ class Mutex
result = false result = false
Thread.critical = true Thread.critical = true
unless @locked unless @locked
@locked = true @locked = Thread.current
result = true result = true
end end
Thread.critical = false Thread.critical = false
@ -92,10 +92,13 @@ class Mutex
# #
def lock def lock
while (Thread.critical = true; @locked) while (Thread.critical = true; @locked)
if @locked == Thread.current
raise ThreadError, "deadlock; recursive locking"
end
@waiting.push Thread.current @waiting.push Thread.current
Thread.stop Thread.stop
end end
@locked = true @locked = Thread.current
Thread.critical = false Thread.critical = false
self self
end end

View file

@ -35,6 +35,7 @@ module Timeout
def timeout(sec, exception=Error) def timeout(sec, exception=Error)
return yield if sec == nil or sec.zero? return yield if sec == nil or sec.zero?
raise ThreadError, "timeout within critical session" if Thread.critical
begin begin
x = Thread.current x = Thread.current
y = Thread.start { y = Thread.start {

View file

@ -5391,11 +5391,10 @@ static NODE*
cond0(node) cond0(node)
NODE *node; NODE *node;
{ {
enum node_type type = nd_type(node); if (node == 0) return 0;
assign_in_cond(node); assign_in_cond(node);
switch (type) { switch (nd_type(node)) {
case NODE_DSTR: case NODE_DSTR:
case NODE_EVSTR: case NODE_EVSTR:
case NODE_STR: case NODE_STR:
@ -5419,8 +5418,8 @@ cond0(node)
case NODE_DOT3: case NODE_DOT3:
node->nd_beg = range_op(node->nd_beg); node->nd_beg = range_op(node->nd_beg);
node->nd_end = range_op(node->nd_end); node->nd_end = range_op(node->nd_end);
if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2); if (nd_type(node) == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3); else if (nd_type(node) == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
node->nd_cnt = local_append(internal_id()); node->nd_cnt = local_append(internal_id());
if (!e_option_supplied()) { if (!e_option_supplied()) {
int b = literal_node(node->nd_beg); int b = literal_node(node->nd_beg);