首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >当您使用Seq(1,2,3)创建Seq对象时会发生什么?

当您使用Seq(1,2,3)创建Seq对象时会发生什么?
EN

Stack Overflow用户
提问于 2019-05-15 02:50:31
回答 2查看 1K关注 0票数 3

计算表达式时究竟发生了什么:Seq(1,2,3)

我是Scala的新手,现在对各种集合类型感到有点困惑。Seq是一种特质,对吗?所以,当你这样称呼它:Seq(1,2,3),它一定是某种伴生对象?还是不想?是某种扩展Seq的类吗?最重要的是,返回值的类型是什么?它是Seq吗?如果是,为什么不显式地使用扩展类呢?

在REPL中,我还看到计算表达式的内容实际上是一个List(1,2,3),但类型显然是Seq[Int]。为什么它不是IndexedSeq集合类型,比如Vector?这一切背后的逻辑是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-05-15 04:33:34

计算表达式时会发生什么情况:Seq(1,2,3)

在Scala中,foo(bar)foo.apply(bar)的语法糖,除非this也有一个名为foo的方法,在这种情况下,它是隐式this接收器上的方法调用,也就是说,就像Java一样,它相当于this.foo(bar)

就像任何其他OO语言一样,方法调用的接收方决定如何处理该调用,因此在本例中,Seq决定要做什么。

Seq是一种特质,对吗?

标准库中有两个Seq

所以,当你把它叫做Seq(1,2,3)时,它一定是某种伴生对象?还是不想?

是的,它必须是一个对象,因为您只能对对象调用方法。因此,当您看到一个方法调用时,它必须是一个对象。一直都是。因此,在这种情况下,Seq不可能是Seq特性,它必须是Seq对象。

请注意,“它必须是某种伴侣对象”不是真的。从这段代码中唯一能看到的就是Seq是一个对象。您无法从这段代码中知道它是否是一个伴生对象。为此,您必须查看源代码。在这种情况下,它实际上是一个伴生对象,但您不能从您展示的代码中得出结论。

是某种扩展了Seq的类吗?

不是的。它不可能是类,因为您只能对对象调用方法,而且类不是Scala中的对象。(这与Ruby或Smalltalk不同,其中类也是Class类的对象和实例。)它一定是个物体。

最重要的是,返回值的类型是什么?

找出这个问题的最简单的方法就是简单地查看Seq.apply文档

def apply[A](elems: A*): Seq[A] 使用指定的元素创建集合。

  • A:集合元素的类型
  • elems:创建的集合的元素
  • 返回一个包含元素elems的新集合。

因此,如您所见,Seq.apply的返回类型是Seq,或者更准确地说,是Seq[A],其中A是一个类型变量,表示集合中元素的类型。

它是Seq吗?如果是,为什么不显式地使用扩展类呢?

因为没有扩展类。

另外,Scala中的标准设计模式是同伴对象的apply方法返回同伴类或特征的实例。打破这个惯例会很奇怪也很令人惊讶。

在REPL中,我还看到计算表达式的内容实际上是一个列表(1,2,3),但类型显然是SeqInt。

静态类型是Seq[Int]。你只需要知道这些。这就是你所能知道的。

现在,Seq是一个trait,不能实例化特征,所以运行时类型将是Seq的某个子类。但!您不能也不应该关心它是什么特定的运行时类型。

为什么没有索引的集合类型,如向量?这一切背后的逻辑是什么?

您怎么知道下次调用它时它不会返回Vector?这一点也不重要,因为静态类型是Seq,因此只允许在它上调用Seq方法,并且只允许您依赖Seq的契约,即Seq的后条件、不变量等。即使您知道返回的是Vector,您也无法使用这些知识做任何事情。

因此,Seq.apply返回它可能返回的最简单的东西,即List

票数 8
EN

Stack Overflow用户

发布于 2019-05-15 03:57:28

Seq是以下的val

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package object scala {
...
  val Seq = scala.collection.Seq
...
}

它指向对象scala.collection.Seq

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/** $factoryInfo
 *  The current default implementation of a $Coll is a `List`.
 *  @define coll sequence
 *  @define Coll `Seq`
 */
object Seq extends SeqFactory[Seq] {
  /** $genericCanBuildFromInfo */
  implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Seq[A]] = ReusableCBF.asInstanceOf[GenericCanBuildFrom[A]]

  def newBuilder[A]: Builder[A, Seq[A]] = immutable.Seq.newBuilder[A]
}

