Functional-programming-quick-guide
関数型プログラミング-はじめに
関数型プログラミング言語は、記号計算およびリスト処理アプリケーションを処理するために特別に設計されています。 関数型プログラミングは数学関数に基づいています。 人気のある関数型プログラミング言語には、Lisp、Python、Erlang、Haskell、Clojureなどが含まれます。
関数型プログラミング言語は、2つのグループに分類されます。 −
- 純粋な関数型言語-これらのタイプの関数型言語は、関数型パラダイムのみをサポートしています。 たとえば-ハスケル。
- Impure Functional Languages -これらのタイプの関数型言語は、関数型パラダイムと命令型プログラミングをサポートしています。 たとえば-LISP。
関数型プログラミング-特性
関数型プログラミングの最も顕著な特徴は次のとおりです-
- 関数型プログラミング言語は、条件式と再帰を使用して計算を実行する数学関数の概念に基づいて設計されています。
- 関数型プログラミングは、*高階関数*と*遅延評価*機能をサポートしています。
- 関数型プログラミング言語は、ループステートメントなどのフロー制御と、If-ElseやSwitchステートメントなどの条件ステートメントをサポートしていません。 関数と関数呼び出しを直接使用します。
- OOPと同様に、関数型プログラミング言語は、抽象化、カプセル化、継承、多態性などの一般的な概念をサポートしています。
関数型プログラミング–利点
関数型プログラミングには次の利点があります-
- バグのないコード-関数型プログラミングは*状態*をサポートしていないため、副作用の結果はなく、エラーのないコードを書くことができます。
- 効率的な並列プログラミング-関数型プログラミング言語にはミュータブル状態がないため、状態変更の問題はありません。 「命令」として並行して動作するように「機能」をプログラムできます。 このようなコードは、簡単な再利用性とテスト容易性をサポートします。
- 効率-機能プログラムは、同時に実行できる独立したユニットで構成されます。 結果として、そのようなプログラムはより効率的です。
- ネスト関数をサポート-関数型プログラミングはネスト関数をサポートします。
- 遅延評価-関数型プログラミングは、遅延リスト、遅延マップなどの遅延関数構造をサポートします。
欠点として、関数型プログラミングには大きなメモリ空間が必要です。 状態がないため、アクションを実行するたびに新しいオブジェクトを作成する必要があります。
関数型プログラミングは、同じデータセットに対して多くの異なる操作を実行する必要がある状況で使用されます。
- Lispは、機械学習、言語処理、音声と視覚のモデリングなどの人工知能アプリケーションに使用されます。
- 組み込みLispインタープリターは、Emacsなどの一部のシステムにプログラマビリティを追加します。
関数型プログラミングと オブジェクト指向プログラミング
次の表は、関数型プログラミングとオブジェクト指向プログラミングの主な違いを強調しています-
Functional Programming | OOP |
---|---|
Uses Immutable data. | Uses Mutable data. |
Follows Declarative Programming Model. | Follows Imperative Programming Model. |
Focus is on: “What you are doing” | Focus is on “How you are doing” |
Supports Parallel Programming | Not suitable for Parallel Programming |
Its functions have no-side effects | Its methods can produce serious side effects. |
Flow Control is done using function calls & function calls with recursion | Flow control is done using loops and conditional statements. |
It uses "Recursion" concept to iterate Collection Data. | It uses "Loop" concept to iterate Collection Data. For example: For-each loop in Java |
Execution order of statements is not so important. | Execution order of statements is very important. |
Supports both "Abstraction over Data" and "Abstraction over Behavior". | Supports only "Abstraction over Data". |
プログラムコードの効率
プログラミングコードの効率は、アルゴリズムの効率と実行速度に正比例します。 効率が良いと、パフォーマンスが向上します。
プログラムの効率に影響を与える要因が含まれます-
- 機械の速度
- コンパイラー速度
- オペレーティング・システム
- 適切なプログラミング言語の選択
- プログラム内のデータの方法が整理されている
- 問題を解決するために使用されるアルゴリズム
プログラミング言語の効率は、次のタスクを実行することにより改善することができます-
- 不要なコードまたは冗長処理に使用されるコードを削除します。
- 最適なメモリと不揮発性ストレージを利用することにより
- 必要に応じて再利用可能なコンポーネントを使用することにより。
- プログラムのすべての層でエラーと例外処理を使用することにより。
- データの整合性と一貫性を保証するプログラミングコードを作成する。
- 設計ロジックとフローに準拠したプログラムコードを開発する。
効率的なプログラミングコードは、リソースの消費と完了時間を可能な限り削減し、オペレーティング環境へのリスクを最小限に抑えます。
機能の概要
プログラミング用語では、*関数*は特定のタスクを実行するステートメントのブロックです。 関数はデータを受け入れて処理し、結果を返します。 関数は、主に再利用性の概念をサポートするために書かれています。 関数を作成すると、同じコードを何度も作成することなく、簡単に呼び出すことができます。
異なる関数型言語は、異なる構文を使用して関数を記述します。
関数を書くための前提条件
関数を書く前に、プログラマは次の点を知っている必要があります-
- 機能の目的はプログラマーに知られている必要があります。
- 関数のアルゴリズムはプログラマーに知られている必要があります。
- 関数データ変数とその目標は、プログラマーに知られている必要があります。
- 関数のデータは、ユーザーが呼び出すプログラマーに知られている必要があります。
関数のフロー制御
機能が「呼び出される」と、プログラムは機能を実行するために制御を「転送」し、その「制御の流れ」は以下のようになります-
- プログラムは、「関数呼び出し」を含むステートメントに到達します。
- 関数内の最初の行が実行されます。
- 関数内のすべてのステートメントは、上から下に実行されます。
- 関数が正常に実行されると、制御は開始元のステートメントに戻ります。
- 関数によって計算されて返されたデータは、元のコード行の関数の代わりに使用されます。
関数の構文
関数の一般的な構文は次のように見えます-
C ++での関数の定義
オブジェクト指向プログラミング言語であるC ++で関数を定義する方法を理解するための例を見てみましょう。 次のコードには、2つの数値を追加し、その結果を出力として提供する関数があります。
それは次の出力を生成します-
Erlangで関数を定義する
関数型プログラミング言語であるErlangで同じ関数を定義する方法を見てみましょう。
それは次の出力を生成します-
関数プロトタイプ
関数プロトタイプは、return-type、function-name、arguments-listを含む関数の宣言です。 これは、関数本体のない関数定義に似ています。
例-一部のプログラミング言語は関数プロトタイプをサポートしていますが、一部はサポートしていません。
C ++では、このような関数「sum」の関数プロトタイプを作成できます-
注-Python、Erlangなどのプログラミング言語は関数プロトタイプをサポートしていません。関数全体を宣言する必要があります。
関数プロトタイプの使用とは何ですか?
関数のプロトタイプは、関数が呼び出されるときにコンパイラーによって使用されます。 コンパイラはこれを使用して、正しい戻り型、適切な引数リストが渡されること、およびその戻り型が正しいことを確認します。
関数シグネチャ
関数シグニチャは、パラメータの数、パラメータのデータ型、および外観の順序が同じ順序である関数プロトタイプに似ています。 例-
Function1とFunction2には異なるシグネチャがあります。 Function2とFunction3には同じシグネチャがあります。
注-後続の章で説明する関数のオーバーロードと関数のオーバーライドは、関数シグネチャの概念に基づいています。
- クラスに同じ名前で異なるシグネチャを持つ複数の関数がある場合、関数のオーバーロードが可能です。
- 派生クラス関数がその基本クラスと同じ名前とシグネチャを持つ場合、関数のオーバーライドが可能です。
関数型プログラミング-関数型
機能は2種類あります-
- 定義済みの関数
- ユーザー定義関数
この章では、関数について詳しく説明します。
定義済みの関数
これらは、操作を実行するために言語に組み込まれ、標準機能ライブラリに保存される機能です。
例-C の「Strcat」とHaskellの「concat」を使用して2つの文字列を追加し、C の「strlen」とPythonの「len」を使用して文字列の長さを計算します。
C ++で文字列の長さを出力するプログラム
次のプログラムは、C ++を使用して文字列の長さを印刷する方法を示しています-
それは次の出力を生成します-
Pythonで文字列の長さを出力するプログラム
次のプログラムは、関数型プログラミング言語であるPythonを使用して文字列の長さを印刷する方法を示しています-
それは次の出力を生成します-
ユーザー定義関数
ユーザー定義関数は、特定のタスクを実行するためにユーザーによって定義されます。 関数を定義する4つの異なるパターンがあります-
- 引数も戻り値もない関数
- 引数なしで戻り値を持つ関数
- 引数はあるが戻り値はない関数
- 引数と戻り値を持つ関数
引数も戻り値もない関数
次のプログラムは、 C ++ で引数と戻り値のない関数を定義する方法を示しています-
それは次の出力を生成します-
次のプログラムは、 Python で同様の関数(引数と戻り値なし)を定義する方法を示しています-
それは次の出力を生成します-
引数なしで戻り値を持つ関数
次のプログラムは、 C ++ で引数なしで戻り値を持つ関数を定義する方法を示しています-
それは次の出力を生成します-
次のプログラムは、 Python で同様の関数(引数なしで戻り値)を定義する方法を示しています-
それは次の出力を生成します-
引数はあるが戻り値はない関数
次のプログラムは、引数を使用して C ++ に戻り値を持たない関数を定義する方法を示しています-
それは次の出力を生成します-
次のプログラムは、 Python で同様の関数を定義する方法を示しています-
それは次の出力を生成します-
引数と戻り値を持つ関数
次のプログラムは、引数なしで戻り値を持つC ++で関数を定義する方法を示しています-
それは次の出力を生成します-
次のプログラムは、 Python で同様の関数(引数と戻り値付き)を定義する方法を示しています-
それは次の出力を生成します-
関数型プログラミング-値で呼び出す
関数を定義したら、目的の出力を得るために引数を渡す必要があります。 ほとんどのプログラミング言語は、関数に引数を渡すための*値による呼び出し*および*参照による呼び出し*メソッドをサポートしています。
この章では、C ++などのオブジェクト指向プログラミング言語およびPythonなどの関数型プログラミング言語での「値による呼び出し」の動作を学習します。
値による呼び出し方法では、元の値は変更できません。 引数を関数に渡すと、関数は引数としてスタックメモリにローカルに保存されます。 したがって、値は関数内でのみ変更され、関数外では効果がありません。
C ++での値による呼び出し
次のプログラムは、C ++でCall by Valueがどのように機能するかを示しています-
それは次の出力を生成します-
Pythonでの値による呼び出し
次のプログラムは、Pythonで値による呼び出しがどのように機能するかを示しています-
それは次の出力を生成します-
関数型プログラミング-参照による呼び出し
参照による呼び出しでは、引数の参照アドレスを渡すため、元の値が変更されます。 実際の引数と形式的な引数は同じアドレス空間を共有するため、関数内の値の変更は、関数の内部だけでなく外部にも反映されます。
C ++の参照による呼び出し
次のプログラムは、C ++でCall by Valueがどのように機能するかを示しています-
それは次の出力を生成します-
Pythonの参照による呼び出し
それは次の出力を生成します-
関数のオーバーロード
同じ名前で異なるパラメーターを持つ複数の関数がある場合、それらはオーバーロードされていると言われます。 この手法は、プログラムの可読性を高めるために使用されます。
関数をオーバーロードするには2つの方法があります。 −
- 引数の数が異なる
- 異なる引数タイプを持つ
関数のオーバーロードは、通常、異なる数または種類の引数を使用して1つの操作を実行する必要がある場合に行われます。
C ++での関数のオーバーロード
次の例は、オブジェクト指向プログラミング言語であるC ++で関数のオーバーロードが行われる方法を示しています-
それは次の出力を生成します-
Erlangでの関数のオーバーロード
次の例は、関数型プログラミング言語であるErlangで関数のオーバーロードを実行する方法を示しています-
それは次の出力を生成します-
関数のオーバーライド
基本クラスと派生クラスに、まったく同じ名前、同じ戻り値型、同じ引数リストを持つメンバー関数がある場合、それは関数オーバーライドと呼ばれます。
C ++を使用した関数のオーバーライド
次の例は、オブジェクト指向プログラミング言語であるC ++で関数のオーバーライドが行われる方法を示しています-
次の出力が生成されます
Pythonを使用した関数のオーバーライド
次の例は、関数型プログラミング言語であるPythonで関数のオーバーライドを実行する方法を示しています-
それは次の出力を生成します-
関数型プログラミング-再帰
自分自身を呼び出す関数は再帰関数と呼ばれ、この手法は再帰と呼ばれます。 再帰命令は、別の命令がそれを妨げるまで継続します。
C ++の再帰
次の例は、オブジェクト指向プログラミング言語であるC ++での再帰の動作を示しています-
次の出力が生成されます
Pythonの再帰
次の例は、関数型プログラミング言語であるPythonで再帰がどのように機能するかを示しています-
それは次の出力を生成します-
高階関数
高次関数(HOF)は、次の条件の少なくとも1つに従う関数です-
- 引数として1つ以上の関数を取ります
- 結果として関数を返します
PHPのHOF
次の例は、オブジェクト指向プログラミング言語であるPHPで高階関数を書く方法を示しています-
それは次の出力を生成します-
PythonのHOF
次の例は、オブジェクト指向プログラミング言語であるPythonで高階関数を書く方法を示しています-
それは次の出力を生成します-
関数型プログラミング-データ型
データ型は、オブジェクトが持つことができる値の型と、そのオブジェクトに対して実行できる操作を定義します。 データ型は、使用する前に最初に宣言する必要があります。 さまざまなプログラミング言語がさまざまなデータ型をサポートしています。 例えば、
- Cは、char、int、float、longなどをサポートしています。
- Pythonは、String、List、Tupleなどをサポートしています。
広義には、3つのタイプのデータタイプがあります-
- 基本的なデータ型-これらは事前定義されたデータ型であり、プログラマーが要件ごとに1つの値のみを保存するために直接使用します。つまり、整数型、文字型、または浮動型です。 例えば-int、char、floatなど。
- 派生データ型-これらのデータ型は、プログラマーが要件に応じて同じ型の複数の値を保存するように設計された組み込みデータ型を使用して導出されます。 例-配列、ポインター、関数、リストなど。
- ユーザー定義のデータ型-これらのデータ型は、単一のデータ型にラップされ、要件に応じて同じ型または異なる型、またはその両方の複数の値を格納する組み込みデータ型を使用して導出されます。 例-クラス、構造など
C ++でサポートされるデータ型
次の表は、C ++でサポートされるデータ型の一覧です-
Data Type | Size | Range |
---|---|---|
char | 1 byte | -128 to 127 or 0 to 255 |
unsigned char | 1 byte | 0 to 255 |
signed char | 1 byte | -128 to 127 |
int | 4 bytes | -2147483648 to 2147483647 |
unsigned int | 4 bytes | 0 to 4294967295 |
signed int | 4 bytes | -2147483648 to 2147483647 |
short int | 2 bytes | -32768 to 32767 |
unsigned short int | 2 bytes | 0 to 65,535 |
signed short int | 2 bytes | -32768 to 32767 |
long int | 4 bytes | -2,147,483,648 to 2,147,483,647 |
signed long int | 4 bytes | -2,147,483,648 to 2,147,483,647 |
unsigned long int | 4 bytes | 0 to 4,294,967,295 |
float | 4 bytes | +/- 3.4e +/- 38 (~7 digits) |
double | 8 bytes | +/- 1.7e +/- 308 (~15 digits) |
long double | 8 bytes | +/- 1.7e +/- 308 (~15 digits) |
Javaでサポートされるデータ型
次のデータ型はJavaでサポートされています-
Data Type | Size | Range |
---|---|---|
byte | 1 byte | -128 to 127 |
char | 2 byte | 0 to 65,536 |
short | 2 byte | -32,7688 to 32,767 |
int | 4 byte | -2,147,483,648 to 2,147,483,647 |
long | 8 byte | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
float | 4 byte | -2147483648 to 2147483647 |
double | 8 byte | +9.223*1018 |
Boolean | 1 bit | True or False |
Erlangがサポートするデータ型
このセクションでは、関数型プログラミング言語であるErlangでサポートされているデータ型について説明します。
数
Erlangは2種類の数値リテラルをサポートしています。 整数*および*浮動小数点数。 2つの整数値を追加する方法を示す次の例を見てください-
それは次の出力を生成します-
Atom
それは次の出力を生成します-
注意-大文字の「M」で原子を「月曜日」に変更してみてください。 プログラムはエラーを生成します。
ブール値
このデータ型は、結果を true または false として表示するために使用されます。 次の例を見てください。 2つの整数を比較する方法を示します。
それは次の出力を生成します-
ビット列
型指定されていないメモリの領域を格納するには、ビット文字列が使用されます。 次の例を見てください。 ビット文字列の2ビットをリストに変換する方法を示します。
それは次の出力を生成します-
タプル
タプルは、固定数の用語を持つ複合データ型です。 タプルの各用語は、*要素*と呼ばれます。 要素の数は、タプルのサイズです。 次の例は、5つの用語のタプルを定義し、そのサイズを出力する方法を示しています。
それは次の出力を生成します-
Map
マップは、可変数のキーと値の関連付けを持つ複合データ型です。 マップ内の各キーと値の関連付けは、関連付けペア*と呼ばれます。 ペアの *key および value 部分は elements と呼ばれます。 アソシエーションペアの数は、マップのサイズと言われています。 次の例は、3つのマッピングのマップを定義し、そのサイズを出力する方法を示しています。
それは次の出力を生成します-
List
リストは、可変数の用語を持つ複合データ型です。 リスト内の各用語は要素と呼ばれます。 要素の数は、リストの長さと言われます。 次の例は、5つのアイテムのリストを定義し、そのサイズを印刷する方法を示しています。
それは次の出力を生成します-
注意-'String’データ型はErlangでは定義されていません。
関数型プログラミング-多態性
プログラミングの観点では、ポリモーフィズムとは、単一のコードを複数回再利用することを意味します。 より具体的には、データ型またはクラスに応じてオブジェクトを異なる方法で処理するプログラムの機能です。
多型は2つのタイプです-
- コンパイル時ポリモーフィズム-このタイプのポリモーフィズムは、メソッドのオーバーロードを使用して実現できます。
- 実行時ポリモーフィズム-このタイプのポリモーフィズムは、メソッドのオーバーライドと仮想関数を使用して実現できます。
多型の利点
多態性には、次の利点があります-
- プログラマーがコードを再利用するのに役立ちます。つまり、一度作成、テスト、実装されたクラスは必要に応じて再利用できます。 多くの時間を節約します。
- 単一の変数を使用して、複数のデータ型を格納できます。 *コードのデバッグが簡単。
多態的なデータ型
ポリモーフィックデータ型は、バイトアドレスのみを格納するジェネリックポインターを使用して実装でき、そのメモリアドレスに格納されるデータのタイプはありません。 例えば、
ここで、 p および q は、 int、float (またはその他の)値を引数として保持できる汎用ポインターです。
C ++の多態性関数
次のプログラムは、オブジェクト指向プログラミング言語であるC ++で多態性関数を使用する方法を示しています。
それは次の出力を生成します-
Pythonの多態性関数
次のプログラムは、関数型プログラミング言語であるPythonでポリモーフィック関数を使用する方法を示しています。
それは次の出力を生成します-
関数型プログラミング-文字列
次の画像は、文字列「チュートリアル」がメモリ内でどのように表示されるかを示しています。
C ++で文字列を作成する
次のプログラムは、オブジェクト指向プログラミング言語であるC ++で文字列を作成する方法を示す例です。
それは次の出力を生成します-
アーランの文字列
次のプログラムは、関数型プログラミング言語であるErlangで文字列を作成する方法を示す例です。
それは次の出力を生成します-
C ++での文字列操作
異なるプログラミング言語は、文字列の異なるメソッドをサポートします。 次の表は、C ++でサポートされるいくつかの定義済みの文字列メソッドを示しています。
S.No. | Method & Description |
---|---|
1 |
Strcpy(s1,s2) 文字列s2を文字列s1にコピーします |
2 |
Strcat(s1,s2) s1の末尾に文字列s2を追加します |
3 |
Strlen(s1) 文字列s1の長さを提供します |
4 |
Strcmp(s1,s2) 文字列s1とs2が同じ場合は0を返します |
5 |
Strchr(s1,ch) 文字列s1で文字chが最初に現れる場所へのポインタを返します |
6 |
Strstr(s1,s2) 文字列s1で文字列s2が最初に現れる場所へのポインタを返します |
次のプログラムは、上記のメソッドをC ++で使用する方法を示しています-
それは次の出力を生成します-
Erlangの文字列操作
次の表は、Erlangでサポートされている事前定義された文字列メソッドのリストを示しています。
S.No. | Method & Description |
---|---|
1 |
len(s1) 指定された文字列の文字数を返します。 |
2 |
equal(s1,s2) 文字列s1とs2が等しい場合はtrueを返し、そうでない場合はfalseを返します |
3 |
concat(s1,s2) 文字列s1の最後に文字列s2を追加します |
4 |
str(s1,ch) 文字列s1の文字chのインデックス位置を返します |
5 |
str (s1,s2) 文字列s1のs2のインデックス位置を返します |
6 |
substr(s1,s2,num) このメソッドは、開始位置と開始位置からの文字数に基づいて、文字列s1から文字列s2を返します |
7 |
to_lower(s1) このメソッドは文字列を小文字で返します |
次のプログラムは、上記のメソッドをErlangで使用する方法を示しています。
それは次の出力を生成します-
関数型プログラミング-リスト
Javaで数字のリストを作成するプログラム
リストはJava/C/C ++のデータ型ではありませんが、Javaでリストを作成する別の方法、つまり ArrayList および LinkedList を使用する方法があります。
次の例は、Javaでリストを作成する方法を示しています。 ここでは、リンクリストメソッドを使用して、数値のリストを作成しています。
それは次の出力を生成します-
Erlangで数字のリストを作成するプログラム
それは次の出力を生成します-
Javaでのリスト操作
このセクションでは、Javaのリストに対して実行できるいくつかの操作について説明します。
リストに要素を追加する
メソッドadd(Object)、add(index、Object)、addAll()は、リストに要素を追加するために使用されます。 例えば、
リストから要素を削除する
メソッドremove(index)またはremoveobject()は、リストから要素を削除するために使用されます。 例えば、
注-リストからすべての要素を削除するには、clear()メソッドを使用します。
リストから要素を取得する
get()メソッドは、指定された場所にあるリストから要素を取得するために使用されます。 getfirst()およびgetlast()メソッドはLinkedListクラスで使用できます。 例えば、
リスト内の要素を更新する
set(index、element)メソッドは、指定された要素で指定されたインデックスの要素を更新するために使用されます。 例えば、
リスト内の要素の並べ替え
collection.sort()およびcollection.reverse()メソッドは、リストを昇順または降順でソートするために使用されます。 例えば、
リスト内の要素を検索する
次の3つの方法は、要件に従って使用されます-
- Boolean contains(Object)メソッドは、リストに指定された要素が含まれている場合は *true を返し、それ以外の場合は false を返します。
- int indexOf(Object)*メソッドは、リスト内の指定された要素の最初の出現のインデックスを返します。そうでない場合、要素が見つからない場合は-1を返します。
- int lastIndexOf(Object)*は、リスト内の指定された要素の最後の出現のインデックスを返します。そうでない場合、要素が見つからない場合は-1を返します。
Erlangのリスト操作
このセクションでは、Erlangのリストに対して実行できるいくつかの操作について説明します。
2つのリストを追加する
append(listfirst、listsecond)メソッドは、2つのリストを追加して新しいリストを作成するために使用されます。 例えば、
要素を削除する
delete(element、listname)メソッドは、リストから指定された要素を削除するために使用され、新しいリストを返します。 例えば、
リストから最後の要素を削除する
droplast(listname)メソッドは、リストから最後の要素を削除して新しいリストを返すために使用されます。 例えば、
要素を検索する
member(element、listname)メソッドは、リスト内の要素を検索するために使用され、見つかった場合はtrueを返し、見つからない場合はfalseを返します。 例えば、
最大値と最小値の取得
max(listname)およびmin(listname)メソッドは、リスト内の最大値と最小値を見つけるために使用されます。 例えば、
リスト要素の並べ替え
メソッドsort(listname)およびreverse(listname)は、リストを昇順または降順でソートするために使用されます。 例えば、
リスト要素を追加する
sum(listname)メソッドは、リストのすべての要素を追加し、それらの合計を返すために使用されます。 例えば、
Javaを使用してリストを昇順および降順に並べ替えます
次のプログラムは、Javaを使用してリストを昇順および降順にソートする方法を示しています-
それは次の出力を生成します-
Erlangを使用してリストを昇順で並べ替える
次のプログラムは、関数型プログラミング言語であるErlangを使用してリストを昇順および降順にソートする方法を示しています-
それは次の出力を生成します-
関数型プログラミング-タプル
タプルは、固定数の用語を持つ複合データ型です。 タプル内の各用語は、*要素*と呼ばれます。 要素の数は、タプルのサイズです。
C#でタプルを定義するプログラム
次のプログラムは、4つの用語のタプルを定義し、オブジェクト指向プログラミング言語であるC#を使用して印刷する方法を示しています。
それは次の出力を生成します-
Erlangでタプルを定義するプログラム
次のプログラムは、4つの用語のタプルを定義し、関数型プログラミング言語であるErlangを使用して印刷する方法を示しています。
それは次の出力を生成します-
タプルの利点
タプルには次の利点があります-
- タプルは、自然に細かくサイズ設定されています。 タプルに要素を追加したり、タプルから要素を削除することはできません。
- タプル内の任意の要素を検索できます。
- タプルは値のセットが一定であるため、リストよりも高速です。 *タプルは、文字列、数値などの不変の値を含むため、辞書キーとして使用できます。
タプルとリスト
Tuple | List |
---|---|
Tuples are* immutable*, i.e., we can’t update its data. | List are mutable, i.e., we can update its data. |
Elements in a tuple can be different type. | All elements in a list is of same type. |
Tuples are denoted by round parenthesis around the elements. | Lists are denoted by square brackets around the elements. |
タプルの操作
このセクションでは、タプルで実行できるいくつかの操作について説明します。
挿入された値がタプルかどうかを確認します
メソッド* is_tuple(tuplevalues)は、挿入された値がタプルかどうかを判断するために使用されます。 挿入された値がタプルの場合は *true を返し、それ以外の場合は false を返します。 例えば、
それは次の出力を生成します-
リストをタプルに変換する
メソッド* list_to_tuple(listvalues)*は、リストをタプルに変換します。 例えば、
それは次の出力を生成します-
タプルをリストに変換する
メソッド* tuple_to_list(tuplevalues)*は、指定されたタプルをリスト形式に変換します。 例えば、
それは次の出力を生成します-
タプルサイズを確認する
メソッド* tuple_size(tuplename)*は、タプルのサイズを返します。 例えば、
それは次の出力を生成します-
関数型プログラミング-レコード
レコードは、固定数の要素を格納するためのデータ構造です。 C言語の構造に似ています。 コンパイル時に、その式はタプル式に変換されます。
レコードを作成するには?
キーワード「レコード」は、レコード名とそのフィールドで指定されたレコードを作成するために使用されます。 その構文は次のとおりです-
レコードに値を挿入する構文は次のとおりです-
Erlangを使用してレコードを作成するプログラム
次の例では、2つのフィールド( sname と sid )を持つ名前 student のレコードを作成しました。
C ++を使用してレコードを作成するプログラム
次の例は、オブジェクト指向プログラミング言語であるC ++を使用してレコードを作成する方法を示しています-
Erlangを使用してレコード値にアクセスするプログラム
次のプログラムは、関数型プログラミング言語であるErlangを使用してレコード値にアクセスする方法を示しています-
それは次の出力を生成します-
C ++を使用してレコード値にアクセスするプログラム
次のプログラムは、C ++を使用してレコード値にアクセスする方法を示しています-
それは次の出力を生成します-
レコード値を更新するには、値を特定のフィールドに変更し、そのレコードを新しい変数名に割り当てます。 次の2つの例を見て、オブジェクト指向および関数型プログラミング言語を使用してどのように行われるかを理解してください。
Erlangを使用してレコード値を更新するプログラム
次のプログラムは、Erlangを使用してレコード値を更新する方法を示しています-
それは次の出力を生成します-
C ++を使用してレコード値を更新するプログラム
次のプログラムは、C ++を使用してレコード値を更新する方法を示しています-
それは次の出力を生成します-
関数型プログラミング-ラムダ計算
ラムダ計算は、関数を使用した計算を研究するために1930年代にアロンゾ教会によって開発されたフレームワークです。
- 関数の作成-教会は、「x」が正式な引数であり、「E」が関数体である関数を示す表記*λx.E*を導入しました。 これらの関数は、名前と単一の引数なしで作成できます。
- 関数アプリケーション-教会は* E〜1〜.E〜2〜という表記を使用して、実際の引数 E〜2〜への関数 E〜1〜*の適用を示しました。 そして、すべての関数は単一の引数に基づいています。
ラムダ計算の構文
Lamdba Calculusには、3種類の式が含まれます。
- E
- = x(変数)
| E1 E2(function application)
| λx.E(function creation)
ここで、*λx.E*はLambda抽象化と呼ばれ、Eはλ式と呼ばれます。
ラムダ計算の評価
純粋なラムダ計算には組み込み関数はありません。 私たちは次の式を評価しましょう-
ここでは、数字のみで動作するため、「+」から始めることはできません。 (* 5 6)と(* 8 3)の2つの縮小可能な式があります。
最初にどちらかを減らすことができます。 たとえば-
β還元ルール
λsを処理する削減ルールが必要です
これはβ還元と呼ばれます。
正式なパラメータは数回使用される場合があります-
複数の用語がある場合、次のように処理できます-
内側の x は内側の*λ*に属し、外側のxは外側のものに属します。
自由変数およびバインド変数
式では、変数の各出現は「自由」(λ)または「結合」(λ)のいずれかです。
(λxのβ還元 E) yは、 E で発生するすべての x を y に置き換えます。 例-
アルファ削減
アルファ削減は非常に簡単で、ラムダ式の意味を変更せずに実行できます。
たとえば-
チャーチ・ロッサーの定理
チャーチ・ロッサーの定理は次のことを述べています-
- E1↔E2の場合、E1→EおよびE2→EというEが存在します。 「何らかの方法で削減しても、最終的には同じ結果になる可能性があります。」
- E1→E2であり、E2が正規形の場合、E1からE2への正規順序の減少があります。 「通常の次数の削減は、存在する場合、常に標準形を生成します。」
関数型プログラミング-遅延評価
遅延評価は、値が必要になるまで式の評価を保持する評価戦略です。 評価の繰り返しを避けます。 Haskell は、基本が遅延評価に基づいている関数型プログラミング言語の良い例です。
遅延評価はUnixマップ関数で使用され、必要なページのみをディスクからロードすることでパフォーマンスを改善します。 残りのページにはメモリは割り当てられません。
遅延評価-利点
- 言語ランタイムは、式の最終結果に直接リンクされていない部分式を破棄できます。
- 一時的な計算と条件を破棄することにより、アルゴリズムの時間の複雑さを軽減します。
- プログラマーは、循環依存関係がない限り、データ構造のコンポーネントを初期化後に順不同でアクセスできます。
- アクセス頻度の低いデータのロードに最適です。
遅延評価-欠点
- thunks (遅延オブジェクト)を作成することにより、最終結果で必要になるまで、言語ランタイムに部分式の評価を保持させます。
- 場合によっては、アルゴリズムのスペースの複雑さが増します。
- 実行前に大量の式が含まれているため、パフォーマンスを見つけるのは非常に困難です。
Pythonを使用した遅延評価
Pythonの range メソッドは、遅延評価の概念に従います。 より大きな範囲の実行時間を節約し、一度にすべての値を必要とすることはないため、メモリ消費も節約します。 次の例を見てください。
それは次の出力を生成します-
ファイルI/O操作
プログラムの終了時にプログラムの出力を保存するファイルが必要です。 ファイルを使用すると、異なる言語のさまざまなコマンドを使用して関連情報にアクセスできます。
これは、ファイルで実行できるいくつかの操作のリストです-
- 新しいファイルを作成する
- 既存のファイルを開く
- ファイルの内容を読む
- ファイルのデータを検索する
- 新しいファイルへの書き込み
- コンテンツを既存のファイルに更新する
- ファイルを削除する
- ファイルを閉じる
ファイルへの書き込み
コンテンツをファイルに書き込むには、まず必要なファイルを開く必要があります。 指定したファイルが存在しない場合、新しいファイルが作成されます。
C ++を使用してファイルにコンテンツを書き込む方法を見てみましょう。
例
注-
- fstream は、ファイルの読み取り/書き込み操作を制御するために使用されるストリームクラスです。
- ofstream は、コンテンツをファイルに書き込むために使用されるストリームクラスです。
関数型プログラミング言語であるErlangを使用して、ファイルにコンテンツを書き込む方法を見てみましょう。
注-
- ファイルを開くには、* open(filename、mode)*を使用する必要があります。
- 内容をファイルに書き込む構文:* write(filemode、file_content)*。
出力-このコードを実行すると、「ファイルへのコンテンツの書き込み」がファイル Tempfile.txt に書き込まれます。 ファイルに既存のコンテンツがある場合は、上書きされます。
ファイルからの読み取り
ファイルから読み取るには、まず指定されたファイルを*読み取りモード*で開く必要があります。 ファイルが存在しない場合、それぞれのメソッドはNULLを返します。
次のプログラムは、 C ++ でファイルの内容を読み取る方法を示しています-
それは次の出力を生成します-
- 注-このプログラムでは、「ios
- in」を使用して読み取りモードでテキストファイルを開き、その内容を画面に印刷します。 「getline」メソッドを使用して、 while ループを使用して、ファイルの内容を1行ずつ読み取りました。
次のプログラムは、 Erlang を使用して同じ操作を実行する方法を示しています。 ここでは、* read_file(filename)*メソッドを使用して、指定されたファイルからすべてのコンテンツを読み取ります。
それは次の出力を生成します-
既存のファイルを削除する
ファイル操作を使用して既存のファイルを削除できます。 次のプログラムは、C ++を使用して既存のファイルを削除する方法を示しています*
それは次の出力を生成します-
次のプログラムは、 Erlang で同じ操作を実行する方法を示しています。 ここでは、メソッド* delete(filename)*を使用して既存のファイルを削除します。
出力-ファイル「Tempfile.txt」が存在する場合、削除されます。
ファイルのサイズを決定する
次のプログラムは、C ++を使用してファイルのサイズを決定する方法を示しています。 ここで、関数 fseek は、ストリームに関連付けられた位置インジケータを新しい位置に設定しますが、 ftell はストリーム内の現在の位置を返します。
出力-ファイル「Tempfile.txt」が存在する場合、そのサイズがバイト単位で表示されます。
次のプログラムは、Erlangで同じ操作を実行する方法を示しています。 ここでは、メソッド* file_size(filename)*を使用してファイルのサイズを決定します。
出力-ファイル「Tempfile.txt」が存在する場合、そのサイズがバイト単位で表示されます。 それ以外の場合、「0」が表示されます。