官术网_书友最值得收藏!

Multiple return values

Let's say that we want to calculate both the positive and negative square roots of an integer. We could approach this problem by writing two different functions:

   fun positiveRoot(k: Int): Double { 
     require(k >= 0) 
     return Math.sqrt(k.toDouble()) 
   } 
 
   fun negativeRoot(k: Int): Double { 
     require(k >= 0) 
     return -Math.sqrt(k.toDouble()) 
   } 

Each function returns one of the roots of k. Another approach might be to return an array so that we only have to invoke one function:

    fun roots(k: Int): Array<Double> { 
      require(k >= 0) 
      val root = Math.sqrt(k.toDouble()) 
      return arrayOf(root, -root) 
    } 

Now, this example returns both the positive and negative roots together in a list. However, we do not know from the return type whether the positive root or negative root is at position 0. We will have to hope that the documentation is correct; if not, inspect the source code. We could improve this further by using a class with two properties that name each of the roots and then return this instead. See the following code snippet as an example:

    class Roots(pos: Double, neg: Double) 
 
    fun roots2(k: Int): Roots { 
      require(k >= 0) 
      val root = Math.sqrt(k.toDouble()) 
      return Roots(root, -root) 
    }

Now, the return value is a class and the two properties make it clear which is the positive root and which is the negative root. This has the advantage of having named fields, so we could be sure which is the positive root and which is the negative root. An alternative to a custom class is using the Kotlin standard library Pair type. This type simply wraps two values, which are accessed through the first and second fields:

    fun roots3(k: Int): Pair<Double, Double> { 
      require(k >= 0) 
      val root = Math.sqrt(k.toDouble()) 
      return Pair(root, -root) 
    } 

This is most often used when it is clear what each value means. For example, a function that returned a currency code and an amount would not necessarily need to have a custom class, as it would be obvious which was which. Furthermore, if the function were a local function, you might feel that creating a custom class would be unnecessary boilerplate for something that will not be visible outside of the member function. As always, the most appropriate choice will depend on the situation.

There is a three-value version of Pair, which is appropriately named Triple.

We can improve this further by using destructuring declarations on the caller site. Destructuring declarations allow the values to be extracted into separate variables automatically:

     val (pos, neg) = roots3(16) 

You can see that the variables are contained in a parenthesis block; the first value will be assigned to the positive root, and the second value will be assigned to the negative root. This syntactic sugar works with any object that implements a special component interface. The built-in Pair type, and all data classes, automatically implement this interface. There will be more on this mechanism in Chapter 9, Data Classes.

主站蜘蛛池模板: 密云县| 克拉玛依市| 新乡县| 同江市| 章丘市| 鹿泉市| 崇义县| 舟曲县| 张家界市| 英山县| 佛冈县| 无棣县| 奈曼旗| 冷水江市| 二手房| 谷城县| 峨眉山市| 新巴尔虎左旗| 莲花县| 台前县| 金塔县| 渑池县| 恩施市| 平安县| 申扎县| 庄河市| 永清县| 昌黎县| 神农架林区| 金湖县| 曲阳县| 定西市| 汤原县| 宜春市| 吉首市| 徐汇区| 南部县| 宁明县| 育儿| 无为县| 呼和浩特市|