[ruby-core:121199] [Ruby master Feature#20202] Memoized endless method definitions
From:
"systho (Philippe Van Eerdenbrugghe) via ruby-core" <ruby-core@...>
Date:
2025-02-27 15:26:50 UTC
List:
ruby-core #121199
Issue #20202 has been updated by systho (Philippe Van Eerdenbrugghe).
(I'm not a frequent user of this board, I hope it is okay to comment on a closed ticket)
I believe there is a significant use case for this feature idea because it reveals something about the intention in a more terser way, and therefore less noisy.
Memoization is a frequent enough intention and the most frequent pattern for implementing it is `@current_method_name ||= compute_value `
This pattern is frequently not usable because of 2 reasons :
- A) The computation does not hold in a one-liner
- B) The result is a boolean (or anything that can be evaluated to false by || operator)
Case A does not really interest us here since endless methods are mostly about one-liners.
Case B is usually solved by using a different pattern :
```
def my_method
return @my_method if defined?(@my_method)
@my_method = compute_boolean_value
end
```
which turns case B into a multiliner and therefore prevents it being written as an endless method.
This is even worse with most style guidelines forcing a blank line after an early return statement, which is also quite frequent.
An additional issue happens when working in teams that will force the usage of `defined?(@ivar)` as the only valid way to do memoizing in order to maximize consistency within the team.
Because of these reasons, the memoization *intention* gets lost in noisy boilerplate and I believe this feature idea (or anything that would allow marking the memoization intention at the signature level) has a valid use case.
The two other bullet points about the method set are beyond my understanding so I cannot propose an argument.
There is an issue which has not been mentioned though : memoization is rather easy for method without arguments called on immutable objects.
But it becomes much more complex when those criteria are not met.
I do not know how realistic it would be to implement this feature in a way that would gracefully fail when some conditions are not met.
----------------------------------------
Feature #20202: Memoized endless method definitions
https://bugs.ruby-lang.org/issues/20202#change-112135
* Author: matheusrich (Matheus Richard)
* Status: Rejected
----------------------------------------
I propose introducing a shorthand for memoized endless method definitions:
```rb
class Foo
def bar ||= :memoized_value
# It should behave like
def bar = (@bar ||= :memoized_value)
end
```
Not only is this shorter and (IMO) a natural follow-up for endless method definitions, but it's also a common pattern on Ruby codebases. It's very useful to decompose responsibilities into several objects:
```rb
class User
def notifications_enabled? = settings.notifications?
def enable_notifications = (settings.notifications = true)
def disable_notifications = (settings.notifications = false)
private
def settings = @settings ||= Settings.new(self)
end
class User::Settings
attr_writer :notifications
def initialize(user)
@user = user
@notifications = false
end
def notifications? = @notifications
end
u = User.new
u.notifications_enabled? # => false
u.enable_notifications
u.notifications_enabled? # => true
```
In the example, the `settings` method could be rewritten as
```rb
def settings ||= Settings.new(self)
```
--
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/lists/ruby-core.ml.ruby-lang.org/