函数式编程
Scala函数式编程相当于面向对象编程的方法封装,是一种“编程范式”,是为了编写程序的方法论。
Scala函数式编程是“结构化编程”的一种,他的思想是把运算过程尽量写成漫画一系列嵌套的函数调用。
函数为了把一些特定功能的代码封装在一个体系之内,方便使用,提高代码的复用性。
函数编程语言的基础是λ-演算。
下面我们尝试在IDEA中进行函数式编程,首先在编程之前我们要进行一定的准备工作,就是在IDEA中进行相应的Scala编程配置。(pom.xml文件)
1.1 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.nefu</groupId>
<artifactId>Scala</artifactId>
<version>1.0-SNAPSHOT</version>
<name>Scala</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.11.8</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.scala-tools</groupId>
<artifactId>maven-scala-plugin</artifactId>
<version>2.15.2</version>
<executions>
<execution>
<id>scala-compile-first</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<includes>
<include>**/*.scala</include>
</includes>
</configuration>
</execution>
<execution>
<id>scala-test-compile</id>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<!--maven �ᓫ -->
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<!-- scala maven �컏����-->
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
首先我们看一下JavaScript动态式编程语言的特征。
1.我们写这样一段代码,其中定义了一个function,test。
<script>
//JS是一种弱类型的编程语言,动态类型的编程语言
function test(v1,v2){
return v1 + v2
}
alert(test("10","20"))
</script>
打开浏览器看到的是:
我们对刚刚的JS代码稍作调整:
<script>
//JS是一种弱类型的编程语言,动态类型的编程语言
function test(v1,v2){
return v1 + v2
}
alert(test(10,20))
</script>
此时的运行结果为
类比着JS的编程的特征我们看Scala函数式编程 。
首先创建一个object类型的Scala类文件。
object Scala_Function {
//public static void main(String[] args){
//}
//相比于js是强类型的编程语言,他要指定类型
def main(args:Array[String]):Unit = {
println("hello Scala!")
println(testSum(10,20))
}
def testSum(v1:Int,v2:Int):Int = {
return v1 + v2;
}
def printScala():Unit = {
println("Scala")
}
}
运行结果为
"C:\Program Files\Java\jdk1.8.0_151\bin\java.exe" "-javaagent:D:\AboutMyWork\MyDevelopmentTool\IntelliJ_Idea\IntelliJ IDEA Community Edition 2019.2.3\lib\idea_rt.jar=50221:D:\AboutMyWork\MyDevelopmentTool\IntelliJ_Idea\IntelliJ IDEA Community Edition 2019.2.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_151\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_151\jre\lib\rt.jar;D:\AboutMyWork\IDEA-WorkSpace\ScalaDemo\ScalaExamples\target\classes;D:\AboutMyWork\MyDevelopmentTool\Maven\Repository\org\scala-lang\scala-library\2.11.8\scala-library-2.11.8.jar" Scala_Function
hello Scala!
30
Process finished with exit code 0
1.2 Scala函数的声明与调用:
def 函数名(参数名[:参数类型]…) [: 返回值类型 = ] {函数体}
函数声明关键字为 def(definition)
如果函数中无返回值,那么返回值类型无需声明
1.分号是可有可无的,是表示一个句子的结束
2.有返回值且类型明确也可以写成Unit无返回值类型,则运行结果为空形式为:“()”
3.在Scala中return关键字可以省略,返回值是函数中最后一行语句的执行结果
4.IDEA可以根据函数的最后一行自动声明返回类型
5.如果函数中写了return,则必须声明返回类型
函数调用:
如果函数无参数列表,那么小括号可以省略
函数声明时如果加括号,调用可加可不加;没加括号,调用一定不能加。
1.3 声明变量
/** *******************
* 有关Scala声明变量
* @auther Dr.Li
* @create 2019-11-08 14:45
* ********************/
object ScalaVar {
/*
val和var是声明关键字,不是类型
1.val是只读的变量(一旦被定义不可变)
若在函数外声明,则为常量,反编译后可知final修饰
在函数内声明,没有final修饰
2.var声明的是可变的变量
3.类型关键字在变量类型明确的条件下可以省略,IDEAScala自动推断
*/
val age = 21
def main(args: Array[String]): Unit = {
val v1 = 10 //value
//v1 = 30 会报错
var v2 = 20 //variable
v2 = 30
println(v1)
//final int[] ints = new int[10]
//final int i = 10;
//i = 20;
// 基本数据类型存在于栈中,对象类型存在于堆中
}
}
1.4 类型声明
Scala 常用类型中包含有 7 种数值类型: Byte、 Char、 Short、 Int、 Long、 Float、
Double及 Boolean 类型,还有 String 类型。
1.5 语义推断
一行逻辑代码的最后,无需使用分号结束,编程语言自动推断
但是一行代码中如果存在多个逻辑代码,那么不同的逻辑代码必须使用分号分隔
2 基础特性
2.1 函数是第一等公民
函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。
/** *******************
*
* @auther Dr.Li
* @create 2019-11-08 15:27
* ********************/
object Scala_Function2 {
def main(args: Array[String]): Unit = {
val m = testM2 _ //m引用testM2
println(m)
m()()
//m()返回testM2引用的结果,即testM1,m()()则是testM1的返回结果
}
def testM1(){
print("Test M1...")
}
def testM2() = {
/*
为什么有等号?这个返回结果不是Unit是引用的testM1的类型
如果没有等号,则证明是一个空类型的返回结果(Unit)。
*/
testM1 _ //引用testM1
}
}
2.2 纯函数
就是没有副作用的函数, 这里所谓的没有副作用,指的是函数要保持独立,所有功能就
是返回一个新的值,没有其他行为,尤其是不得修改外部变量的值。
// 纯函数
function sum( num1, num2 ) {
return num1 + num2
}
// 非纯函数
var num1 = 10; // 函数外变量
function sum( num2 ) {
return num1 + num2;
}
2.3 引用透明
在函数式编程中,引用透明指的是运行函数的时候,函数的每一个步骤都不会牵连到函
数的外部变量或状态,而是只依赖于函数输入的参数, 相同的参数输入总会得到相同的函
数返回值(如 MD5 加密算法) 。而在其他类型的语言中,函数的返回值不仅仅与函数的参数传入有关,也与当前的系统状态有关。在不同的系统状态的情况下,函数的返回值不同。