scala010_関数プログラミング構文

7784 ワード

引用する
scalaの関数はjavaには全くない概念です.Javaは完全にオブジェクト向けのプログラミング言語であり、プロセス向けのプログラミング言語の特性がないため、javaの一等公民はクラスとオブジェクトであり、メソッドの概念だけであり、クラスとオブジェクトのメソッドに格納され、依存している.JAvaのメソッドは、クラスとオブジェクトが独立して存在することは絶対に不可能です.scalaはオブジェクト向けであり、プロセス向けの言語です.従ってscalaには非常に良いオブジェクト向けの特性があり,scalaを用いてオブジェクト向けの思想に基づいて大規模で複雑なシステムとエンジニアリングを開発することができ,scalaもプロセス向けであるため,scalaには関数の概念がある.scalaでは,関数はクラス,オブジェクトなどと同様に一等公民である.scalaの関数は独立して存在し、クラスやオブジェクトに依存する必要はありません.scalaの関数式プログラミングは,scalaがプロセスに向かう最良の証拠である.関数式プログラミングだからこそscalaはjavaにはないより強力な機能と特性を備えている.
1変数に関数を割り当てる
2匿名関数
3高次関数
4高次関数のタイプ推定
5 scalaの一般的な高次関数
6閉パッケージ
7 SAM変換
8 Currying関数
9 return
1、関数を変数に割り当てる
scalaの関数は一等公民であり,独立して定義でき,独立して存在し,直接関数を値として変数に割り当てることができる.scalaの構文では、関数を変数に割り当てる場合、関数の後にスペースと下線を付ける必要があります.
scala> def sayHello(name:String){print("Hello,"+name)}
sayHello: (name: String)Unit

scala> val sayHelloFunc = sayHello _
sayHelloFunc: String => Unit = 

scala> sayHelloFunc("leo")
Hello,leo
scala>

2匿名関数
scalaでは、関数の名前を付ける必要がなく、匿名関数と呼ばれることもあります.関数を直接定義した後、関数を変数に割り当てることができます.直接定義された匿名関数を他の関数に転送することもできます.scalaが匿名関数を定義する元のルールは、(パラメータ名:パラメータタイプ)=>関数体
scala> val sayHelloFunc = (name:String) => println("Hello,"+name)
sayHelloFunc: String => Unit = 

scala> sayHelloFunc("de")
Hello,de

3高次関数
scalaでは,関数は一等公民であるため,パラメータとしてある関数を直接他の関数に伝達することができる.この機能は極めて強力であり、javaというオブジェクト向けのプログラミング言語には備わっていない.他の関数をパラメータとして受信する関数は、高次関数(higher-older-function)とも呼ばれる.
scala> val sayHelloFunc = (name:String) => println("Hello,"+name)
sayHelloFunc: String => Unit = 

scala> def greeting(func:String => Unit,name:String){func(name)}
greeting: (func: String => Unit, name: String)Unit

scala> greeting(sayHelloFunc,"leo")
Hello,leo

scala> Array(1,2,3,4,5).map((num:Int) => num*num)
res4: Array[Int] = Array(1, 4, 9, 16, 25)

高次関数のもう一つの機能は、関数を戻り値とすることです.
scala> def getGreetingFunc(msg:String) = (name:String) => println(msg + ","+name)
getGreetingFunc: (msg: String)String => Unit

scala> val greetingFunc = getGreetingFunc("hello,")
greetingFunc: String => Unit = 

scala> greetingFunc("leo")
hello,,leo


4高次関数のタイプ推定
高次関数は、タイプを明記する必要がなく、パラメータタイプを自動的に推定することができる.また、パラメータが1つしかない関数については、カッコを省略することもできます.右側の関数内で1つのパラメータのみが1回しか使用されない場合は、その受信関数を省略し、そのパラメータを_クラスの代替.
scala> def greeting(func:(String) => Unit,name:String){func(name)}
greeting: (func: String => Unit, name: String)Unit

scala> greeting((name:String) => println("Hello,"+name),"leo")
Hello,leo

scala> greeting((name) => println("Hello,"+name),"leo")
Hello,leo

scala> greeting(name => println("Hello,"+name),"leo")
Hello,leo

scala> def triple(func:(Int) => Int) = {func(3)}
triple: (func: Int => Int)Int

scala> triple(3 * _)
res10: Int = 9


5 scalaの一般的な高次関数
map:入力された各要素をマッピングし、処理後の要素を返します.
scala> Array(1,2,3,4,5).map(2*_)
res11: Array[Int] = Array(2, 4, 6, 8, 10)

foreach:入力された各要素は処理されますが、値は返されません.
scala> (1 to 9).map("*" * _).foreach(println _)
*
**
***
****
*****
******
*******
********
*********

scala>

filter:入力された各要素に対して条件判断を行い、要素に対してtrueを返すと、その要素を保持し、そうしないとフィルタされます.
scala> (1 to 20).filter(_ % 2 ==0)
res13: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)

scala>

