loading...

Simple memorization

alyson profile image aly quey ・1 min read

I know ||=, but I have to know more feature of this.

  • Simple simple
class Smile
  attr_accessor :smile

  def ensmile
    @smile = "SMILE"
  end
end
  • Use memo simply
class Smile
  attr_accessor :smile

  def ensmile
    @smile ||= "SMILE"
  end
end
  • TEST With begin 1)
class Smile
  attr_accessor :smile

  def ensmile
    @smile ||= begin
      "SMILE"
    end
  end
end
  • TEST With begin 2)
class Smile
  attr_accessor :smile

  def ensmile(cry: false)
    @smile ||= begin
      cry ? "CRY" : "SMILE"
    end
  end
end
  • TEST includes handling error
class Smile
  SmileError = Class.new(StandardError)

  attr_accessor :smile

  def ensmile(cry: false)
    @smile ||= begin
      raise SmileError if cry
      "SMILE"
    rescue SmileError
      "CRY"
    end
  end
end
  • Spec file
require 'spec_helper'
require_relative '../lib/smile'

RSpec.describe Smile do
  let(:smile) { described_class.new }
  describe '#ensmile' do
    it 'returns "SMILE"' do
      expect(smile.smile).to be_nil
      expect(smile.ensmile).to eq 'SMILE'
      expect(smile.smile).to eq 'SMILE'
    end

    it 'returns "CRY"' do
      expect(smile.smile).to be_nil
      expect(smile.ensmile(cry: true)).to eq 'CRY'
      expect(smile.smile).to eq 'CRY'
    end
  end
end

repo: https://github.com/shtakai/simple-smile

Posted on by:

alyson profile

aly quey

@alyson

Always traveling, I vomit. :cry:

Discussion

pic
Editor guide
 

(Disclaimer - I've never written Ruby, but I'm assuming || is logical or - a || b is a if a is true, otherwise b)

I believe that ||= might not work very well if you try to memoize false.

The point of memoization is that once a value is set, you don't change it:

it 'smilers never "CRY"' do
  expect(smile.smile).to be_nil
  expect(smile.ensmile).to eq 'SMILE'
  expect(smile.ensmile(cry: true)).to eq 'SMILE'
  expect(smile.smile).to eq 'SMILE'
end

it 'criers never "SMILE"' do
  expect(smile.smile).to be_nil
  expect(smile.ensmile(cry: true)).to eq 'CRY'
  expect(smile.ensmile).to eq 'CRY'
  expect(smile.smile).to eq 'CRY'
end

Consider a boolean property instead:

class Smile
  attr_accessor :smiling

  def ensmile(cry: false)
    @smiling ||= begin
      !cry
    end
  end
end

And test that criers never smile:

it 'criers never "SMILE"' do
  expect(smile.smiling).to be_nil
  expect(smile.ensmile(cry: true)).to eq false
  expect(smile.ensmile).to eq false # Failure here
  expect(smile.smiling).to eq false # And here, for the same reason
end
 
Sloan, the sloth mascot Comment marked as low quality/non-constructive by the community View code of conduct

thank you. I'll check and fix.😃