Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
February 11, 2021 08:54 am GMT

Understanding Ruby - Enumerable - Intro and Interfaces

Introduction

Enumerable. Debatably one of, if not the, most powerful features in Ruby. As a majority of your time in programming is dealing with collections of items it's no surprise how frequently you'll see it used.

This first article will cover implementing the interface for Enumerable.

Difficulty

Foundational

Some knowledge required of functions in Ruby. This post focuses on foundational and fundamental knowledge for Ruby programmers.

Prerequisite Reading:

Enumerable

Enumerable is an interface module that contains several methods for working with collections. Many Ruby classes implement the Enumerable interface that look like collections. Chances are if it has an each method it supports Enumerable, and because of that it's quite ubiquitous in Ruby.

So how are we going to cover such a large piece of the language? Categorically, and of course after we show how you can implement one of your own

Note: This idea was partially inspired by Lamar Burdette's recent work on Ruby documentation, but takes its own direction.

Cards in a Hand

To start with, how do we implement Enumerable ourselves? Via an each method and including the module, much like Comparable from the last post. We'll be re-exploring our Card class from that article as well as making a Hand to contain those cards.

Remembering our Card

Let's start with our Card class from last time:

class Card  include Comparable  SUITS        = %w(S H D C).freeze  RANKS        = %w(2 3 4 5 6 7 8 9 10 J Q K A).freeze  RANKS_SCORES = RANKS.each_with_index.to_h  include Comparable  attr_reader :suit, :rank  def initialize(suit, rank)    @suit = suit    @rank = rank  end  def self.from_str(s) = new(s[0], s[1..])  def to_s() = "#{@suit}#{@rank}"  def <=>(other) = precedence <=> other.precedenceend
Enter fullscreen mode Exit fullscreen mode

There's one new method here for convenience that gives us a Card from a String, letting us do this:

Card.from_str('SA')
Enter fullscreen mode Exit fullscreen mode

That gets to be handy when we want an entire hand in a second.

Creating a Hand

Now let's take a look at a Hand class that might contain these cards:

class Hand  include Enumerable  attr_reader :cards  def initialize(*cards)    @cards = cards.sort  end  def self.from_str(s) = new(*s.split(/[ ,]+/).map { Card.from_str(_1) })  def to_s() = @cards.map(&:to_s).join(', ')  def each(&fn) = @cards.each { |card| fn.call(card) }end
Enter fullscreen mode Exit fullscreen mode

Starting with Enumerable features, we define an each method at the bottom which takes a Block Function and calls it with each card from the cards in our Hand.

Next we have a utility function like Card had which allows us to make a Hand from a String, because otherwise that's a lot of typing:

royal_flush = Hand.from_str('S10, SJ, SQ, SK, SA')
Enter fullscreen mode Exit fullscreen mode

With the above Enumerable code we can now use any of the Enumerable methods against it:

royal_flush.reject { |c| c <= Card.from_str('SQ') }.join(', ')# => "SK, SA"
Enter fullscreen mode Exit fullscreen mode

Nifty! Now with that down let's take a look at all of the shiny fun things in Enumerable. We'll be using more generic examples from here on out.

In the next few articles we'll really be digging into Enumerable. This was broken up into multiple quickly published articles to make it a bit more readable, otherwise it's 30+ minutes to get through.

Note on Aliases

Ruby has many aliases, like collect is an alias for map. As I prefer map I will be using that for examples. When you see a / in the header in other sections, the first item will be the preference I will draw from, but you could use the other name to the same effect.

Note on Syntax

You might see #method_name or .method_name mentioned in Ruby on occasion. This means Instance Method and Class Method respectively. You might also see it like Enumerable#map, which means map is an Instance Method of Enumerable.

Wrapping Up

The next few articles will be getting into the various parts of Enumerable, grouped by functionality:

  1. Transforming
  2. Predicate Conditions
  3. Searching and Filtering
  4. Sorting and Comparing
  5. Counting
  6. Grouping
  7. Combining
  8. Iterating and Taking
  9. Coercion

While lazy is part of Enumerable that deserves a post all its own, and we'll be getting to that one soon too.

Want to keep up to date on what I'm writing and working on? Take a look at my new newsletter: The Lapidary Lemur


Original Link: https://dev.to/baweaver/understanding-ruby-enumerable-intro-and-interfaces-29bk

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To