Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyでの関数型プログラミング(完全ガイド)

関数型プログラミングについて聞いたばかりで、いくつか質問があるかもしれません。

いいね…

  • 関数型プログラミングとは正確には何ですか?
  • オブジェクト指向プログラミングと比較してどうですか?
  • Rubyで関数型プログラミングを使用する必要がありますか?

これらの質問に答えて、これがどのように機能するかをよりよく理解できるようにします。

関数型プログラミングとは

これは単なる流行や派手な言葉ではなく、長い間存在していた実際のプログラミングパラダイムですが、最近人気を取り戻しています。

そして、このパラダイムの背後にある基本的な考え方は、あなたが思っているよりも理解しやすいです。

関数型プログラミングでは、状態の変更を避けます &私たちは「純粋な」関数を書こうとします 。

状態の変更を回避するということは、これらの関数が関数の外部で何も変更せず、インスタンス変数も、渡されたオブジェクトも変更しないことを意味します…

そのどれも!

関数型プログラミング言語(Haskellなど)では、すべてのデータは不変です。

変数のようなものもありますが、それらは数学の世界のように振る舞います。変数に値が指定されると、コンパイラはこの変数を別の値で再定義することを許可しません。

Rubyでの関数型プログラミング(完全ガイド)

関数型プログラミングの利点

可変データは追跡が難しい微妙なエラーにつながる可能性があるため、不変性は関数型プログラミングの主な利点です。

def all_different_from_first?(arr)
  first = arr.shift

  arr.all? { |n| n != first }
end

arr = [1,3,5,7,9]

p all_different_from_first?(arr)
# true

この例では、配列内のすべての要素が最初の要素と異なるかどうかを調べたいと思います。

これを機能させるには、配列から最初の要素を削除すると同時に、この要素を保存して、残りの要素と比較できるようにする必要があります。

どうすればそれができますか?

私たちは配列を扱っています。利用可能なメソッドのリストを見ると、Array#shiftメソッドがまさに私たちが望んでいることを実行していることがわかります。

までは問題なく動作します

arrの値を確認します メソッドを1回呼び出した後:

all_different_from_first?(arr)
# true

arr
# [3,5,7,9]

サプライズ!

配列は1つの要素を失いました(1 )&気づかなかった。

これが、この種の可変性のバグがいかに卑劣であるかです。

修正バージョン

def all_different_from_first?(arr)
  arr[1..-1].all? { |n| n != arr.first }
end

機能vsOOP

関数型プログラミングを採用するだけでいいですか?

このすべての不変の状態により、関数型プログラミングはOOPとは正反対のように見えるかもしれませんが、ある意味ではそうですが、2つのプログラミングパラダイムが連携できる方法はまだあります。 。

ですから、急いで関数型プログラミングを本格的に行う必要はありません。 RubyはとにかくOOP用に設計されているので、穀物と戦うことになります。

朗報

関数型プログラミングの最良のアイデアを引き続き使用して、Rubyコードに適用することができます。

その方法について話しましょう。

可変性を可能な限り減らす

これを行う1つの方法は、attr_accessorの使用を停止することです。 、attr_readerのみに固執する 。

その後、文字列、配列、ハッシュを監視する必要があります。

これらのオブジェクトを変更するメソッドがあります:

  • !で終わるほとんどのメソッド (gsub!のように )
  • 削除
  • 更新
  • クリア
  • シフト/シフト解除/ポップ/プッシュ

最初のステップは、これらの方法を認識することです。

これらのメソッドのいずれかを使用する必要がある場合は、重複するオブジェクトで作業できます。

文字列とその文字列のクローンを指定

str = "abcd"
dup = str.dup

clearすると、これらの結果が得られます 複製された文字列:

dup.clear

# str => "abcd"
# dup => ""

これにより、元の文字列が安全に保たれます。

部分適用

関数型プログラミングには、不変のデータと純粋関数以上のものがあります。

関数の部分適用のように、「カリー化」とも呼ばれます。

def add(a,b)
  a + b
end

add_five = method(:add).curry[5]

add_five.call(5)
# 10

add_five.call(20)
# 25

addの方法に注目してください メソッドは2つの引数を取りますが、curryを使用します メソッドは、引数の1つを「プリロード」できます。

次に、2番目の引数だけで呼び出すことができるラムダを取得します。

別の例です

list = (1..10)

greater_than = ->(x,y) { y > x }.curry

list.select(&greater_than.(5))
# [6, 7, 8, 9, 10]

list.select(&greater_than.(8))
# [9, 10]

もう1つの例

divisible_by = ->(x,y) { y % x == 0 }.curry

list.select(&divisible_by.(5))
# [5, 10]

list.select(&divisible_by.(2))
# [2, 4, 6, 8, 10]

概要

関数型プログラミングについて学びました。その核となるのは純粋関数と不変データです。これはコードについて考えるための方法であり、OOPと完全に互換性があるわけではありません。

読んでいただきありがとうございます。まだお済みでない場合は、ニュースレターを購読することを忘れないでください。 🙂


  1. Rubyネットワークプログラミング

    Rubyでカスタムネットワーククライアントとサーバーを作成しますか?または、それがどのように機能するかを理解しますか? 次に、ソケットを処理する必要があります。 このルビーネットワークプログラミングのツアーに参加してください 基本を学び、Rubyを使用して他のサーバーやクライアントと会話を始めましょう! では、ソケットとは何ですか ? ソケットは通信チャネルのエンドポイントであり、クライアントとサーバーの両方がソケットを使用して通信します。 動作方法は非常にシンプルです : 接続が確立されると、データをソケットに入れることができます。データはもう一方の端に送られ、そこで受信者はソケ

  2. 完全ガイド:Fitbit Pay

    Fitbit は、利用可能な最高のスマート ウェアラブルの 1 つです。多くのモデルがあり、多くの機能を備えています。 Fitbit の有名な機能の 1 つに Fitbit Pay があります。 Fitbit Ionic と Fitbit Versa の近距離無線通信チップを使用すると、非接触型決済を利用できるあらゆる店舗で支払うことができます。 この投稿では、Fitbit Pay の使用方法を理解するのに役立つ完全なガイドを掲載しています。 Fitbit Pay とは? Fitbit Pay は、Fitbit Ionic および Versa にデビット カードまたはクレジット カードを追