scala 函数式编程与隐式函数

scala 函数式编程:
1,函数式编程强调的函数可以像变量一样被创建,修改,并当成变量一样传递,返回或是在函数中嵌套函数
2,Scala混合了面向对象和函数式的特性,我们通常将可以做为参数传递到方法中的表达式叫做函数
3,函数柯里化指的是将原来接受两个参数的方法变成新的接受一个参数的方法的过程
4,引用透明指的是函数的运行不依赖于外部变量或“状态”,只依赖于输入的参数,任何时候只要参数相同,调用函数所得到的返回值总是相同的。天然适应并发编程,因为调用函数的结果具有一致性,所以根本不需要加锁,也就不存在死锁的问题。
5,尾递归:函数调用要压栈保存现场,递归层次过深的话,压栈过多会产生性能问题。所以引入尾递归优化,每次递归时都会重用栈,提升性能
package day01
object DFuntion {
  def main(args: Array[String]): Unit = {
    /* 传入值是函数的形式! */
    val arr = Array(1,2,3,4,5,6)
    //定义一个函数
    val fun = (item:Int)=>{item*2}
    //匿名函数
//    val arr2 = arr.map((item:Int)=>{item*2})
    //_ 表示数组里面的元素
    val arr2 = arr.map(_*2) // map 传入值是函数,map是高阶函数
    println(arr2.toBuffer)

    // 定义一个高阶函数 : 返回值是函数  {}函数体 最后一行是返回值
  def urlBuilder(ssl:Boolean,DomainName:String):(String,String)=>String={
      val schema =if(ssl) "https://" else "http://"
      (endpoint:String,query:String)=>s"$schema$DomainName/$endpoint?$query"
  }
  val DomainName ="www.baidu.com"
  val getUrl:(String,String)=>String=urlBuilder(ssl = false,DomainName)
  val endpoint="user"
  val query ="id=1"
  val res3 =getUrl(endpoint,query)
  println(res3)
}
}
object CurryD{
  def main(args: Array[String]): Unit = {
    /* 柯里化指的是将两个参数函数变成一个参数函数,这样可以创建更多的函数*/
    // 普通方法
    def numadd(x:Int,y:Int)=x+y
    println(numadd(1, 3))
    // 柯里化后的方法
    def curryAdd(x:Int)(y:Int)=x+y
    println(curryAdd(1)(3))

//    模拟柯里化过程 方法指定函数!
    def first(x:Int)=(y:Int)=>x+y
    val second = first(1)
    val res =second(3)
    println(res)
    // _ 表示占位符
    val ont_test=curryAdd(1)_
    println(ont_test(2))
    val two_test =curryAdd(2)_
    println(two_test(1))

    val list =List(1,2,3,4)
    // 柯里化实例 两个函数 (0) (_+_)
    println(list.foldLeft(0)(_ + _))
  }
}
object Method{
  // 使用函数的嵌套来实现阶乘
  def main(args: Array[String]): Unit = {
    def fatorial(x:Int): Int = {
      def fact(x: Int, accurmulator: Int): Int = {
        if (x < 1) accurmulator
        else fact(x - 1, x * accurmulator)
      }
      fact(x, accurmulator = 1)
    }
    println(fatorial(5))
  }
  // 方法的多态 方法可以根据类型实现参数化,类似泛型
  def listofDuplicates[A](x:A,length:Int): List[A] ={
      if (length<1)
        Nil  // 空对象
      else
        x::listofDuplicates(x,length-1)
  }
  println(listofDuplicates(3, 2))
  println(listofDuplicates("ABC", 2))
}
scala隐式转换:
1,隐式转换函数是指那种以implicit关键字声明的带有单个参数的函数
2,隐式的对类的方法进行增强,丰富现有类库的功能
3.隐式转换和隐式参数是Scala中两个非常强大的功能,利用隐式转换和隐式参数,你可以提供优雅的类库,对类库的使用者隐匿掉那些枯燥乏味的细节
4,隐式参数:
1),方法中带有以一个标记为implict的参数列表,编译器会查找缺省值,提供给该方法
2),被查找到的值必须被implict修饰并与方法中implict修饰的类型相同
package day01
import java.io.File
import scala.Predef._
import scala.io.Source// 里面包含了 println
object implisc {
  def main(args: Array[String]): Unit = {
      val ma =Map("name"->" a ")
      val num:Int =1
    //println(num)
    // 定义一个隐式类 可以将 File 转换成 ReachFile
    //使用隐式类为原有的类扩展功能
      implicit class ReachFile(from: File){
      def read:String = Source.fromFile(from.getPath).mkString
}
     // 为 File 增加一个 read 方法
      val cotend = new File(
        "E:\\ScalaCode\\src\\main\\scala\\day01\\1.txt"
      ).read
      println(cotend)
    var a = 1 ;var b=0.1; b=a  // 可以互相转换时由于 int类型有着 隐式转换(int->double)
    //      a=b double 类型不能转换成int ,double 没有定义转换成int的隐式转换
    println(b)
    //定义一个隐式转换 使得 double 转换成 int(有精度损失)
    implicit def DoubleToint(x:Double): Int = {
      x toInt
    }
    a=b //类型和期望的类型不一致,解释器就会隐式查找
      import implicitClass._
      // 解释器找不到方法就会去隐式查找
      10 times println("Sucess!")
  }
}
 object implicitClass{
//   为 int 类型增加一个 times方法!
   // 隐式类 只能定义在类, trait,object内部
   //隐式类构造函数只能带一个非隐式参数
   implicit class implicitClasswith(x: Int){
      def times[A](f:A):Unit={
        def loop(current:Int):Unit={
          if (current>0){
            f
            loop(current-1)
          }
        }
       loop(x)
     }
   }
   //一个特质,带有一个抽象方法
   trait Adder[T]{
     def add(x:T,y:T):T
   }
   //创建一个隐式对象
   implicit val a =new Adder[Int] {
     def add(x:Int,y:Int): Int ={
       x+y
     }
   }
   // 定义了一个带有隐式参数的方法
   def AddTest(x:Int,y:Int)(implicit adder:Adder[Int]):Int={
     adder.add(x,y)
   }

   def main(args: Array[String]): Unit = {
     // 在函数的作用域内有相同的隐式值,那么就会自动填充方法的隐式参数
     println(AddTest(1, 2))
//   println(AddTest(1, 2)(a)) //两者结果相同
   }
 }

 

posted @ 2019-03-23 22:35  十七楼的羊  阅读(480)  评论(0编辑  收藏  举报