我有以下Scala代码示例,我想知道为什么我在foldLeft上出现错误而不是在foldRight上出现错误?
val xs = List(1,2,3)
val ys = List(4,5,6)
(xs foldLeft ys) (_::_) // Error: Value :: is not a member of Int
(xs foldRight ys) (_::_) // Res: List(1, 2, 3, 4, 5, 6)
我是Scala的新手,所以请尽可能简单地回复。感谢
答案 0 :(得分:3)
传递给foldLeft
和foldRight
的运算符(函数)的参数顺序相反。
所以在foldLeft
_ :: _
ys :: xs.head
以foldRight
开头,这没有任何意义。
使用xs.last :: ys
,最里面的操作是z /: ws
,这很好。
参数顺序在运算符版本中更有意义:z
向ws
推进foldLeft
(即ws :\ z
),而z
推动foldRight
向左(即z
)。内部参数的顺序与上面w
与class Node():
def __init__(self, value = None, nex = None):
self.val = value
self.nex = nex
class List(Node):
def __init__(self):
self.head = Node()
def ins(self):
li = []
for i in range(10):
setattr(self,'n' + str(i), Node(i))
#self.n0.nex = self.n1
#self.n1.nex = self.n2
#self.n2.nex = self.n3
#.
#.
#.
#self.n8.nex = self.n9
的顺序一致。
答案 1 :(得分:2)
foldLeft和foldRight有不同的签名,它们接受不同的参数
def foldLeft[B](z: B)(op: (B, A) => B): B
def foldRight[B](z: B)(op: (A, B) => B): B
在这两个中查看函数op
的类型。对于foldLeft,左参数是您要折叠的集合的类型(在您的情况下是int),而对于foldRight,它是结果类型(在您的情况下是集合)。
因此,如果您希望每个后续元素都附加到结果列表中,那么您希望在foldLeft中使用不同的函数。
答案 2 :(得分:1)
简而言之,操作'::'在Int上不可用,仅在集合上可用。 如果在Scala REPL中执行'(xs foldLeft ys)_',您会看到它导致函数
((List[Int], Int) => List[Int]) => List[Int] = <function1>
因此第一个操作数是List [Int],第二个操作数是Int。 请注意,以“:”结尾的任何运算符都是特殊的,因为它使用左侧作为参数在右侧侧操作数上操作。这称为“右关联”,而默认通常是“左关联”。
因此'aList :: anInt'被翻译成'anInt.::(aList)',这会导致问题,因为Int没有'::'方法。
在'foldLeft'的情况下,你需要一个左关联函数来添加像':+'这样的单个元素。所以这可行:
(xs foldLeft ys)(_ :+ _)
请注意,结果与foldRight完全不同,所以请务必根据您的情况选择更正。