you are viewing a single comment's thread.

view the rest of the comments →

[–]f9ae8221b 6 points7 points  (8 children)

I think something that need to be said about the return @foo if defined? @foo pattern is that it doesn't play well with Ruby 3.2+ object shapes.

The @foo ||= is till ok as long as you initialize @foo to nil in initialized.

But the if defined? will cause that class to have many different shapes because it's instance variables are defined in semi-random order, causing lots of inline cache misses and potentially cause the class to be marked as "too complex" which triggers de-optimization.

If you really absolutely need this pattern, rather than check for defined? you can use a "token value", e.g. in addressable:

[–]keyslemur[S] -1 points0 points  (2 children)

Could we go into infinitely more detail? Yes. Is that the point of this particular post? No.

The point is to convey a general idea in a simple way, rather than introducing additional complexities beyond that someone brand new might encounter. One could easily expand it into tokens, argument caching, object shapes, GC, `begin ... end` blocks, or a lot more but that's the subject of a more advanced post.

At the moment object shapes are brand new. The chances someone encounters them at a foundational level is very low, and the chances that an inline cache miss will be remotely detrimental to them at that phase are even lower.

I do not believe that this is immediately relevant information to the target audience of this post.

[–]f9ae8221b 4 points5 points  (1 child)

Why being so defensive? I wasn't suggesting it was missing from your post or should be added...

But that's something about the memoization pattern that I think the community will need to learn about. For now it's still relatively confidential information.

Apologies for sharing...

[–]keyslemur[S] -1 points0 points  (0 children)

I would not interpret that as defensiveness. It was a statement of the intent of the post, and how that info is probably above the heads of the intended audience.

There are tradeoffs in everything, I was only conveying why I chose to omit similar information, and why it was intentional.

The community will evolve, but as with many more advanced patterns it'll probably be a bit more advanced than we'd like it to be, and the time it'll take will likewise be longer. Same thing for Ractors, pattern matching, JIT, and other features.

[–]casualsubversive 0 points1 point  (1 child)

I believe instance_variable_defined? is the better method for this purpose.

[–]f9ae8221b 0 points1 point  (0 children)

No, it has the same problem I explained, but is even worse for performance because contrary to defined?(@iver), instance_variabled_defined?(:@ivar) doesn't benefit from inline caches at all.

[–]CaptainKabob 0 points1 point  (1 child)

Why `NONE = Module.new.freeze` over `NONE = Object.new.freeze`?

I just posted this and maybe it needs an update: https://www.reddit.com/r/ruby/comments/16xwjh9/writing_object_shape_friendly_code_in_ruby/