Issue #15881 has been updated by marcandre (Marc-Andre Lafortune).


mame (Yusuke Endoh) wrote:
> I talked with ktsj, the author of pattern matching.  He had actually considered caching the result of deconstruct, but we found it difficult because of some reasons.
> 
> * If destructive operation is applied to the object being matched (this is possible in a guard expression), the behavior of pattern matching would get messed up.

Is there a valid use case for this though? Seems more like an anti-pattern that is better not being supported at all.

> * ktsj investigated Scala's pattern match, and it calls `unapply` method each time without caching.

Interesting. Do we know if there a is good reason for that? Scala is in general faster than Ruby, so it might not matter as much there...

> * We believe `Array#deconstruct` and `Hash#deconstruct_keys` would be most often called.  They just return the receiver itself, so no object is generated.  So, caching is useless in the typical case.

Well, unless I'm mistaken, it would not be completely useless as it would avoid `send(:respond_to?, :deconstruct_keys)` and `send(:deconstruct_keys)`, but the main issue really is for user defined classes.

> * If you need to cache the result of your own `deconstruct` definition, it is not so difficult to manually memoize the result.

I disagree. You can't simply use `@cache ||= ...`, you need to invalidate `@cache` if any dependency of the `...` changes. That may be quite tricky. Let's remember:

    There are only two hard things in Computer Science: cache invalidation and naming things.

    -- Phil Karlton

I remain convinced that it would be better to cache this result.


----------------------------------------
Feature #15881: Optimize deconstruct in pattern matching
https://bugs.ruby-lang.org/issues/15881#change-78485

* Author: marcandre (Marc-Andre Lafortune)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 2.7
----------------------------------------
```ruby
class A
  def deconstruct
    puts 'deconstruct called'
    [1]
  end
end

case A.new
in [2]
  2
in [1]
  1
else
end

# => 1, prints "deconstruct called"
```

Shouldn't `deconstruct called` print only once, whenever the first deconstruction needed occurs?



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

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