From: "shyouhei (Shyouhei Urabe) via ruby-core" Date: 2023-08-09T08:21:13+00:00 Subject: [ruby-core:114368] [Ruby master Feature#19832] Method#destructive?, UnboundMethod#destructive? Issue #19832 has been updated by shyouhei (Shyouhei Urabe). Dan0042 (Daniel DeLorme) wrote in #note-13: > shyouhei (Shyouhei Urabe) wrote in #note-12: > > Do you mean `IO#printf` is not destructive because everything destructive is implemented by `IO#write` and printf is merely calling it? That sounds counter-intuitive to me. > > Ok, I think we have different ideas of what is "destructive", because to me it's not about side-effects that would require a Monad if we were coding in Haskell. Because we are coding in Ruby, I would define a "destructive" operation as something that fails if the object is frozen. And `@buf << 42` does not fail if `self` is frozen. This is how the frozen flag has always worked and I can't really imagine introducing a new way of defining/handling destructive operations. So in that sense neither `IO#printf` nor `IO#write` are destructive. ```ruby STDOUT.freeze.printf("Hello, World!") ``` But yes, I agree that the word "destructive" here is kind of vague, and we are seeing different things. Maybe @sawa could show us his intended usage of the propsed functionality for more pragmatic discussions. ---------------------------------------- Feature #19832: Method#destructive?, UnboundMethod#destructive? https://bugs.ruby-lang.org/issues/19832#change-104111 * Author: sawa (Tsuyoshi Sawada) * Status: Open * Priority: Normal ---------------------------------------- I propose to add `destructive?` property to `Method` and `UnboundMethod` instances, which shall behave like: ```ruby String.instance_method(:<<).destructive? # => true String.instance_method(:+).destructive? # => false ``` One main purpose of using these classes is to inspect and make sure how a certain method behaves. Besides arity and owner, whether a method is destructive or not is one important piece of information, but currently, you cannot achieve that from `Method` or `UnboundMethod` instances. The problem is how to implement this. It is best if this information (whether or not a method is destructive) can be extracted automatically from the method definition. Unlike owner and arity, it may or may not be straightforward by statically analyzing the code. I think that, if a method definition defined at the ruby level does not call a destructive method anywhere within its own definition, and no dynamic method calls (`send`, `eval`, etc.) are made, then we can say that the method is non-destructive. If it does call, then the method is most likely a destructive method (it would not be destructive if the internally-called destructive method is applied to a different object. Or, we could rather call that a destructive method in the sense that it has a destructive side effect). If doing that turns out to be difficult for some or all cases, then a practical approach for the difficult cases is to label the methods as destructive or not, manually. We can perhaps have methods `Module#destructive` and `Module#non_destructive` which take (a) symbol/string argument(s) and return the method name(s) in symbol so that they can be used like: ```ruby class A destructive private def some_destructive_private_method ... end end ``` or ```ruby class A def foo; ... end def bar; ... end def baz; ... end non_destructive :foo, :baz destructive :bar end ``` or ```ruby class A non_destructive def foo; ... end def baz; ... end destructive def bar; ... end end ``` When the method is not (yet) specified whether destructive or not, the return value can be `"unknown"` (or `:unknown` or `nil`) by default. ```ruby String.instance_method(:<<).destructive? # => "unknown" ``` -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/