Home > Back-end >  How does `in` works in Ruby?
How does `in` works in Ruby?

Time:07-29

I could not find usage about in here https://docs.ruby-lang.org/en/master/index.html, but it seems to be supported.

h = {a: 1}
:a in h # => true

2 in 1..3 # => true

How does it work? Is there any special method I can override like == or [] ?

CodePudding user response:

Please see here:

https://docs.ruby-lang.org/en/master/syntax/pattern_matching_rdoc.html

<expression> in <pattern> is the same as case <expression>; in <pattern>; true; else false; end

So :a in h is the same as

case :a
in h
  true
else
  false
end

You can use it when you only want to know if a pattern has been matched or not

CodePudding user response:

I think Ruby 3.0's in is what you are looking for.

See also https://rubyreferences.github.io/rubychanges/3.0.html#in-as-a-truefalse-check. It says:

in was reintroduced to return true/false (whether the pattern matches) instead of raising NoMatchingPatternError.

in is a keyword, so you cannot override it like a method.

CodePudding user response:

I could not find usage about in here https://docs.ruby-lang.org/en/master/index.html, but it seems to be supported.

All keywords are documented in the doc/keywords.rdoc document, where you can find this entry for the in keyword:

Used to separate the iterable object and iterator variable in a for loop. See control expressions syntax It also serves as a pattern in a case expression. See pattern matching

Since the example in your code is clearly not a for loop, it must therefore be Pattern Matching.

Ruby's Pattern Matching feature is documented in the Pattern Matching Syntax documentation doc/syntax/pattern_matching.rdoc:

Or with the => operator and the in operator, which can be used in a standalone expression:

<expression> => <pattern>

<expression> in <pattern>

[…]

<expression> in <pattern> is the same as case <expression>; in <pattern>; true; else false; end. You can use it when you only want to know if a pattern has been matched or not:

users = [{name: "Alice", age: 12}, {name: "Bob", age: 23}]
users.any? {|user| user in {name: /B/, age: 20..} } #=> true

How does it work?

A high-level overview about Pattern Matching can be found in the above-mentioned documentation.

However, as always, for the details, you need to check the various bits and pieces that make up the Ruby Language Specification (which, unfortunately, does not exist as a single document in a single place).

Unlike many other programming languages, Ruby does not have a single formal specification that defines what certain language constructs mean.

There are several resources, the sum of which can be considered kind of a specification for the Ruby programming language.

Some of these resources are:

  • The ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification – Note that the ISO Ruby Specification was written around 2009–2010 with the specific goal that all existing Ruby implementations at the time would easily be compliant. Since YARV only implements Ruby 1.9 and MRI only implements Ruby 1.8 and lower, this means that the ISO Ruby Specification only contains features that are common to both Ruby 1.8 and Ruby 1.9. Also, the ISO Ruby Specification was specifically intended to be minimal and only contain the features that are absolutely required for writing Ruby programs. Because of that, it does for example only specify Strings very broadly (since they have changed significantly between Ruby 1.8 and Ruby 1.9). It obviously also does not specify features which were added after the ISO Ruby Specification was written, such as Ractors or Pattern Matching.
  • The Ruby Spec Suite aka ruby/spec – Note that the ruby/spec is unfortunately far from complete. However, I quite like it because it is written in Ruby instead of "ISO-standardese", which is much easier to read for a Rubyist, and it doubles as an executable conformance test suite.
  • The Ruby Programming Language by David Flanagan and Yukihiro 'matz' Matsumoto – This book was written by David Flanagan together with Ruby's creator matz to serve as a Language Reference for Ruby.
  • Programming Ruby by Dave Thomas, Andy Hunt, and Chad Fowler – This book was the first English book about Ruby and served as the standard introduction and description of Ruby for a long time. This book also first documented the Ruby core library and standard library, and the authors donated that documentation back to the community.
  • The Ruby Issue Tracking System, specifically, the Feature sub-tracker – However, please note that unfortunately, the community is really, really bad at distinguishing between Tickets about the Ruby Programming Language and Tickets about the YARV Ruby Implementation: they both get intermingled in the tracker.
  • The Meeting Logs of the Ruby Developer Meetings.
  • New features are often discussed on the mailing lists, in particular the ruby-core (English) and ruby-dev (Japanese) mailing lists.
  • The Ruby documentation – Again, be aware that this documentation is generated from the source code of YARV and does not distinguish between features of Ruby and features of YARV.
  • In the past, there were a couple of attempts of formalizing changes to the Ruby Specification, such as the Ruby Change Request (RCR) and Ruby Enhancement Proposal (REP) processes, both of which were unsuccessful.
  • If all else fails, you need to check the source code of the popular Ruby implementations to see what they actually do.

Unfortunately, in this particular case, most of those resources are useless: the ISO Ruby Language Specification only specifies features that are common between Ruby 1.8 and 1.9 and hasn't updated since 2010. Since Pattern Matching is a feature of Ruby 3.x, it is not described there. Also, the book by Flanagan and matz and the Programming Ruby book are too old to contain documentation about Pattern Matching.

The Ruby Spec Suite does have a quite extensive specification of Pattern Matching: language/pattern_matching_spec.rb, but the one thing it does not specify is the one-line form of the in operator.

There are some references in the Feature tracker:

There is also some discussion in the Meeting Notes of the 20201026Japan Developer Meeting and the corresponding ticket.

Is there any special method I can override like == or [] ?

  • For Value Patterns, the method used is ===.
  • For Array Patterns and Find Patterns, the method used is deconstruct.
  • For Hash Patterns, the method used is deconstruct_keys.
  • Related