Scala_Note_1

	
1 class 中调用类的伴生对象(object)方法时需要加类名
2 理解var&val VS mutable&immutable的区别
3 理解lazy val.若一个耗时方法被声明为lazy val,则调用该方法的所有方法尽量声明为lazy val.否则类实例化的时候,还是会计算,似的lazy val失效
4 mutable.Map can not cast to immutable.Map
5 Description	Resource	Path	Location	Type
          type mismatch;  found   : item_id.type (with underlying type String)  required: _1	UserMap.scala	/TmallData/src/weejang	line 68	Scala Problem

6 xml: xml 在2.11以后的系列中,都将被作为一个独立的jar引入.
  refer: http://stackoverflow.com/questions/22223304/how-will-xml-modularisation-in-scala-2-11-play-with-xml-literals

7 @符号的作用:
---1
//绑定匹配变量

     val list = List(User("jangwee",11),1,User("Liuhuapeng",33),4)
     val seeList = for{
       elem @ User(_,_) <- list
     }yield (elem)
     
     println(seeList)    

//output : 
//    List(User(jangwee,11), User(Liuhuapeng,33))





8 sbt 拉取下来的库位置
 ~/.ivy/cache

9 akka 需要引入 config.jar 
com.typesafe.
   refer : http://stackoverflow.com/questions/26052261/bad-symbolic-reference-in-scala-ide-for-eclipse

10  
 过滤数据:


    val wordFrequencies = ("hh", 5) :: ("ww", 2) :: ("aa", 7) :: Nil

    //method1,Tuple2
    def format1(wf: Seq[(String, Int)]): Seq[String] = {
      wf.filter { x => x._2 > 2 && x._2 < 7 }.map { _._1 }
    }

    println(format1(wordFrequencies))//List(hh)

    //method2,模式匹配结构
    def format2(wf: Seq[(String, Int)]): Seq[String] = {
      wf.filter { case (word, count) => count > 2 && count < 7 }.map { case (word, _) => word }
    }

    println(format2(wordFrequencies))//List(hh)
    //method3-1,偏函数
    //    val pf : PartialFunction[(String,Int),String] = {
    //      case (word,freq) if freq > 2 && freq < 7 => word
    //    }

    //method3-2,显式定义偏函数Trait
    val pf = new PartialFunction[(String, Int), String] {
      def apply(wordFrequency: (String, Int)): String = {
        wordFrequency match {
          case (word, count) if count > 2 && count < 7 => word
        }

      }
      def isDefinedAt(wordFrequency: (String, Int)): Boolean = {
        wordFrequency match {
          case (word, count) if count > 2 && count < 7 => true
          case _ => false
        }
      }
    }

    // Compile Okay,RunTime Error
    //  Exception in thread "main" scala.MatchError: (ww,2) (of class scala.Tuple2)
    //println(wordFrequencies.map(pf))

    println(wordFrequencies.map(pf.isDefinedAt(_))) //List(true, false, false)

    println(wordFrequencies.collect(pf)) // List(hh)

11 for-expression
  

val lastNames = List("Jang", "Geng")
    val firstNames = List("Wee", "Jie")

    //for-expression
    val allName = for {
      lastname <- lastNames
      firstname <- firstNames
    } yield lastname + " " + firstname

    println(allName) //List(Jang Wee, Jang Jie, Geng Wee, Geng Jie)

    // == flatMap
    val allName2 = lastNames.flatMap { lastname =>
      firstNames.map { firstname => lastname + " " + firstname }
    }

    println(allName2) //List(Jang Wee, Jang Jie, Geng Wee, Geng Jie)

    // why flatMap ? what happened with Map?
    val allName3 = lastNames.map { lastname =>
      firstNames.map { firstname => lastname + " " + firstname }
    }
    println(allName3) //List(List(Jang Wee, Jang Jie), List(Geng Wee, Geng Jie))
    
    // with Option
    val maybeFirstName = Some("Wee")
    val maybeLastName = None
    val result = for{
      lastname <- maybeLastName
      firstname <- maybeFirstName
    } yield User(lastname,firstname)
    
    println(result) // None

12 异常处理
   

   //类Java方式的异常处理
case class Customer(age: Int)
class Cigarettes
case class UnderAgeException(message: String) extends Exception(message)

object MMain {
  def main(args: Array[String]): Unit = {
    val customer = new Customer(16)
    try{
      buyCigarettes(customer)
    }catch{
      //case UnderAgeException(msg) => println(msg) //Customer must be older than 18 but was 16
      case ex @ UnderAgeException(_) => ex.printStackTrace()
//      qoeAnalyzer.UnderAgeException: Customer must be older than 18 but was 16
//      at qoeAnalyzer.MMain$.buyCigarettes(MMain.scala:35)
//      at qoeAnalyzer.MMain$.main(MMain.scala:25)
//      at qoeAnalyzer.MMain.main(MMain.scala)
    }

  }