reduceLeft:左側の要素から、要素1と要素2を先に処理してから、結果を要素3と処理してから、結果を要素4と処理して、順番に類推します.つまり、reduceの下の操作は123456789に相当します.
scala> (1 to 9).reduceLeft(_*_)
res15: Int = 362880

scala>

softWith:要素を2つ比較して並べ替え
scala> Array(3,2,5,4,10,1).sortWith(_ < _)
res16: Array[Int] = Array(1, 2, 3, 4, 5, 10)

scala>

6閉パッケージ
閉パケットの最も簡潔な解釈:関数は変数が有効な役割ドメインにない場合、変数にアクセスすることができます.すなわち、閉パケットです.
scala> def getGreetFunc(msg:String) = (name:String) => println(msg+","+name)
getGreetFunc: (msg: String)String => Unit

scala> val greetingFuncHello = getGreetFunc("hello")
greetingFuncHello: String => Unit = 

scala> val greetingFuncHi = getGreetingFunc("HI")
greetingFuncHi: String => Unit = 


getGreetingFunc関数を2回呼び出し、異なるmsgに転送し、異なる関数を作成して返すが、msgはローカル変数にすぎないが、getGreetingFuncが実行された後も、作成された関数の中に存在し続けることができ、greetingFuncHello(「leo」)は呼び出し時に「hello」の値を持つmsgが関数体の内部に保持され、このような変数を繰り返し使用できるのは,その役割ドメインを超え,また使用できる場合,すなわち閉パケットである.
scalaは、各関数によってオブジェクトを作成することによって閉パケットを実現するが、実際にはgreetingFunc関数によって作成される関数に対して、msgは関数オブジェクトの変数として存在するため、各関数が異なるmsg scalaコンパイラを持つことができるため、上記の閉パケットメカニズムが確保される.
7 SAM変換
Javaでは、パラメータとして関数を直接伝達する方法はサポートされていません.通常、唯一の方法は、インタフェースを実現したクラスのインスタンスオブジェクトを定義することです.このオブジェクトには1つの方法しかありません.これらのインタフェースはすべて単一の抽象的な方法だけで、つまりsingle abstract methodで、略称SAMはscalaがjavaのコードを呼び出すことができるため、私达がjavaのある方法を呼び出す时、SAMを作成して方法に伝えることができなくて、とても面倒です;しかしscalaは直接伝達関数をサポートしている.したがってscalaが提供するjavaメソッドを呼び出すときに使用する機能、SAM変換を使用して、SAMをscala関数に変換することができます.SAM変換を使用するには、scalaが提供する特性、暗黙的な変換を使用する必要があります.
scala> import javax.swing._
import javax.swing._

scala> import java.awt.event._
import java.awt.event._

#java            
scala> val button = new JButton("Click")
button: javax.swing.JButton = javax.swing.JButton[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@2857dbe3,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=Click,defaultCapable=true]
# button           
#SAM
scala> button.addActionListener(new ActionListener{
     | override def actionPerformed(event:ActionEvent){
     |  println("Click Mell!")
     | }
     | })
#SAM  ,    
scala> implicit def getActionListener(actionProcessFunc:(ActionEvent) => Unit) = new ActionListener{
     | override def actionPerformed(event:ActionEvent){
     |  actionProcessFunc(event)
     | }
     | }
warning: there was one feature warning; re-run with -feature for details
getActionListener: (actionProcessFunc: java.awt.event.ActionEvent => Unit)java.awt.event.ActionListener

scala> button.addActionListener((event:ActionEvent) => println("Cick ME!!"))

scala>

8 curring関数
Curring関数コリー化()とは、元の2つのパラメータを受信した1つの関数を2つの関数に変換し、最初の関数は元の最初のパラメータを受信し、2番目のパラメータを受信した2番目の関数に戻ることを意味します.関数呼び出し中に、2つの関数が連続的に呼び出される形式になります.
scala> def sum(a:Int,b:Int) = a + b
sum: (a: Int, b: Int)Int

scala> sum(1,1)
res0: Int = 2

scala> def sum2(a:Int) = (b:Int) => a+b
sum2: (a: Int)Int => Int

scala> sum2(1)(1)
res1: Int = 2

scala> def sum3(a:Int)(b:Int) = a + b
sum3: (a: Int)(b: Int)Int

scala> sum3(1)(1)
res4: Int = 2

scala>

9 return
scalaでは、returnを使用して関数の値を返す必要はありません.関数の最後の行の文の値は、関数の戻り値です.scalaでは、匿名関数に匿名関数を含む名前付き関数に値を返し、名前付き関数の戻り値として使用します.returnの匿名関数を使用するには、戻りタイプを指定する必要があります.そうしないと、コンパイルできません.
scala> def greeting(name:String) = {
     | def sayHello(name:String):String ={
     |  return "Hello" + name
     |  }
     |  sayHello(name)
     | }
greeting: (name: String)String

scala> greeting("Leo")
res5: String = HelloLeo

scala>