当您执行Seq(1,2,3)时,apply()方法是从scala.collection.generic.GenericCompanion抽象类中提取的:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/** A template class for companion objects of "regular" collection classes
 *  represent an unconstrained higher-kinded type. Typically
 *  such classes inherit from trait `GenericTraversableTemplate`.
 *  @tparam  CC   The type constructor representing the collection class.
 *  @see [[scala.collection.generic.GenericTraversableTemplate]]
 *  @author Martin Odersky
 *  @since 2.8
 *  @define coll  collection
 *  @define Coll  `CC`
 */
abstract class GenericCompanion[+CC[X] <: GenTraversable[X]] {
...
  /** Creates a $coll with the specified elements.
   *  @tparam A      the type of the ${coll}'s elements
   *  @param elems  the elements of the created $coll
   *  @return a new $coll with elements `elems`
   */
  def apply[A](elems: A*): CC[A] = {
    if (elems.isEmpty) empty[A]
    else {
      val b = newBuilder[A]
      b ++= elems
      b.result()
    }
  }
}

最后,该方法通过上面提到的代码构建一个Seq类型的对象。

最重要的是,返回值的类型是什么?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
object MainClass {

  def main(args: Array[String]): Unit = {

    val isList = Seq(1,2,3).isInstanceOf[List[Int]]

    println(isList)
  }
}

指纹:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
true

所以,类型是scala.collection.immutable.List

在REPL中,我还看到计算表达式的内容实际上是一个列表(1,2,3),但类型显然是SeqInt。

根据上面提到的代码,Seq的默认实现是List

为什么没有索引的集合类型,如向量?这一切背后的逻辑是什么?

因为永恒的设计。该列表是不变的,使其不可变,并且具有一个恒定的前置操作,但是O(n)附加了操作成本和O(n)访问n‘’th元素的成本。Vector具有持续有效的访问实现,并通过id、prepend和append操作添加元素。

要更好地理解清单是如何在Scala中设计的,请参阅https://mauricio.github.io/2013/11/25/learning-scala-by-building-scala-lists.html

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56147577

复制
相关文章
无符号整型和有符号整型的区别,以及无符号整型的使用
size_t 等价于unsigned int 接收sizeof的返回值要用%u
大忽悠爱学习
2021/03/04
4.4K0
mysql无符号整型溢出
下午用sql的时候突然想到这个问题,徒手测试了一下,结果还真令人意外: 首先创建一张测试用表 mysql> CREATE TABLE `t1` ( -> `id` int UNSIGNED NOT NULL AUTO_INCREMENT , -> `val` int UNSIGNED NOT NULL DEFAULT 0 , -> PRIMARY KEY (`id`) -> ); Query OK, 0 rows affected (0.04 sec) 初始化一条数据: mysql> insert in
码农二狗
2018/06/29
2K0
PWN 无符号和有符号整型的绕过漏洞
C语言中,无符号整型数是不带正负表示符号的整型数。C语言在计算机里编译时数都是用二进制表示的,如果最左边这一位不用来表示正负,而是和后面的连在一起表示整数,那么就不能区分这个数是正还是负,就只能是正数,这就是无符号整型数。
yulate
2023/05/02
9660
PWN 无符号和有符号整型的绕过漏洞
FPGA设计中 有符号数、无符号数
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
1.7K0
FPGA设计中 有符号数、无符号数
itoa、atoi 整型转字符串、字符串转整型的函数[通俗易懂]
将value转换成radix进制数,在将其转换成字符串,写入string中,返回值是string的首地址,windows下才有该函数,可用作进制转换(sprintf函数也有类似功能)。
全栈程序员站长
2022/11/07
2K0
无符号数和有符号数
人有十个手指头,习惯了逢十进一,于是十进制成了生活中的标准。程序的世界只有高低电平两种状态,更适合用二进制来表示,于是二进制成了程序世界的标准。 对与无符号数来说,我们更喜欢谈他们之间的转化,十进制是我们最习惯的进制,于是十进制转为R进制,R进制转为十进制变尤为重要。
naget
2019/07/03
3.1K0
无符号数和有符号数
C++ 中有符号类型到无符号类型的转换
为了更好地解释下面的代码,先来介绍一些背景知识,在我的计算机中, char 类型占 8 个比特位,那么, unsigned char 类型能表示的数的范围为 0 ~ 2的8次方 - 1,即 0 ~ 255,共 256 个数;int 类型占 32 个比特位,那么 unsigned 类型所能表示的数的范围为 0 ~ 2的32次方 - 1,即 0 ~ 4294967295,共 4294967296 个数,接下来看下面的代码:
用户7886150
2021/02/15
1.4K0
为什么C++短整型溢出了还可以比较!
复习C++的时候,看到一段通过比较两个short变量之和与2^15大小来判定是否溢出的代码,惊到我了,两个short相加都超过short取值范围了,还能和最大取值范围比较???
gojam
2019/05/14
1.1K0
C++核心准则ES.106:不要试图通过使用无符号类型避免负值
Choosing unsigned implies many changes to the usual behavior of integers, including modulo arithmetic, can suppress warnings related to overflow, and opens the door for errors related to signed/unsigned mixes. Using unsigned doesn't actually eliminate the possibility of negative values.
面向对象思考
2020/06/24
8080
EasyC++04,C++中的整型
今天是EasyC++系列第四篇,我们来聊聊C++中的整型。想要更好观看体验的同学可以点击「阅读原文」访问github仓库。
TechFlow-承志
2022/08/26
3960
移位运算(无符号移位运算,有符号移位运算)
可以移位运算的类型有:iuint,int,lang等类型.我们本次使用int类型 一个int类型占4个字节,共32位,带符号位,所以最高位位符号位(使用0,1表示符号位)
全栈程序员站长
2022/09/14
1.4K0
深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
IT可乐
2018/01/04
1.8K0
深入理解计算机系统(2.5)------C语言中的有符号数和无符号数以及扩展和截断数字
c语言字符串转换为整型_c语言输出负数用什么
注意:整型变量与字符变量相加减是使用ASCII码值,可以通过类型转换或格式字符来控制打印。
全栈程序员站长
2022/11/02
2.2K0
【C语言进阶】整型在内存中的存储
 在日常敲代码的过程中,我们经常会使用整型常量来对变量进行赋值,但我们可能却没有考虑过不同的变量到底是如何存入内存中!今天俺来和大家一起探究一下其中的奥秘。
