Using Tuples in map, flatmap,… partial functions

前端 未结 3 1841
滥情空心
滥情空心 2020-12-19 18:17

If I do:

val l = Seq((\"un\", \"\"), (\"deux\", \"hehe\"), (\"trois\", \"lol\"))
l map { t => t._1 + t._2 }

It\'s ok.

If I d

相关标签:
3条回答
  • 2020-12-19 18:24

    This situation can be understand with the types of inner function.

    First, the type syntax of parameter function for the map function is as follows.

    Tuple2[Int,Int] => B //Function1[Tuple2[Int, Int], B]
    

    The first parameter function is expand to this.

    (t:(Int,Int)) => t._1 + t._2 // type : Tuple2[Int,Int] => Int
    

    This is ok. Then the second function.

    (t:(Int, Int)) => t match {
      case (a:Int, b:Int) => a + b
    }
    

    This is also ok. In the failure scenario,

    (a:Int, b:Int) => a + b 
    

    Lets check the types of the function

    (Int, Int) => Int // Function2[Int, Int, Int]
    

    So the parameter function type is wrong.

    As a solution, you can convert multiple arity functions to tuple mode and backward with the helper functions in Function object. You can do following.

    val l = Seq(("un", ""), ("deux", "hehe"), ("trois", "lol"))
    l map(Function.tupled((b, n) => b + n ))
    

    Please refer Function API for further information.

    0 讨论(0)
  • 2020-12-19 18:37

    The error message with 2.11 is more explanatory:

    scala> l map { (b, n) => b + n }
    <console>:9: error: missing parameter type
    Note: The expected type requires a one-argument function accepting a 2-Tuple.
          Consider a pattern matching anonymous function, `{ case (b, n) =>  ... }`
                  l map { (b, n) => b + n }
                           ^
    <console>:9: error: missing parameter type
                  l map { (b, n) => b + n }
                              ^
    

    For an apply, you get "auto-tupling":

    scala> def f(p: (Int, Int)) = p._1 + p._2
    f: (p: (Int, Int))Int
    
    scala> f(1,2)
    res0: Int = 3
    

    where you supplied two args instead of one.

    But you don't get auto-untupling.

    People have always wanted it to work that way.

    0 讨论(0)
  • 2020-12-19 18:47

    The type of a function argument passed to map function applied to a sequence is inferred by the type of elements in the sequence. In particular,

    scenario 1: l map { t => t._1 + t._2 } is same as l map { t: ((String, String)): (String) => t._1 + t._2 } but shorter, which is possible because of type inference. Scala compiler automatically inferred the type of the argument to be (String, String) => String

    scenario 2: you can also write in longer form

    l map { t => t match {
        case(b, n) => b + n
      }
    }
    

    scenario 3: a function of wrong type is passed to map, which is similar to

    def f1 (a: String, b: String) = a + b
    
    def f2 (t: (String, String)) = t match { case (a, b) => a + b }
    
    l map f1 // won't work
    
    l map f2
    
    0 讨论(0)
提交回复
热议问题