入門ビッグデータ---Scala関数と閉パッケージ
6174 ワード
一、関数
1.1関数と方法
Scalaでは関数とメソッドの違いは非常に小さく,関数がオブジェクトのメンバーである場合,このような関数をメソッドと呼び,そうでない場合は正常な関数である.
1.2関数タイプ
1.3一等公民&匿名関数
Scalaでは、関数は一等公民です.これは、関数を定義して呼び出すだけでなく、値として渡すこともできることを意味します.
Scalaでは、
1.4特殊な関数式
1.可変長パラメータリスト
Javaで可変長のパラメータを渡すには
2.名前付きパラメータを渡す
関数にパラメータを渡すときに、特定のパラメータ名を指定できます.
3.デフォルトパラメータ
関数を定義するときに、パラメータのデフォルト値を指定できます.
二、閉包
2.1閉パッケージの定義
上記の関数x:この関数のパラメータであるため、関数のコンテキストに明確な定義があるバインド変数です. more:フリー変数(free variable)です.関数の数値面量は、moreに意味を与えていないからです.
定義に従って:関数を作成するときに自由変数をキャプチャする必要がある場合、キャプチャされた変数への参照を含む関数を閉パッケージ関数と呼びます.
2.2自由変数の変更
ここで、閉パケットは、変数自体、すなわち変数自体への参照を取得します.これは、次のことを意味します.閉パケット外部による自由変数の修正は、閉パケット内部で可視である. 閉パケット内部の自由変数の修正は、閉パケット外部でも見られる.
2.3自由変数マルチコピー
フリー変数はプログラムの変更に伴って変更され、複数のコピーが生成される可能性がありますが、閉パッケージは作成時に有効な変数のコピーを指します.
上記の例から、再宣言
三、高次関数
3.1パラメータとして関数を使用する
関数を定義するときに入力関数をパラメータとしてサポートします.このとき、新しく定義した関数は高次関数と呼ばれます.
3.2関数コリー化
上で定義した関数は1つのパラメータリストのみをサポートし、コリー化関数は複数のパラメータリストをサポートします.コリー化とは,2つのパラメータを受け入れた関数を1つのパラメータを受け入れる関数に変える過程を指す.新しい関数は、元の2番目のパラメータをパラメータとします.
ここでcurriedSumを呼び出すと、実際には従来の関数呼び出しを2回連続して行い、実際に実行されたコリー化プロセスは以下の通りです.第1回目の呼び出しは 返される関数は、パラメータ
コリー化の中間戻り関数を得るのも簡単です.
コリー化は複数のパラメータリストをサポートし、複数のパラメータは左から右の順にコリー化操作を実行します.
参考資料 Martin Odersky . Scalaプログラミング(第3版)[M].电子工业出版社2018-1-1 ケイ.S.ホストマン速学Scala(第2版)[M].电子工业出版社2017-7
シリーズゲート
1.1関数と方法
Scalaでは関数とメソッドの違いは非常に小さく,関数がオブジェクトのメンバーである場合,このような関数をメソッドと呼び,そうでない場合は正常な関数である.
//
def multi1(x:Int) = {x * x}
//
val multi2 = (x: Int) => {x * x}
println(multi1(3)) // 9
println(multi2(3)) // 9
def
を使用して関数を定義することもできます.def multi3 = (x: Int) => {x * x}
println(multi3(3)) // 9
multi2
とmulti3
は本質的に区別されない.これは、関数が一等公民であるためである.val multi2 = (x: Int) => {x * x}
この文はdef
を用いて関数を予め定義し、その後変数multi2
に値を付与することに相当する.1.2関数タイプ
multi2
とmulti3
は本質的に同じですが、関数としてはどのようなタイプですか?どちらのタイプも実際にはInt => Int
であり、前のIntは入力パラメータタイプを表し、後のIntは戻り値タイプを表す.scala> val multi2 = (x: Int) => {x * x}
multi2: Int => Int = $$Lambda$1092/594363215@1dd1a777
scala> def multi3 = (x: Int) => {x * x}
multi3: Int => Int
// , :( , ...)=>
scala> val multi4 = (x: Int,name: String) => {name + x * x }
multi4: (Int, String) => String = $$Lambda$1093/1039732747@2eb4fe7
1.3一等公民&匿名関数
Scalaでは、関数は一等公民です.これは、関数を定義して呼び出すだけでなく、値として渡すこともできることを意味します.
import scala.math.ceil
object ScalaApp extends App {
// ceil fun, (_) ceil
val fun = ceil _
println(fun(2.3456)) // 3.0
}
Scalaでは、
(x: Int) => 3 * x
が匿名関数であるなど、各関数に名前を付ける必要はありません.object ScalaApp extends App {
// 1.
(x: Int) => 3 * x
// 2.
val fun = (x: Int) => 3 * x
// 3.
val array01 = Array(1, 2, 3).map((x: Int) => 3 * x)
// 4.
val array02 = Array(1, 2, 3).map(_ * 3)
// 5.
val array03 = Array(1, 2, 3).map(fun)
}
1.4特殊な関数式
1.可変長パラメータリスト
Javaで可変長のパラメータを渡すには
String ...args
という形式を使う必要があります.Scalaでは等価にargs: String*
と表現されています.object ScalaApp extends App {
def echo(args: String*): Unit = {
for (arg
2.名前付きパラメータを渡す
関数にパラメータを渡すときに、特定のパラメータ名を指定できます.
object ScalaApp extends App {
def detail(name: String, age: Int): Unit = println(name + ":" + age)
// 1.
detail("heibaiying", 12)
// 2. ,
detail(age = 12, name = "heibaiying")
}
3.デフォルトパラメータ
関数を定義するときに、パラメータのデフォルト値を指定できます.
object ScalaApp extends App {
def detail(name: String, age: Int = 88): Unit = println(name + ":" + age)
// age ,
detail("heibaiying")
detail("heibaiying", 12)
}
二、閉包
2.1閉パッケージの定義
var more = 10
// addMore : more
val addMore = (x: Int) => x + more
上記の関数
addMore
には、2つの変数xとmoreがあります.定義に従って:関数を作成するときに自由変数をキャプチャする必要がある場合、キャプチャされた変数への参照を含む関数を閉パッケージ関数と呼びます.
2.2自由変数の変更
ここで、閉パケットは、変数自体、すなわち変数自体への参照を取得します.これは、次のことを意味します.
// more
scala> var more = 10
more: Int = 10
// more ,
scala> val addMore = (x: Int) => {x + more}
addMore: Int => Int = $$Lambda$1076/1844473121@876c4f0
scala> addMore(10)
res7: Int = 20
// more , more
scala> more=1000
more: Int = 1000
scala> addMore(10)
res8: Int = 1010
2.3自由変数マルチコピー
フリー変数はプログラムの変更に伴って変更され、複数のコピーが生成される可能性がありますが、閉パッケージは作成時に有効な変数のコピーを指します.
// more
scala> var more = 10
more: Int = 10
//
scala> val addMore10 = (x: Int) => {x + more}
addMore10: Int => Int = $$Lambda$1077/1144251618@1bdaa13c
//
scala> addMore10(9)
res9: Int = 19
// more
scala> var more = 100
more: Int = 100
//
scala> val addMore100 = (x: Int) => {x + more}
addMore100: Int => Int = $$Lambda$1078/626955849@4d0be2ac
// more
scala> addMore100(9)
res10: Int = 109
// more
scala> addMore10(9)
res11: Int = 19
// more 100
scala> more
res12: Int = 100
上記の例から、再宣言
more
後、グローバルなmore
の値は100であるが、閉パケット関数addMore10
については、10のmore
を参照するか、仮想マシンによって実現され、仮想機会保証more
変数は、再宣言後も元の取得された変数のコピーがスタック上で生存し続けることを保証する.三、高次関数
3.1パラメータとして関数を使用する
関数を定義するときに入力関数をパラメータとしてサポートします.このとき、新しく定義した関数は高次関数と呼ばれます.
object ScalaApp extends App {
// 1.
def square = (x: Int) => {
x * x
}
// 2. : Int => Int
def multi(fun: Int => Int, x: Int) = {
fun(x) * 100
}
// 3.
println(multi(square, 5)) // 2500
// 4.
println(multi(_ * 100, 5)) // 50000
}
3.2関数コリー化
上で定義した関数は1つのパラメータリストのみをサポートし、コリー化関数は複数のパラメータリストをサポートします.コリー化とは,2つのパラメータを受け入れた関数を1つのパラメータを受け入れる関数に変える過程を指す.新しい関数は、元の2番目のパラメータをパラメータとします.
object ScalaApp extends App {
//
def curriedSum(x: Int)(y: Int) = x + y
println(curriedSum(2)(3)) // 5
}
ここでcurriedSumを呼び出すと、実際には従来の関数呼び出しを2回連続して行い、実際に実行されたコリー化プロセスは以下の通りです.
x
というInt型パラメータを受信し、第2回目の呼び出しに使用する関数を返し、x
が2であると仮定すると、関数2+y
を返す.y
を受信し、値2+3
の値を計算して返します.コリー化の中間戻り関数を得るのも簡単です.
object ScalaApp extends App {
//
def curriedSum(x: Int)(y: Int) = x + y
println(curriedSum(2)(3)) // 5
// 10 10 + y
val plus: Int => Int = curriedSum(10)_
println(plus(3)) // 13
}
コリー化は複数のパラメータリストをサポートし、複数のパラメータは左から右の順にコリー化操作を実行します.
object ScalaApp extends App {
//
def curriedSum(x: Int)(y: Int)(z: String) = x + y + z
println(curriedSum(2)(3)("name")) // 5name
}
参考資料
シリーズゲート