The sky
2023/04/12
9470
【C语言进阶】整型在内存中的存储
mysql整型转字符串_java中如何将字符串转换为字符数组
select * from A order by cast(name as unsigned);
全栈程序员站长
2022/09/27
23.3K0
java整型转换成字符串_java整型转换成字符串
二、 实验要求 1、编写一个 Java 程序,在程序中进行字符串与数值型数据的转换。 2、编写一个 Java 程序,在程序中通过键盘输入常用的数据,包括字符串、 整数和……
全栈程序员站长
2022/11/02
6.4K0
【C语言笔记】关于有符号数与无符号数的一些总结
原因是因为编译器会将有符号数b转换成为一个无符号数,即此处a+b等价于a+(unsigned int)b。
正念君
2019/06/26
4K0
【C语言笔记】关于有符号数与无符号数的一些总结
C算法实现:将字符串中的数字返回为整型数
今天看linux内核驱动的代码,发现一个算法写得挺简单,也有意思。 分享一下我的测试代码: #include <stdio.h> typedef int U32 ; U32 String2Dec( const char *pstr ) { char ch; U32 value; value = 0; //从字符串的第一个字符遍历到'\0' while( *pstr != '\0' ) { //获取字符
zy010101
2019/05/25
1.8K0
a为整型数组,&a+1的含义
#include <stdio.h> int main() { int a[10]; printf("a的值为:\t%d\n",a); printf("&a的值为:\t%d\n",&a); printf("a+1的值为:\t%d\n",a+1); printf("&a+1的值为:\t%d\n",&a+1); /**把int a[10]变下形,为:int *(&a)[10],这样就可以直观的看出 来,&a就相当于指向一个int [10]类
谙忆
2021/01/20
5500
a为整型数组,&a+1的含义
C++ 动态捕获整型数列
本文介绍了C++动态捕获整型数列,包括数组和动态数组的使用方法,以及使用动态数组和vector存储大量数字的示例。
chaibubble
2018/01/02
6300

相似问题

npm错误!enoent ENOENT:没有这样的文件或目录,chmod

144

SailsJS 0.11: ENOENT:没有这样的文件或目录,stat‘./node_modules/..bin/cdl’

43

Composer "chmod():没有这样的文件或目录“,带有bin目录

10

npm错误!enoent ENOENT:没有这样的文件或目录

1156

enoent ENOENT:没有这样的文件或目录,

31
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文