2017年11月19日 星期日

用 Ruby 實作 Elixir 的 cond statement

## Elixir:

```
defmodule Validator do
  def validate_age(age) do
    if age < 18 do
      "Under 18"
    else
      if age < 21 do
        "Under 21"
      else
        "Adult"
      end
    end
  end
end
```

變成

```
defmodule Validator do
  def validate_age(age) do
    cond do
      age < 18 -> "Under 18"
      age < 21 -> "Under 21"
      true -> "Adult"
    end
  end
end
```

## Ruby

Implement 1

```ruby
class Elixir

  def cond(&block)
    assertions = block.call()
    return assertions.compact[0]
  end

  def cassert(assertion, block)
    block.call() if assertion == true
  end

end



RSpec.describe Elixir do
  let(:elixir) { described_class.new }

  describe "cond" do
    specify do
      result = elixir.cond do
        [
          elixir.cassert(false, -> { return 1 }),
          elixir.cassert(true, -> { return 2 }),
          elixir.cassert(true, -> { return 3 })
        ]
      end

      expect(result).to eq(2)
    end
  end


  describe "cassert" do
    specify do
      result = elixir.cassert(true, -> { return 1 })

      expect(result).to eq(1)
    end

    specify do
      result = elixir.cassert(false, -> { return 1 })

      expect(result).to eq(nil)
    end
  end
end

```



Implement 2

```ruby

class Elixir
  def cond(*assertions)
    return assertions.compact.first
  end

  def cassert(assertion, block)
    return block.call() if assertion == true
  end
end



RSpec.describe Elixir do
  let(:elixir) { described_class.new }

  describe "cond" do
    specify do
      result = elixir.cond(
        elixir.cassert(false, -> { return 1 }),
        elixir.cassert(true, -> { return 2 }),
        elixir.cassert(true, -> { return 3 })
      )

      expect(result).to eq(2)
    end
  end

  describe "cassert" do
    specify do
      result = elixir.cassert(true, -> { 1 })

      expect(result).to eq(1)
    end

    specify do
      result = elixir.cassert(false, -> { 1 })

      expect(result).to eq(nil)
    end
  end
end

```


Implement 3

```ruby

class Elixir
  def cond(*assertions)
    return assertions.compact.first
  end

  def if(assertion)
    yield if block_given? && assertion == true
  end
end

RSpec.describe Elixir do
  let(:elixir) { described_class.new }

  describe "cond" do
    specify do
      result = elixir.cond(
        elixir.if(false) { 1 },
        elixir.if(true) { 2 },
        elixir.if(true) { 3 }
      )

      expect(result).to eq(2)
    end
  end

  describe "if" do
    specify do
      result = elixir.if(true) { 1 }

      expect(result).to eq(1)
    end

    specify do
      result = elixir.if(true)

      expect(result).to eq(nil)
    end

    specify do
      result = elixir.if(false) { 1 }

      expect(result).to eq(nil)
    end
  end
end
```




沒有留言:

張貼留言