加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala中的正确关联方法有什么好处?

发布时间:2020-12-16 09:46:02 所属栏目:安全 来源:网络整理
导读:我刚刚开始玩Scala,我刚刚了解了如何将方法做成正确的关联(而不是在命令式面向对象语言中常见的更传统的左组合)。 起初,当我看到Scala中列出的示例代码时,我注意到每个例子总是在右边列出: println(1 :: List(2,3,4))newList = 42 :: originalList 然而
我刚刚开始玩Scala,我刚刚了解了如何将方法做成正确的关联(而不是在命令式面向对象语言中常见的更传统的左组合)。

起初,当我看到Scala中列出的示例代码时,我注意到每个例子总是在右边列出:

println(1 :: List(2,3,4))
newList = 42 :: originalList

然而,即使看到这一遍又一遍,我也没有想过两次,因为我不知道(当时)::是List上的一种方法。我只是认为它是一个运算符(再次,在Java中的运算符的意义上),并且关联性没有关系。事实上,List总是出现在右边的例子代码中似乎是巧合的(我以为这可能只是“首选风格”)。

现在我知道更好:它必须以这种方式写成,因为::是正确的关联。

我的问题是,能够定义正确的关联方法是什么意思?

纯粹是为了美学的原因,还是在某些情况下,右组合实际上是否具有某种对左组合的好处?

从我的(新手)角度来看,我真的不明白

1 :: myList

比任何更好

myList :: 1

但这显然是一个微不足道的例子,我怀疑这是一个公平的比较。

解决方法

简单的答案是,正确的关联性可以通过使程序员类型与程序实际执行的程序类型一致来提高可读性。
所以,如果你输入’1 :: 2 :: 3’,你会得到一个List(1,2,3),而不是以完全不同的顺序获得List。
那是因为’1 :: 2 :: 3 :: Nil’实际上是

List[Int].3.prepend(2).prepend(1)

scala> 1 :: 2 :: 3:: Nil
res0: List[Int] = List(1,2,3)

这两个是:

>更可读
>更高效(O(1)为前缀,而O(n)为假设附加方法)

(提醒,从书Programming in Scala提取)
如果在运算符符号中使用一个方法,例如* b,则该方法将在左侧操作数中调用,如*。(b)所示,除非方法名以冒号结尾。
如果方法名称以冒号结尾,则该方法将在右侧操作数上调用。
因此,在1 :: twoThree中,:: method被调用在twoThree,传入1,像这样:twoThree.::(1)。

对于列表,它起到追加操作的作用(该列表似乎附加在’1’之后,以形成’1 2 3’,其中事实上它是前面列表的1)。
类列表不提供真正的追加操作,因为附加到列表所需的时间随列表的大小线性增长,而前缀为::需要不变的时间。
myList :: 1将尝试将myList的整个内容添加到’1’,这将比在myList中添加1更长(如’1 :: myList’)

注意:不管操作符的组合性如何,它的操作数都是
总是从左到右进行评估。
所以如果b是一个表达式,它不仅仅是对一个不可变值的简单引用,那么一个::: b更精确地被视为如下的块:

{ val x = a; b.:::(x) }

在这个块中,a仍然在b之前进行评估,然后是该评估的结果
作为操作数传递给b的:::方法。

why make the distinction between left-associative and right-associative methods at all?

这允许在实际应用正确表达式的操作时保持通常的左关联操作(‘1 :: myList’)的外观,因为;

它更有效率。
>但是它是更可读的反相关顺序(‘1 :: myList’与’myList.prepend(1)’)

就像你所说的,“语法糖”,据我所知。
注意,在foldLeft的情况下,例如,它们可能具有gone a little to far(具有’/:’右关联运算符等效)

要包括你的一些评论,稍微改写一下:

如果你考虑一个“附加”功能,左关联,那么你会写’oneTwo append 3 append 4 append 5’。
但是,如果要将3,4和5附加到一个(你将通过写入的方式假设),那将是O(N)。
与“::”相同,如果是“append”。但它不是。它实际上是“前置”

这意味着’a :: b :: Nil’用于’List []。b.prepend(a)’

如果’::’预先添加但仍保留左联,那么生成的列表将按顺序排列错误。
你会希望它返回List(1,2,3,4,5),但它最终会返回List(5,4,1,2),这对程序员来说可能是意想不到的。
那是因为,你所做的一切都是左列的顺序:

(1,2).prepend(3).prepend(4).prepend(5) : (5,2)

所以,正确的关联性使得代码与返回值的实际顺序相匹配。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读