socialgekon.com
  • メイン
  • 革新
  • 設計プロセス
  • リモートの台頭
  • 財務プロセス
バックエンド

可能性の配列:Rubyパターンマッチングのガイド

パターンマッチングは、Ruby2.7に登場する大きな新機能です。トランクにコミットされているので、興味のある人は誰でもインストールできます Ruby 2.7.0-dev そしてそれをチェックしてください。これらはいずれも確定しておらず、開発チームはフィードバックを求めているため、フィードバックがある場合は、機能が実際にリリースされる前にコミッターに知らせることができます。

この記事を読んだ後、パターンマッチングとは何か、Rubyでの使用方法を理解していただければ幸いです。

パターンマッチングとは何ですか?

パターンマッチングは、関数型プログラミング言語で一般的に見られる機能です。による ドキュメントの規模 、パターンマッチングは 「パターンに対して値をチェックするためのメカニズム。一致が成功すると、値を構成要素に分解することもできます。」



これを正規表現、文字列照合、またはパターン認識と混同しないでください。パターンマッチングは文字列とは関係ありませんが、データ構造とは関係ありません。パターンマッチングに初めて遭遇したのは、2年ほど前に試したときでした。 エリクサー 。私はElixirを学び、それを使ってアルゴリズムを解こうとしていました。私は自分のソリューションを他のソリューションと比較し、パターンマッチングを使用していることに気付きました。これにより、コードがはるかに簡潔で読みやすくなりました。

そのため、パターンマッチングは本当に印象的でした。 Elixirのパターンマッチングは次のようになります。

[a, b, c] = [:hello, 'world', 42] a #=> :hello b #=> 'world' c #=> 42

上記の例は、 複数の割り当て Rubyで。しかし、それだけではありません。また、値が一致するかどうかもチェックします。

[a, b, 42] = [:hello, 'world', 42] a #=> :hello b #=> 'world'

上記の例では、左側の番号42は割り当てられている変数ではありません。その特定のインデックスの同じ要素が右側の要素と一致することを確認する値です。

[a, b, 88] = [:hello, 'world', 42] ** (MatchError) no match of right hand side value

この例では、値が割り当てられる代わりに、MatchError代わりに発生します。これは、88番が42番と一致しないためです。

また、マップ(Rubyのハッシュに似ています)でも機能します。

%{'name': 'Zote', 'title': title } = %{'name': 'Zote', 'title': 'The mighty'} title #=> The mighty

上記の例では、キーの値がnameであることを確認しています。はZoteであり、キーの値をバインドしますtitle変数のタイトルに。

この概念は、データ構造が複雑な場合に非常にうまく機能します。変数を割り当てて、値またはタイプをすべて1行で確認できます。

さらに、Elixirのような動的に型付けされた言語でメソッドのオーバーロードを行うこともできます。

def process(%{'animal' => animal}) do IO.puts('The animal is: #{animal}') end def process(%{'plant' => plant}) do IO.puts('The plant is: #{plant}') end def process(%{'person' => person}) do IO.puts('The person is: #{person}') end

引数のハッシュのキーに応じて、さまざまなメソッドが実行されます。

うまくいけば、それはパターンマッチングがいかに強力であるかを示しています。次のようなgemを使用してパターンマッチングをRubyに組み込む試みは数多くあります。 ノアイデ 、 何 、および egison-ruby 。

Ruby 2.7にも、これらのgemとそれほど変わらない独自の実装があり、これが現在行われている方法です。

Rubyパターンマッチング構文

Rubyでのパターンマッチングは、caseを介して行われます。ステートメント。ただし、通常のwhenを使用する代わりに、キーワードin代わりに使用されます。 ifの使用もサポートしますまたはunlessステートメント:

case [variable or expression] in [pattern] ... in [pattern] if [expression] ... else ... end

Caseステートメントは変数または式を受け入れることができ、これはで提供されるパターンと照合されます。 に 句。 場合 または そうでなければ パターンの後にステートメントを指定することもできます。ここでの等価性チェックでも===を使用します通常のcaseステートメントのように。これは、クラスのサブセットとインスタンスを照合できることを意味します。使用方法の例を次に示します。

一致する配列

translation = ['th', 'เต้', 'ja', 'テイ'] case translation in ['th', orig_text, 'en', trans_text] puts 'English translation: #{orig_text} => #{trans_text}' in ['th', orig_text, 'ja', trans_text] # this will get executed puts 'Japanese translation: #{orig_text} => #{trans_text}' end

上記の例では、変数translation 2つのパターンと照合されます。

['th', orig_text, 'en', trans_text]および['th', orig_text, 'ja', trans_text]。パターンの値がtranslationの値と一致するかどうかを確認します。各インデックスの変数。値が一致する場合は、translationの値を割り当てます。各インデックスのパターン内の変数への変数。

Rubyパターンマッチングアニメーション:配列のマッチング

マッチングハッシュ

translation = {orig_lang: 'th', trans_lang: 'en', orig_txt: 'เต้', trans_txt: 'tae' } case translation in {orig_lang: 'th', trans_lang: 'en', orig_txt: orig_txt, trans_txt: trans_txt} puts '#{orig_txt} => #{trans_txt}' end

