Scala 中的折叠列表
Folding lists in scala
scala 中使用 /: 和 :\ 运算符的折叠列表
我试图查看不同的站点,但他们只谈论 foldRight 和 foldLeft 函数。
def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)
sum(List(1,2,3))
res0: 6
代码段按描述工作。但是我无法完全理解方法定义。我的理解是第一个括号内的那个 -> 0 /: xs 其中 /: 是右关联运算符。对象是 xs,参数是 0。我不确定操作的 return 类型(很可能是另一个列表?)。第二部分是功能部分,将其两个参数相加。但我不明白什么对象调用它?和函数名称。有人可以帮我理解一下吗。
:/
的签名是
/:[B](z: B)(op: (B, A) ⇒ B): B
这是一个有多个参数列表的方法,所以当它只是用 on 参数调用时(即在你的例子中是 0 /: xs
),return 类型是 (op: (B, A) ⇒ B): B
。因此,您必须向它传递一个带有 2 个参数 ( _ + _ ) 的方法,该方法用于组合从 z 开始的列表元素。
这种方法通常被称为foldLeft
:
(0 /: xs)(_ + _)
等同于 xs.foldLeft(0)(_ + _)
您可以在此处找到更多详细信息:https://www.scala-lang.org/api/2.12.3/scala/collection/immutable/List.html
感谢@HaraldGliebe 和@LuisMiguelMejíaSuárez 的精彩回复。我现在开悟了!我只是在这里总结一下答案,这可能会使阅读此主题的其他人受益。
"/:"实际上是Listclass中定义的函数名。函数的签名是:/:[B](z: B)(op: (B, A) ⇒ B): B
--> 其中B是类型参数,z是第一个参数; op 是函数类型的第二个参数。
该函数遵循 curried 版本 --> 这意味着我们可以传递比实际数量更少的参数。如果我们这样做,
部分应用的函数存储在一个临时变量中;然后我们可以使用临时变量来传递剩余的参数。
如果提供所有参数,“/:”可以调用为: x./:(0)(_+_)
其中 x 是列表类型的 val/var。或 "/:" 可以分两步调用,如下所示:
step:1 val temp = x./:(0)(_)
我们只传递第一个参数。这导致存储在临时变量中的部分应用函数。
step:2 temp(_+_)
这里使用部分应用函数 temp 与第二个(最终)参数一起传递。
如果我们决定遵循第一种风格(x./:(0)(_+_)
),调用第一个参数可以写在运算符概念中,即:x /: 0
由于方法名称以冒号结尾,因此对象将从右侧拉出。所以 x /: 0
是无效的,必须写成 0 /: x
才是正确的。
这个相当于临时变量。在0 /: x
之后,还需要传递第二个参数。所以整个构造变成:(0/:x)(_+_)
问题中函数 sum 的定义是这样解释的。
我们必须注意,当我们在运算符概念中使用函数的柯里化版本时,我们必须一次性提供所有参数。
即:(0 /: x) (_)
或 (0 /: x) _
似乎抛出语法错误。
scala 中使用 /: 和 :\ 运算符的折叠列表
我试图查看不同的站点,但他们只谈论 foldRight 和 foldLeft 函数。
def sum(xs: List[Int]): Int = (0 /: xs) (_ + _)
sum(List(1,2,3))
res0: 6
代码段按描述工作。但是我无法完全理解方法定义。我的理解是第一个括号内的那个 -> 0 /: xs 其中 /: 是右关联运算符。对象是 xs,参数是 0。我不确定操作的 return 类型(很可能是另一个列表?)。第二部分是功能部分,将其两个参数相加。但我不明白什么对象调用它?和函数名称。有人可以帮我理解一下吗。
:/
的签名是
/:[B](z: B)(op: (B, A) ⇒ B): B
这是一个有多个参数列表的方法,所以当它只是用 on 参数调用时(即在你的例子中是 0 /: xs
),return 类型是 (op: (B, A) ⇒ B): B
。因此,您必须向它传递一个带有 2 个参数 ( _ + _ ) 的方法,该方法用于组合从 z 开始的列表元素。
这种方法通常被称为foldLeft
:
(0 /: xs)(_ + _)
等同于 xs.foldLeft(0)(_ + _)
您可以在此处找到更多详细信息:https://www.scala-lang.org/api/2.12.3/scala/collection/immutable/List.html
感谢@HaraldGliebe 和@LuisMiguelMejíaSuárez 的精彩回复。我现在开悟了!我只是在这里总结一下答案,这可能会使阅读此主题的其他人受益。
"/:"实际上是Listclass中定义的函数名。函数的签名是:/:[B](z: B)(op: (B, A) ⇒ B): B
--> 其中B是类型参数,z是第一个参数; op 是函数类型的第二个参数。
该函数遵循 curried 版本 --> 这意味着我们可以传递比实际数量更少的参数。如果我们这样做,
部分应用的函数存储在一个临时变量中;然后我们可以使用临时变量来传递剩余的参数。
如果提供所有参数,“/:”可以调用为: x./:(0)(_+_)
其中 x 是列表类型的 val/var。或 "/:" 可以分两步调用,如下所示:
step:1 val temp = x./:(0)(_)
我们只传递第一个参数。这导致存储在临时变量中的部分应用函数。
step:2 temp(_+_)
这里使用部分应用函数 temp 与第二个(最终)参数一起传递。
如果我们决定遵循第一种风格(x./:(0)(_+_)
),调用第一个参数可以写在运算符概念中,即:x /: 0
由于方法名称以冒号结尾,因此对象将从右侧拉出。所以 x /: 0
是无效的,必须写成 0 /: x
才是正确的。
这个相当于临时变量。在0 /: x
之后,还需要传递第二个参数。所以整个构造变成:(0/:x)(_+_)
问题中函数 sum 的定义是这样解释的。
我们必须注意,当我们在运算符概念中使用函数的柯里化版本时,我们必须一次性提供所有参数。
即:(0 /: x) (_)
或 (0 /: x) _
似乎抛出语法错误。