  def buyCigarettes(customer: Customer) : Cigarettes = {
    if (customer.age < 18 )
      throw UnderAgeException(s"Customer must be older than 18 but was ${customer.age}")
    else
      new Cigarettes
  }
}



// 函数式的错误处理 -Try


import scala.util.Random
import scala.util.{ Try,Success, Failure }
import scala.io.StdIn

object MMain {
  def main(args: Array[String]): Unit = {
    
    val result = divide
    result match {
      case Success(v) =>
        println(s"result of is ${v}")
      case Failure(e) =>
        println("You must've divided by zero or entered something that's not an Int. Try again!")
        println(e.getMessage)
    }
    
  }
  
  def divide: Try[Int] = {
    val dividend = Try(StdIn.readLine("Enter an Int that you'd like to divide:\n").toInt)
    val divisor = Try(StdIn.readLine("Enter an Int that you'd like to divide by :\n").toInt)
    
    //Method_1:    for-expression    
//    val problem = for{
//      x <- dividend
//      y <- divisor
//    } yield( x / y )

    //Method_2:    flatMap*N-Map    
    val problem = dividend.flatMap( x => divisor.map { y => (x / y) })
    
    problem
  }
}

:output:

Enter an Int that you'd like to divide:
10
Enter an Int that you'd like to divide by :
3
result of is 3


or

Enter an Int that you'd like to divide:
10
Enter an Int that you'd like to divide by :
0
You must've divided by zero or entered something that's not an Int. Try again!
/ by zero


----

  def main(args: Array[String]): Unit = {
    
   def parseURL(url:String) = Try(new URL(url))//MalformedURLException
   
   //val url = parseURL(StdIn.readLine("URL: ")) getOrElse new URL("http://www.baidu.com")
   
   val result1 = parseURL("http://www.baidu.com").map{_.getProtocol} //Success(http)
   result1.map { println _ }
   
   val result2 = parseURL("garbage").map{_.getProtocol} //Failure(java.net.MalformedURLException: no protocol: garbage)
   result2.map { println _ } 
  }


output:

http


:result2不执行里面的闭包  

----


  def main(args: Array[String]): Unit = {

    def parseURL(url: String) = Try(new URL(url)) //MalformedURLException

    //Method1 -(flatMap with Map)
    def getURLContent1(url: String):Try[Iterator[String]] = {
      parseURL(url).flatMap { url => Try(url.openConnection) }
          .flatMap { conn => Try(conn.getInputStream) }
          .flatMap { istream => Try(scala.io.Source.fromInputStream(istream))}
    }.map{_.getLines()}
   
    getURLContent1("http://www.baidu.com").map{ x => x.foreach { println _} }
    
    //Method2 - for express
    def getURLContent2(url: String): Try[Iterator[String]] = for{
      purl <- parseURL(url)
      conn <- Try(purl.openConnection)
      inputStream <- Try(conn.getInputStream)
      source <- Try(scala.io.Source.fromInputStream(inputStream))
    } yield source.getLines()
    
     getURLContent2("http://www.baidu.com").map{ x => x.foreach { println _} }
  }


----
添加 recover 

    //添加故障回复 recover
    val content = getURLContent1("garbage") recover {
      case e: FileNotFoundException => Iterator("Requested page does not exist")
      case e: MalformedURLException => Iterator("Please make sure to enter a valid URL")
      case _ => Iterator("An unexpected error has occurred. We are so sorry!")
    }
    
    content.get.foreach { println _ }  

---

13 Either - 无偏的Try


      import java.net.URL
      import scala.io.Source
      
      def getContent(url: URL): Either[String,Source] = {
        if(url.getHost.contains("google"))
          Left("Requested URL is blocked for the good of the people")
        else
          Right(Source.fromURL(url))
      }
      
      //RightProjection 
      val content : Either[String,Iterator[String]] = getContent(new URL("http://www.baidu.com")).right.map { _.getLines }
      //Right(non-empty iterator)
      val morecontent : Either[String,Iterator[String]] = getContent(new URL("http://google.com")).right.map{ _.getLines }
      //Left(Requested URL is blocked for the good of the people)

      //LeftProjection
      val content1 : Either[Iterator[String],Source] = getContent(new URL("http://www.baidu.com")).left.map{ Iterator(_) }
      //Right(non-empty iterator)
      val morecontent1 : Either[Iterator[String],Source] =getContent(new URL("http://google.com")).left.map{ Iterator(_) }
      //Left(non-empty iterator)
      
      //content.right.map{ iter => iter.foreach { println _ } } 
      // 网页内容 ...content-type" content="text/html;charset ...
      //morecontent.right.map{ iter => iter.foreach { println _ } }
      //无输出
      content1.left.map { iter => iter.foreach { println _ } }
      //无输出
      morecontent1.left.map { iter => iter.foreach {println _}}
      //Requested URL is blocked for the good of the people