上記の例では、translation変数がハッシュになりました。 in内の別のハッシュと照合されます句。何が起こるかというと、caseステートメントは、パターン内のすべてのキーがtranslation内のキーと一致するかどうかをチェックします。変数。また、各キーのすべての値が一致することも確認します。次に、ハッシュ内の変数に値を割り当てます。

Rubyパターンマッチングアニメーション:配列のマッチング

一致するサブセット

パターンマッチングで使用される品質チェックは、===のロジックに従います。

複数のパターン

  • | 1つのブロックに複数のパターンを定義するために使用できます。
translation = ['th', 'เต้', 'ja', 'テイ'] case array in {orig_lang: 'th', trans_lang: 'ja', orig_txt: orig_txt, trans_txt: trans_txt} | ['th', orig_text, 'ja', trans_text] puts orig_text #=> เต้ puts trans_text #=> テイ end

上記の例では、translation変数は両方の{orig_lang: 'th', trans_lang: 'ja', orig_txt: orig_txt, trans_txt: trans_txt}と一致しますハッシュと['th', orig_text, 'ja', trans_text]アレイ。

これは、同じものを表すわずかに異なるタイプのデータ構造があり、両方のデータ構造で同じコードブロックを実行する場合に役立ちます。

矢印の割り当て

この場合、=>一致した値を変数に割り当てるために使用できます。

case ['I am a string', 10] in [Integer, Integer] => a # not reached in [String, Integer] => b puts b #=> ['I am a string', 10] end

これは、データ構造内の値をチェックするだけでなく、これらの値を変数にバインドする場合に役立ちます。

ピン演算子

ここで、ピン演算子は変数が再割り当てされるのを防ぎます。

case [1,2,2] in [a,a,a] puts a #=> 2 end

上記の例では、パターン内の変数aが1、2、2の順に照合されます。1、2、2の順に割り当てられます。これは、すべての変数を確認する場合は理想的な状況ではありません。配列の値は同じです。

case [1,2,2] in [a,^a,^a] # not reached in [a,b,^b] puts a #=> 1 puts b #=> 2 end

ピン演算子を使用すると、変数を再割り当てするのではなく、変数を評価します。上記の例では、最初のインデックスではaが1に割り当てられているため、[1,2,2]は[a、^ a、^ a]と一致しません。2番目と3番目では、aは1と評価されます。しかし、2と一致します。

ただし、[a、b、^ b]は[1,2,2]と一致します。これは、aが最初のインデックスで1に割り当てられ、bが2番目のインデックスで2に割り当てられ、次に^ b(現在は2)が照合されるためです。 3番目のインデックスの2なので、合格します。

a = 1 case [2,2] in [^a,^a] #=> not reached in [b,^b] puts b #=> 2 end

上記の例に示すように、caseステートメントの外部からの変数も使用できます。

アンダースコア(_)演算子

アンダースコア(_)は、値を無視するために使用されます。いくつかの例でそれを見てみましょう:

case ['this will be ignored',2] in [_,a] puts a #=> 2 end case ['a',2] in [_,a] => b puts a #=> 2 Puts b #=> ['a',2] end

上記の2つの例では、_と一致する値パスします。 2番目のcaseステートメントでは、=>演算子は、無視された値もキャプチャします。

Rubyでのパターンマッチングのユースケース

次のJSONデータがあるとします。

{ nickName: 'Tae' realName: {firstName: 'Noppakun', lastName: 'Wongsrinoppakun'} username: 'tae8838' }

Rubyプロジェクトで、このデータを解析し、次の条件で名前を表示する必要があります。

  1. ユーザー名が存在する場合は、ユーザー名を返します。
  2. ニックネーム、名、および姓が存在する場合は、ニックネーム、名、および姓を返します。
  3. ニックネームが存在しないが、名前と名前が存在する場合は、名前を返し、次に名前を返します。
  4. いずれの条件も当てはまらない場合は、「新規ユーザー」を返送してください。

これが私が今Rubyでこのプログラムを書く方法です:

def display_name(name_hash) if name_hash[:username] name_hash[:username] elsif name_hash[:nickname] && name_hash[:realname] && name_hash[:realname][:first] && name_hash[:realname][:last] '#{name_hash[:nickname]} #{name_hash[:realname][:first]} #{name_hash[:realname][:last]}' elsif name_hash[:first] && name_hash[:last] '#{name_hash[:first]} #{name_hash[:last]}' else 'New User' end end

それでは、パターンマッチングでどのように見えるかを見てみましょう。

def display_name(name_hash) case name_hash in {username: username} username in {nickname: nickname, realname: {first: first, last: last}} '#{nickname} #{first} #{last}' in {first: first, last: last} '#{first} #{last}' else 'New User' end end

構文の好みは少し主観的かもしれませんが、私はパターンマッチングバージョンを好みます。これは、パターンマッチングにより、ハッシュの値を記述してチェックする代わりに、期待するハッシュを書き出すことができるためです。これにより、予想されるデータを簡単に視覚化できます。

