# frozen_string_literal: true RSpec.describe Fear::PartialFunction, "#or_else" do subject(:first_or_else_second) { first.or_else(second) } let(:first) { Fear.case(->(x) { x.even? }) { |x| "first: #{x}" } } let(:second) { Fear.case(->(x) { x % 3 == 0 }) { |x| "second: #{x}" } } describe "#defined_at?" do context "first defined, second not" do subject { first_or_else_second.defined_at?(4) } it { is_expected.to eq(true) } end context "first not defined, second defined" do subject { first_or_else_second.defined_at?(9) } it { is_expected.to eq(true) } end context "first not defined, second not defined" do subject { first_or_else_second.defined_at?(5) } it { is_expected.to eq(false) } end context "first and second defined" do subject { first_or_else_second.defined_at?(6) } it { is_expected.to eq(true) } end end describe "#call" do context "first defined, second not" do subject { first_or_else_second.(4) } it { is_expected.to eq("first: 4") } end context "first not defined, second defined" do subject { first_or_else_second.(9) } it { is_expected.to eq("second: 9") } end context "first not defined, second not defined" do subject { -> { first_or_else_second.(5) } } it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 5") } end context "first and second defined" do subject { first_or_else_second.(6) } it { is_expected.to eq("first: 6") } end end describe "#call_or_else" do let(:fallback) { ->(x) { "fallback: #{x}" } } context "first defined, second not" do subject { first_or_else_second.call_or_else(4, &fallback) } it { is_expected.to eq("first: 4") } end context "first not defined, second defined" do subject { first_or_else_second.call_or_else(9, &fallback) } it { is_expected.to eq("second: 9") } end context "first not defined, second not defined" do subject { first_or_else_second.call_or_else(5, &fallback) } it { is_expected.to eq("fallback: 5") } end context "first and second defined" do subject { first_or_else_second.call_or_else(6, &fallback) } it { is_expected.to eq("first: 6") } end end describe "#or_else" do let(:first_or_else_second_or_else_third) { first_or_else_second.or_else(third) } let(:third) { Fear.case(->(x) { x % 7 == 0 }) { |x| "third: #{x}" } } describe "#defined_at?" do context "first defined, second not" do subject { first_or_else_second_or_else_third.defined_at?(4) } it { is_expected.to eq(true) } end context "first not defined, second defined" do subject { first_or_else_second_or_else_third.defined_at?(9) } it { is_expected.to eq(true) } end context "first not defined, second not defined, third defined" do subject { first_or_else_second_or_else_third.defined_at?(7) } it { is_expected.to eq(true) } end context "first not defined, second not defined, third not defined" do subject { first_or_else_second_or_else_third.defined_at?(1) } it { is_expected.to eq(false) } end context "first, second and third defined" do subject { first_or_else_second.defined_at?(42) } it { is_expected.to eq(true) } end end describe "#call" do context "first defined, second not" do subject { first_or_else_second_or_else_third.(4) } it { is_expected.to eq("first: 4") } end context "first not defined, second defined" do subject { first_or_else_second_or_else_third.(9) } it { is_expected.to eq("second: 9") } end context "first not defined, second not defined, third defined" do subject { first_or_else_second_or_else_third.(7) } it { is_expected.to eq("third: 7") } end context "first not defined, second not defined, third not defined" do subject { -> { first_or_else_second_or_else_third.(1) } } it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 1") } end context "first, second and third defined" do subject { first_or_else_second.(42) } it { is_expected.to eq("first: 42") } end end describe "#call_or_else" do let(:fallback) { ->(x) { "fallback: #{x}" } } context "first defined, second not" do subject { first_or_else_second_or_else_third.call_or_else(4, &fallback) } it { is_expected.to eq("first: 4") } end context "first not defined, second defined" do subject { first_or_else_second_or_else_third.call_or_else(9, &fallback) } it { is_expected.to eq("second: 9") } end context "first not defined, second not defined, third defined" do subject { first_or_else_second_or_else_third.call_or_else(7, &fallback) } it { is_expected.to eq("third: 7") } end context "first not defined, second not defined, third not defined" do subject { first_or_else_second_or_else_third.call_or_else(1, &fallback) } it { is_expected.to eq("fallback: 1") } end context "first, second and third defined" do subject { first_or_else_second_or_else_third.call_or_else(42, &fallback) } it { is_expected.to eq("first: 42") } end end end describe "#and_then" do let(:first_or_else_second_and_then_function) { first_or_else_second.and_then(&function) } let(:function) { ->(x) { "f: #{x}" } } describe "#defined_at?" do context "first defined, second not" do subject { first_or_else_second_and_then_function.defined_at?(2) } it { is_expected.to eq(true) } end context "first not defined, second defined" do subject { first_or_else_second_and_then_function.defined_at?(3) } it { is_expected.to eq(true) } end context "first not defined, second not defined" do subject { first_or_else_second_and_then_function.defined_at?(5) } it { is_expected.to eq(false) } end context "first defined, second defined" do subject { first_or_else_second_and_then_function.defined_at?(6) } it { is_expected.to eq(true) } end end describe "#call" do context "first defined, second not" do subject { first_or_else_second_and_then_function.(2) } it { is_expected.to eq("f: first: 2") } end context "first not defined, second defined" do subject { first_or_else_second_and_then_function.(3) } it { is_expected.to eq("f: second: 3") } end context "first not defined, second not defined" do subject { -> { first_or_else_second_and_then_function.(5) } } it { is_expected.to raise_error(Fear::MatchError, "partial function not defined at: 5") } end context "first defined, second defined" do subject { first_or_else_second_and_then_function.(6) } it { is_expected.to eq("f: first: 6") } end end describe "#call_or_else" do let(:fallback) { ->(x) { "fallback: #{x}" } } context "first defined, second not" do subject { first_or_else_second_and_then_function.call_or_else(2, &fallback) } it { is_expected.to eq("f: first: 2") } end context "first not defined, second defined" do subject { first_or_else_second_and_then_function.call_or_else(3, &fallback) } it { is_expected.to eq("f: second: 3") } end context "first not defined, second not defined" do subject { first_or_else_second_and_then_function.call_or_else(5, &fallback) } it { is_expected.to eq("fallback: 5") } end context "first defined, second defined" do subject { first_or_else_second_and_then_function.call_or_else(6, &fallback) } it { is_expected.to eq("f: first: 6") } end end end end