Issue #17004 has been updated by jeremyevans0 (Jeremy Evans).


duerst (Martin D=FCrst) wrote in #note-12:
> - Where there are performance implications, couldn't that be solved by an
>   additional parameter to the methods in question? Or by a better design
>   of interfaces (e.g. different methods for cases where an expensive
>   return value isn't needed)? (@jeremyevans0)

Yes, it could definitely be solved by additional method arguments (or keywo=
rd arguments).  However, that can complicate implementation or may not be p=
ossible depending on the method's API (consider a method that already accep=
ts arbitrary arguments and arbitrary keywords).

One specific use case I see for this is `Sequel::Dataset#insert` (http://se=
quel.jeremyevans.net/rdoc/classes/Sequel/Dataset.html#method-i-insert).  Th=
e return value of this method is generally the primary key value of the las=
t inserted row.  On some databases, getting that value is expensive, potent=
ially doubling the execution time of the method when using a remote databas=
e.  If the return value is not needed, the INSERT query could still be perf=
ormed, but it would not be necessary to issue another query to SELECT the r=
eturn value.

Due to `Sequel::Dataset#insert`'s flexible API, it would be hard to support=
 this as a method argument.  I could add a different method to support it, =
but then I need to add a separate internal method (more indirection, lower =
performance), or significant duplication.  Additionally, having fewer, more=
 flexible methods can result in an API that is easier to remember and use, =
compared to an API that has many more methods with less flexible behavior f=
or each (with the tradeoff that the internals become significantly more com=
plex).

One potential advantage of the VM_FRAME_FLAG_DISCARDED flag that may not ye=
t have been anticipated is not a performance advantage, but a usability adv=
antage.  Consider the following code:

```ruby
  def foo(**kw)
    kw.merge(FORCE_VALUES)
    bar(**kw)
  end
```

This code has a bug I've seen new Ruby programmers make.  The bug is that `=
Hash#merge` returns a new hash, it doesn't modify the existing hash.  This =
is almost certainly a bug, because there is no reason to call `Hash#merge` =
without using the return value.  The programmer almost certainly wanted the=
 behavior of `Hash#merge!`.  Basically, `Hash#merge` is a pure function.  W=
e could add a way to mark methods as pure functions (e.g. `Module#pure_func=
tion`), and if the method is called with VM_FRAME_FLAG_DISCARDED, Ruby coul=
d warn or raise.

While I am in favor of this, I can certainly understand the potential for a=
buse.  However, Ruby has never been a language that avoided features simply=
 because it is possible to abuse them.  That being said, I think it would m=
ake sense to make this strictly internal initially, and not expose it to C =
extensions and pure ruby code unless the internal usage demonstrates its us=
efulness.

----------------------------------------
Feature #17004: Provide a way for methods to omit their return value
https://bugs.ruby-lang.org/issues/17004#change-86398

* Author: shyouhei (Shyouhei Urabe)
* Status: Open
* Priority: Normal
----------------------------------------
In ruby, it often is the case for a method's return value to not be used by=
 its caller.  Even when a method returns something meaningful, its caller i=
s free to ignore it.

Why not provide a way for a method to know if its return value is needed or=
 not?  That adds a room for methods to be optimized, by for instance skippi=
ng creation of complex return values.

The following pull request implements `RubyVM.return_value_is_used?` method=
, which does that: https://github.com/ruby/ruby/pull/3271



-- =

https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=3Dunsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>