`{nickname: nickname, realname: {first: first, last: last}}`

の代わりに:

`name_hash[:nickname] && name_hash[:realname] && name_hash[:realname][:first] && name_hash[:realname][:last]`.

DeconstructとDeconstruct_keys

Ruby2.7で導入された2つの新しい特別なメソッドがあります:deconstructおよびdeconstruct_keys。クラスのインスタンスが配列またはハッシュと照合されている場合、deconstructまたはdeconstruct_keysそれぞれと呼ばれます。

これらのメソッドの結果は、パターンとの照合に使用されます。次に例を示します。

class Coordinate attr_accessor :x, :y def initialize(x, y) @x = x @y = y end def deconstruct [@x, @y] end def deconstruct_key {x: @x, y: @y} end end

このコードは、Coordinateというクラスを定義しています。属性としてxとyがあります。 deconstructもありますおよびdeconstruct_keys定義されたメソッド。

c = Coordinates.new(32,50) case c in [a,b] p a #=> 32 p b #=> 50 end

ここでは、Coordinateのインスタンスが定義され、配列に対してパターンが照合されています。ここで何が起こるかというとCoordinate#deconstructが呼び出され、その結果を使用して配列と照合します[a,b]パターンで定義されています。

case c in {x:, y:} p x #=> 32 p y #=> 50 end

この例では、Coordinateの同じインスタンスハッシュに対してパターンマッチングされています。この場合、Coordinate#deconstruct_keys結果はハッシュとの照合に使用されます{x: x, y: y}パターンで定義されています。

エキサイティングな実験的特徴

Elixirで最初にパターンマッチングを経験したとき、この機能にはメソッドのオーバーロードが含まれ、1行しか必要としない構文で実装される可能性があると思いました。ただし、Rubyはパターンマッチングを念頭に置いて構築された言語ではないため、これは理解できます。

caseステートメントを使用することは、おそらくこれを実装するための非常に無駄のない方法であり、既存のコードにも影響しません(deconstructおよびdeconstruct_keysメソッドを除く)。 caseステートメントの使用法は、実際にはScalaのパターンマッチングの実装と似ています。

個人的には、パターンマッチングはエキサイティングな新機能だと思います Ruby開発者 。コードをよりクリーンにし、Rubyをもう少しモダンでエキサイティングなものにする可能性があります。人々がこれをどうやって作っているのか、そしてこの機能が将来どのように進化するのかを見てみたいです。

基本を理解する

関数型プログラミングのパターンマッチングとは何ですか?

Scalaのドキュメントによると、パターンマッチングは「パターンに対して値をチェックするためのメカニズムです。一致が成功すると、値を構成要素に分解することもできます。」

パターンマッチングが役立つのはなぜですか?

コードをよりクリーンにし、Rubyをもう少しモダンでエキサイティングなものにする可能性があります。

パターンマッチングはどのように機能しますか?

Ruby2.7のswitchcaseステートメントを使用して、通常の「when」の代わりに「in」というキーワードを使用します。

パターンマッチングとはどういう意味ですか?

Scalaのドキュメントによると、パターンマッチングは「パターンに対して値をチェックするためのメカニズムです。一致が成功すると、値を構成要素に分解することもできます。」

ツリーカーネル:ツリー構造化データ間の類似性の定量化

データサイエンスとデータベース

ツリーカーネル:ツリー構造化データ間の類似性の定量化
アジャイルドキュメント:スピードと知識保持のバランス

アジャイルドキュメント:スピードと知識保持のバランス

アジャイル

人気の投稿
PHPおよびMySQLでのUTF-8エンコーディングのガイド
PHPおよびMySQLでのUTF-8エンコーディングのガイド
ApeeScapeのトップ無料プログラミング本のリスト
ApeeScapeのトップ無料プログラミング本のリスト
ボタンレスUIデザインの未来
ボタンレスUIデザインの未来
コウノトリ、パート4:ステートメントの実装とまとめ
コウノトリ、パート4:ステートメントの実装とまとめ
iPhoneで本格的なライフスタイル写真を撮影する方法
iPhoneで本格的なライフスタイル写真を撮影する方法
 
Instagramでより多くのいいねを獲得する10の本物の方法
Instagramでより多くのいいねを獲得する10の本物の方法
ARMサーバー:データセンター向けのモバイルCPUアーキテクチャ?
ARMサーバー:データセンター向けのモバイルCPUアーキテクチャ?
あなたの本当に、フリーランスのデザインアドバイス
あなたの本当に、フリーランスのデザインアドバイス
iPhoneで鮮明な商品写真を撮影する方法
iPhoneで鮮明な商品写真を撮影する方法
UI Trends 2020:何が入っていますか?
UI Trends 2020:何が入っていますか?
カテゴリー
財務プロセスリモートの台頭転記ヒントとツールバックエンド革新プロジェクト管理仕事の未来設計プロセス製品ライフサイクル

© 2023 | 全著作権所有

socialgekon.com