为什么“++”有效但“::”无效,即使它们在 Scala 中具有相同的逻辑
Why "++" works but "::" doesn't work even though they have same logic in scala
abstract class MyList[+A] {
def head: A
def next: MyList[A]
def isEmpty: Boolean
def add[B >: A](element: B): MyList[B]
def printElements: String
override def toString: String = s"[$printElements]"
def ++[B >: A](list: MyList[B]): MyList[B]
def ::[B >: A](list: MyList[B]): MyList[B]
}
case object Empty extends MyList[Nothing] {
def head: Nothing = throw new NoSuchElementException
def next: MyList[Nothing] = throw new NoSuchElementException
def isEmpty: Boolean = true
def add[B >: Nothing](element: B): MyList[B] = Cons(element, Empty)
def printElements: String = ""
def ++[B >: Nothing](list: MyList[B]): MyList[B] = list
def ::[B >: Nothing](list: MyList[B]): MyList[B] = list
}
case class Cons[+A](h: A, t: MyList[A]) extends MyList[A] {
def this(h: A) = this(h, Empty)
def head: A = h
def next: MyList[A] = t
def isEmpty: Boolean = false
def add[B >: A](element: B): MyList[B] = Cons(element, this)
def printElements: String =
if (t.isEmpty) s"$h"
else s"$h ${t.printElements}"
def ++[B >: A](list: MyList[B]): MyList[B] = Cons(h, next ++ list)
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
}
object runTest extends App {
val a = Empty.add(1).add(2).add(3)
val b = Empty.add(4).add(5).add(6)
println(a)
println(b)
println(a ++ b) //[3 2 1 6 5 4] good
println(a :: b) //[6 3 5 2 4 1] why???
}
我尝试连接两个 MyList,但问题是,
“++”和“::”逻辑相同
但是“++”将打印 [3 2 1 6 5 4],这是有道理的,而“::”将打印 [6 3 5 2 4 1]
来自2.13 language specifications(我好像找不到scala3版本,不过这部分没变):
Operators ending in a colon ‘:’ are
right-associative. All other operators are left-associative.
[...]
If op
is right-associative and its parameter is passed by name, the same operation is interpreted as e2.op(e1)
所以你的 a :: b
与 b.::(a)
相同,
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
是
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, list.::(next))
这解释了您得到的 [6 3 5 2 4 1]
。
您可以使用
得到您想要的结果
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next.::(list))
...
println(a.::(b))
abstract class MyList[+A] {
def head: A
def next: MyList[A]
def isEmpty: Boolean
def add[B >: A](element: B): MyList[B]
def printElements: String
override def toString: String = s"[$printElements]"
def ++[B >: A](list: MyList[B]): MyList[B]
def ::[B >: A](list: MyList[B]): MyList[B]
}
case object Empty extends MyList[Nothing] {
def head: Nothing = throw new NoSuchElementException
def next: MyList[Nothing] = throw new NoSuchElementException
def isEmpty: Boolean = true
def add[B >: Nothing](element: B): MyList[B] = Cons(element, Empty)
def printElements: String = ""
def ++[B >: Nothing](list: MyList[B]): MyList[B] = list
def ::[B >: Nothing](list: MyList[B]): MyList[B] = list
}
case class Cons[+A](h: A, t: MyList[A]) extends MyList[A] {
def this(h: A) = this(h, Empty)
def head: A = h
def next: MyList[A] = t
def isEmpty: Boolean = false
def add[B >: A](element: B): MyList[B] = Cons(element, this)
def printElements: String =
if (t.isEmpty) s"$h"
else s"$h ${t.printElements}"
def ++[B >: A](list: MyList[B]): MyList[B] = Cons(h, next ++ list)
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
}
object runTest extends App {
val a = Empty.add(1).add(2).add(3)
val b = Empty.add(4).add(5).add(6)
println(a)
println(b)
println(a ++ b) //[3 2 1 6 5 4] good
println(a :: b) //[6 3 5 2 4 1] why???
}
我尝试连接两个 MyList,但问题是, “++”和“::”逻辑相同 但是“++”将打印 [3 2 1 6 5 4],这是有道理的,而“::”将打印 [6 3 5 2 4 1]
来自2.13 language specifications(我好像找不到scala3版本,不过这部分没变):
Operators ending in a colon ‘:’ are right-associative. All other operators are left-associative.
[...]
If
op
is right-associative and its parameter is passed by name, the same operation is interpreted ase2.op(e1)
所以你的 a :: b
与 b.::(a)
相同,
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next :: list)
是
def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, list.::(next))
这解释了您得到的 [6 3 5 2 4 1]
。
您可以使用
得到您想要的结果def ::[B >: A](list: MyList[B]): MyList[B] = Cons(h, next.::(list))
...
println(a.::(b))