----
      val baidu = new URL("http://www.baidu.com")
      val gufen = new URL("http://www.gfsoso.net")

//    Method 1
//      val contentSize = getContent(baidu).right.flatMap{
//        bd => getContent(sina).right.map{
//          sn => ( bd.getLines().size , sn.getLines().size )
//        }
//      }

//    Method 2 For-comprehesion
  
      val contentSize = for{
        bd <- getContent(baidu).right
        gf <- getContent(gufen).right
        line1 <- Right(bd.getLines().size).right
        line2 <- Right(gf.getLines().size).right
      }yield (line1,line2)
      
      println(contentSize) //Right((23,129))

----

      //Fold 函数
      //如果想变换一个Either(不论它是Left值,还是Right值),可以使用定义在Either上的fold方法.这个方法接受两个
      //返回相同类型的变换函数,当这个函数是Left值时,第一个函数被调用,否则,第二个函数会被调用
      //替换模式匹配
      
      val content: Iterator[String] = getContent(new URL("http://www.baidu.com")).fold(Iterator(_), _.getLines())


----

         
    //异常处理
    import scala.util.control.Exception.catching
    def handling[Ex <: Throwable, T](exType: Class[Ex])(block: => T): Either[Ex, T] =
      catching(exType).either(block).asInstanceOf[Either[Ex, T]]

    def parseURL(url: String): Either[MalformedURLException, URL] =
      handling(classOf[MalformedURLException])(new URL(url))


----
    处理集合

   object MMain {

  type Citizen = String
  case class BlackListResource(url: URL, visitor: Set[Citizen])
  
  val blacklist = List(
    BlackListResource(new URL("https://google.com"),Set("hh")),
    BlackListResource(new URL("https://sina.com"),Set.empty),
    BlackListResource(new URL("https://git.com"),Set.empty),
    BlackListResource(new URL("https://finger.com"),Set("ni","wo"))
  )
  

  def main(args: Array[String]): Unit = { 
    val checkedList : List[Either[URL,Set[Citizen]]] = blacklist.map { bsource =>
      if(bsource.visitor.isEmpty)  Left(bsource.url)
      else Right(bsource.visitor)
    }
    
    val suspicisousResources = checkedList.flatMap(_.left.toOption)
    val problemCitizens = checkedList.flatMap(_.right.toOption)
    println(problemCitizens.flatten.toSet)
}




---------

高阶函数-DRY(Dont Repeat Yourself)


 // 命名
   type EmailFilter = Email => Boolean
   // 
   def newEmailsForUser(mails:Seq[Email],filter: EmailFilter) = mails.filter(filter)
   
   //EmailFilter工厂函数
   val sendByOneOf:Set[String] => EmailFilter = 
     (senders: Set[String] ) =>
       (email: Email) =>
         senders.contains(email.sender)
         
   val notSendByOneOf:Set[String] => EmailFilter =
     (senders: Set[String]) =>
       (email: Email) =>
         !senders.contains(email.sender)
         
         
   val minumSize : Int => EmailFilter =
     (n: Int) =>
       (email: Email) =>
         email.text.size > n
   
   val maxnumSize : Int => EmailFilter =
     (n: Int) =>
       (email: Email) =>
         email.text.size < n
         
  def main(args: Array[String]): Unit = { 
     
      val emailFilter: EmailFilter = notSendByOneOf(Set("jangwee1@sina.com.cn"))
      
      val emails = Email(
        subject = "hello",
        text = "hello",
        sender = "jangwee1@sina.com.cn",
        recipient = "hh"
      ) :: Nil
      
      val result = newEmailsForUser(emails,emailFilter)
      println(result.toSeq.toString()) //List()
    
  }  


improve:

 type sizeCheck = Int => Boolean
   
   val sizeConstraint:sizeCheck => EmailFilter =
     (f: sizeCheck) =>
       (email: Email) =>
         f(email.text.size)
  
   val mininumSize: Int => EmailFilter =
     (n: Int) =>
       sizeConstraint(_ > n)
       
   val maxinumSize: Int => EmailFilter =
     (n: Int) =>
       sizeConstraint(_ < n)