🐷

[Feature #20786] then キーワードを使って処理をチェーンしたいという提案

2024/10/08に公開

[Feature #20786] Flow chaining with "then" keyword

  • then キーワードを使って処理をチェーンしたいという提案
  • どういうことかというと以下のようなコードに対して
def include?(other)
  other = coerce_other(other)
  return false unless other.family == family
  begin_addr <= other.begin_addr && end_addr >= other.end_addr
end
  • 以下のように then キーワードで処理結果を取得し、それに対してチェーンしていくらしい
def include?(other)
  begin
    coerce_other(other)
  then => coerced  # then => name で値を取得する
    return false unless coerced.family == family
    coerced
  then => it
    begin_addr <= it.begin_addr && end_addr >= it.end_addr
  end
end
  • 更に begin を省略したり it を使った例も書かれています
def include?(other)
  coerce_other(other)
then 
  it.family == family ? it : false
then
  begin_addr <= it.begin_addr && end_addr >= it.end_addr
end
  • 構文としては以下みたいなイメージみたいです
    • begin ~ end の中で then を使って処理を分割する
    • then の直前の式の結果が真であれば次の then が呼び出されて式の結果が渡される
    • begin ~ end の結果は最後の式の結果が返ってくる
  • パッと見、 #then でチェーンすればいいんじゃない?と思ったけど偽の場合はスキップしたいので全く同じにはかけないのかな?
def include?(other)
  coerce_other(other)
    .then { |coerced|
      coerced.family == family ? coerced : false
    }
    # 上の then の戻り値が false の場合は then を呼んでほしくない
    .then { |it|
      begin_addr <= it.begin_addr && end_addr >= it.end_addr
    }
end
  • 個人的にはよくわからん構文に見えるので普通に『偽のときはブロックは呼ばれない』 #then メソッドとか定義するといいんじゃないかなー
module Kernel
  def chain(...) = self.then(...)
end

class NilClass
  def chain(...) = self
end

class FalseClass
  def chain(...) = self
end

# これはブロックが呼ばれる
pp 42.chain { _1 + _1 }

# これはブロックが呼ばれず、レシーバを返す
pp nil.chain { 42 }
pp false.chain { 42 }

def include?(other)
  coerce_other(other)
    .chain { |coerced|
      coerced.family == family ? coerced : false
    }
    # 上の chain が false を返した場合でもブロックが呼ばれない
    .chain { |it|
      begin_addr <= it.begin_addr && end_addr >= it.end_addr
    }
end
  • 個人的には新しい構文を追加するよりもこっちのほうがわかりやすいと思う
GitHubで編集を提案

Discussion