DevelopersMeeting20210416Japan
https://bugs.ruby-lang.org/issues/17734
DateTime and location
- 4/16 (Fri) 13:00-17:00 JST @ Online
Next Date
- 5/21 (Fri) 13:00-17:00 JST @ Online
- pre-reading: 5/19 (Wed)
Announce
About release timeframe
- 3.0.1/2.7.3/2.6.7/2.5.9 have been released
Tickets
[Feature #17398] SyntaxError in endless method (jeremyevans0)
- I don’t believe this is a bug, but maybe it is a useful feature.
- @mame has a patch that allows commands as the RHS of a endless method.
- However, @mame’s patch doesn’t allow direct usage with method visibility methods such as private.
- Do we want to support this syntax, or can this be closed (or moved to Feature)?
Preliminary discussion:
- mame: I created the patch, but I’m not keen to merge it.. The implemention is redundant, and the syntax will be more confusing.
Discussion:
# current: SyntaxError
# mame's patch: Allow
def foo() = puts "bar"
# current: SyntaxError
# mame's patch: SyntaxError
private def foo() = puts "bar"
p var = puts("bar") # OK
p var = puts "bar" # NG
- matz: If Ruby were young, I would accept mame’s patch. But now, I don’t know which is better.
- matz: I like the patch. I’m positive but the limitation is not preferable
- nobu: How about moving the ticket to Feature tracker and continue to discuss?
off topic:
- ko1: How about PEG?
- matz: Some mruby variant uses lemon parser generator instead of bison, for memory efficiency. It is possible to replace it
Conclusion:
- matz: move it to Feature tracker and will reply
[Bug #17403] Remove Fixnum and Bignum (jeremyevans0)
- Do we want to remove Fixnum and Bignum in Ruby 3.1?
- If not, can we decide on a later version where they can be removed, such as 3.2 or 4.0?
Preliminary discussion:
- mame: maybe postponed to 3.2 because naruse-san says 3.1 will have no incompatibility in principle
Discussion:
- naruse: No at least 3.1
Conclusion:
- postpone to 3.2
[Bug #16983] RubyVM::AbstractSyntaxTree.of(method) returns meaningless node if the method is defined in eval (jeremyevans0)
RubyVM::AbstractSyntaxTree.of(method)relies on reading the file with the method source, which could have changed or could not exist at all.- I don’t think we can work around that without keeping the abstract syntax tree or source code of all methods in memory, which seems wasteful.
- Is the current behavior a bug, or should we just accept the current behavior as spec and close this?
Preliminary discussion:
- ko1: Maybe we should a flag to represent that a method object is created in eval (and make
AST.ofan error).
Discussion:
- (no discussion)
Conclusion:
- ko1: Will do.
[Bug #9542] Delegator does not delegate protected methods (jeremyevans0)
- Do we want to add a way to tell if a method was called with an implicit receiver or self?
- We may be able to implement this via a VM frame flag and a method to check it.
- If we don’t want to add such a way, can we accept the current behavior as spec and close this?
Preliminary discussion:
- nobu: current behavior is expected, other than the error message.
require "delegate" class Cow def unprotected_moo "mooooo" end protected def protected_moo "guarded mooooo!" end end my_cow = Cow.new puts SimpleDelegator.new(my_cow).unprotected_moo # => "mooooo!" puts SimpleDelegator.new(my_cow).protected_moo # => "guarded mooooo!" in 2.0 # => undefined method `protected_moo' (NoMethodError) in 2.1... puts my_cow.unprotected_moo # => "mooooo!" puts my_cow.protected_moo # => protected method `protected_moo' called (NoMethodError) in 2.1... - mame: protected method must not be called in this calling style.
Discussion:
- nobu: the error message is wrong; it should be “protected method xxx called” instead of “undefined method xxx called”
Conclusion:
- matz: the behavior change between 2.0 and 2.1 is a bug fix.
[Bug #11230] Should rb_struct_s_members() be public API? (jeremyevans0)
- This is still public in the C-API.
- Do we want to keep it and close this issue, or do we want to remove it?
- If we want to remove it, how should it be deprecated?
Preliminary discussion:
ko1@aluminium:~$ csearch rb_struct_s_members
jameskilton-rice-1.2.0/test/test_Struct.cpp: // can't call rb_struct_s_members, because this isn't a struct yet
jameskilton-rice-1.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s));
jameskilton-rice-1.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
jameskilton-rice-1.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
metasm-1.0.4/metasm/os/gnu_exports.rb: rb_struct_alloc rb_struct_aref rb_struct_aset rb_struct_define rb_struct_getmember rb_struct_iv_get rb_struct_members rb_struct_new rb_struct_s_members
metasm-1.0.4/metasm/os/windows_exports.rb: rb_struct_getmember rb_struct_iv_get rb_struct_members rb_struct_new rb_struct_s_members rb_svar rb_sym_all_symbols rb_symname_p rb_sys_fail rb_sys_warning
rice-2.2.0/test/test_Struct.cpp: // can't call rb_struct_s_members, because this isn't a struct yet
rice-2.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s));
rice-2.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
rice-2.2.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
rice-jdguyot-1.4.0/test/test_Struct.cpp: // can't call rb_struct_s_members, because this isn't a struct yet
rice-jdguyot-1.4.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s));
rice-jdguyot-1.4.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
rice-jdguyot-1.4.0/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
rubyosa19-0.6.2/ext/rubyosa/osx_intern.h:VALUE rb_struct_s_members(VALUE);
open script_core-0.2.6/ext/enterprise_script_service/mruby/mrbgems/mruby-struct/src/struct.c: no such file or directory
wurlinc-rice-1.4.0.4/test/test_Struct.cpp: // can't call rb_struct_s_members, because this isn't a struct yet
wurlinc-rice-1.4.0.4/test/test_Struct.cpp: Array members(rb_struct_s_members(s));
wurlinc-rice-1.4.0.4/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
wurlinc-rice-1.4.0.4/test/test_Struct.cpp: Array members(rb_struct_s_members(s2));
- ko1: it seems nobody use on lib or app.
Discussion:
- shyouhei: There also is
rb_struct_members(). What is the difference? - nobu:
rb_struct_s_members()takes a struct class, whilerb_struct_members()takes its instance. - matz: It might be difficult to implement
rb_struct_s_members()on top ofrb_struct_members()because doing so needs a temporary instance. - shyouhei: It seems there also is
rb_struct_s_members_m()which can be called viaStruct.members. - ko1: Users of
rb_struct_s_members()can resort to call that method viarb_funcall, theoretically. - ko1: But in reality it seems there is no practical usages.
- shyouhei: Delete it then.
- nobu: Are there really no usages…?
- naruse: We could revive this if any later.
- shyouhei: Should we provide such transition path? Or just delete it?
Conclusion:
- Everyone agreed with the removal, but it should be removed after 3.2
[Feature #17749] Add Module#source_location (tenderlovemaking)
- It’s similar to the const_source_location feature, but easier to use when you don’t know the constant name, or enclosing const
- This is useful for debugging
Preliminary discussion:
- ko1: weakly related: https://github.com/ruby/ruby/pull/4370
- mame: I don’t see actual use case. But I guess it would be useful for memory profiling purpose or what not? I’m for this proposal
- ko1: I have two concerns about the patch. (1) a class created by
Class.newwill have a different result (allocated site) fromconst_source_location(site assigned to a constant). (2)rb_const_source_location_of()seems to be declared and not defined. - ko1: Aaron said it is allocation site. https://github.com/ruby/ruby/pull/4324#issuecomment-816319444
- mame:
const_source_locationandsource_locationis similar but different. I don’t think it is a good idea to introduce similar features in terms of maintenance, unless it is really needed.
Discussion:
module A
class B
end
end
p A::B.source_location
Conclusion:
- matz: I don’t bother but at least there are people who need this…
- mame: I’ll ask the usecase.
[Feature #17753] Add Module#namespace (tenderlovemaking)
A::B.namespacewill returnA- This is to help with finding “sibling” constants of
Bso we don’t have to parse the constant name - This is also useful for debugging
Preliminary discussion:
- it seems difficult to name…
Discussion:
- nobu: It resembles the nesting of a module but not the same.
- matz: I don’t want to accept this, at least, as-is. If the receiver is literally like
M::N,M::N.namespaceis obvious. So, it will make sense in form likesome_klass.namespace, but I’m unsure if it deserves as the name. - matz: I’d like to use the general good word “namespace” for another concept.
- knu: There is demodulize in Rails.
- https://www.rubydoc.info/github/rubyworks/facets/String:modulize
- akira: this is very slightly different from the proposed one.
- mame: We will next want a method that returns
BfromA::B - ko1: What does they return?
Class.new{}.namespaceC.namespace# toplevel module
Conclusion:
- matz: Please explain use case, and propose other names then
namespace. (outer_scope also looks weird)
[Feature #17762] A simple way to trace object allocation (mame)
- I want
require "objspace/trace"or something which is a very useful debugging tool to identify the allocation site of an object.
Preliminary discussion:
- mame: Enabling a feature just by
requireis arguable. And extendingKernel#pis more arguable.
Discussion:
- matz: looks good.
Conclusion:
- matz: accepted
[Feature #17682] String#casecmp performance improvement (dan0042)
- Is it ok to make
casecmpfaster?
Preliminary discussion:
- mame: It is a bit difficult to maintain, but if noby says okay, I’m okay
Discussion:
- shyouhei: naruse can you review?
- naruse: I will.
[Feature #15198] Add Array#intersect? (marcandre)
- Ok to add?
Preliminary discussion:
- ko1: is there many use cases for this?
- mame: There are already Array#intersection and Array#union. Can we add
Array#intersect??Array#union?looks non-sense. (I’m not against, but just want to confirm) - knu: set.rb has already
Set#intersect?and I’ve seen many use cases for this. - knu: Extending
include?()to accept an arbitrary number of values could be an option, but that would open Pandora’s box when many other builtin classes have `include?. - nobu: Should it accept multiple arrays?
- – maybe, but not part of this request.
Discussion:
- (no discussion)
Conclusion:
- matz: OK.
[Feature #17795] before_fork and after_fork callback API (byroot)
- Many libraries out there use various tricks to detect the process being forked, most commonly
Process.pid != @pid, butglibcno longer cache the PID so these libraries end up doing syscalls in tight loops. - If a callback API is too complicated, I proposed a simplee alternative that is to have
Kernel.forkbe a simple delegator toProcess.forkhttps://github.com/ruby/ruby/pull/4361, This would makes it easy for libraries to decorate fork to have their own callbacks on either before or after fork.
Preliminary discussion:
- ko1: I want this for debugger implementation (3 hooks).
- mrkn: It is good to provide both after_fork_parent and after_fork_child instead of one after_fork.
- mame: I’m unsure if Kernel#fork and Process.fork are enough. Process.daemon is really needed?
- nobu:
IO.popen("-")is also a fork - mame: How about extension libraries? Maybe we don’t have to care them?
Discussion:
- mrkn: Python provides C-API to call registered hooks. https://github.com/python/cpython/blob/master/Modules/posixmodule.c#L570-L588
- background ticket: https://bugs.ruby-lang.org/issues/5446#note-18
- shyouhei: Understand both byroot’s needs and jeremyevens’ concern.
- ko1: Is it possible to reroute Jeremy’s problem?
- shyouhei: At least user-defined
forkappears on backtrace on errors, which is better than silently break things. - akr: Jeremy’s concern looks valid. An appropriate way to handle DB connection before and after fork depends on each application, not libraries. So, this proposed API may lead to misuse. Rather, supporting PID monitoring looks good. If getpid is slow, it may be good to provide another way such as Process.fork_level that returns how many “fork” is called.
p Process.fork_level #=> 0
if fork
p Process.fork_level #=> 0
else
p Process.fork_level #=> 1
end
-
akr: Process.daemon is very special, so it doesn’t have to call the hooks (or update fork_level)
- mame: There are two fork methods: Kernel#fork and Process.fork. All libraries that want to wrap them need to wrap both.
- ko1: A library A wraps only Kernel#fork, and library B wraps only Process.fork
Conclusion:
- akr: Will counter-propose fork_level.
[Feature #17016] Add Enumerable#accumulate (parkerfinch)
- Is the name
#accumulateacceptable? - Is this feature ok to add?
Preliminary discussion:
- mame: I’m unsure about use case
- mrkn: cumulative sum is reasonable, but other examples are not so convincing
- knu: eregon’s code looks great and intuitive
val = 0
p (0..).lazy.map { |x| val += x }.first(4) # => [0, 1, 3, 6]
val = 0
p [0] + (1..).lazy.map { |x| val += x }.first(3) # => [0, 1, 3, 6]
- knu: This may be generalization of
Enumerator.producein which a value to yield and a value to pass to the next iteration are the same.
Discussion:
[1, 2, 3].accumulate(0, &:+) => [0, 1, 3, 6]
- https://reference.wolfram.com/language/ref/Accumulate.html
-
https://reference.wolfram.com/language/ref/FoldList.html
- mame: ↓ is crystal clear to me
ret = []
accum = 0
ary.each do |e|
accum += e
ret << accum
end
Conclusion:
- conclusion is not reached