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

Scala:为什么我不能用占位符正确过滤我的Int List?例如:myLis

发布时间:2020-12-16 09:09:23 所属栏目:安全 来源:网络整理
导读:我在 Scala中有一个与占位符语法相关的问题. 所以我有一个简单的数字列表: myList = List(13,24,10,35) 首先,我试着像这样过滤这个列表 myList.filter(_ = (_ % 5) == 0) 并且编译器抱怨因为它无法推断参数类型: error: missing parameter type for expand
我在 Scala中有一个与占位符语法相关的问题.
所以我有一个简单的数字列表:

myList = List(13,24,10,35)

首先,我试着像这样过滤这个列表

myList.filter(_ => (_ % 5) == 0)

并且编译器抱怨因为它无法推断参数类型:

error: missing parameter type for expanded function ((x$2) => x$2.$percent(5))

好吧,没问题:我为参数添加了一个类型

myList.filter(_:Int => _ % 5 == 0)

现在编译器给了我这个:

identifier expected but integer literal found.
       someNumbers.filter(_:Int => _ % 5 == 0)
                                       ^

你们知道为什么我有这个奇怪的错误吗?我真的不明白……

提前致谢,

解决方法

你不知道,但是这个:

identifier expected but integer literal found.
       someNumbers.filter(_:Int => _ % 5 == 0)
                                       ^

是一个很棒的错误!好吧,从某种意义上说,人们并不喜欢它,但是你几乎写出了语法上正确的东西,并且与你的意图完全不同.首先,让我们看一下有效代码的重写:

someNumbers.map(_: Int => _ <:< Any)

现在,您看到它与您编写的内容之间只有两个不同之处(直到错误位置):%替换为<:,而5替换为Any(编译器需要 - 标识符而不是数字) . 你可以编译并运行上面的代码,它会返回一些东西,所以让我们试着把它分解.首先,考虑以下两个陈述:

someNumbers.map(_ + 1)
someNumber.map(_) // does not compile

它们各自意味着略有不同,可以像这样重写:

someNumbers.map(x => x + 1)
x => someNumbers.map(x)

第一个编译是因为,在声明x参数时,编译器知道预期的类型.第二个不编译,因为在编译器看到x时,它不知道如何使用它.当然,这只是因为编译器已经重写了代码,但事实就是如此.

这里重要的是,当你添加:Int时,编译器开始尝试编译你编写的第二种方式.

你打算写的东西不是有效的代码.例如:

someNumbers.map(x => x + 1) // valid code
someNumbers.map((x: Int) => x + 1) // valid code
someNumbers.map(x : Int => x + 1) // "invalid" code

更确切地说,第三个例子是“无效的”,因为编译器不知道类型的结束位置!要了解原因,请查看此声明:

val f: Int => Int = x => x

这里我们有=>出现两次,但每次都有不同的含义!第一种情况,Int => Int,是Function1 [Int,Int]的语法糖.换句话说,=>在Int => Int是该类型的一部分.

在第二种情况下,x => x(粗略地)代表新的Function1 [Int,Int] {def apply(x:Int)= x}. =>在此代码中表示存在匿名函数,并将其参数与其主体分开.

现在我们可以理解编译器如何解释someNumbers.filter(_:Int => _%5 == 0).像这样:

someNumbers.filter(_: Int => _ % 5 == 0) // gets rewritten as
(x: Int => _ % 5 == 0) => someNumbers.filter(x)

意思是Int => _%5 == 0被认为是类型.我们已经看到了为什么=>不会阻止它,但错误只发生在5!这里和那里之间发生了什么?

首先,我将回到我的可编辑示例.它使用了一个不太清楚的Scala结构,并且经常看不到:中缀类型表示法.该示例可以重写如下:

someNumbers.map(_: Int => _ <:< Any)
someNumbers.map(_: Int => <:<[_,Any])

换句话说,就像2 * 2代表2.*(2)一样,Int Map String代表Map [Int,String].这就解释了为什么编译器没有停在% – 它认为它代表一种类型 – 但它仍然留给我们_.

然而,在这一点上,_的含义,特别是在改写形式中,不应该看起来很神秘:它是一种存在主义类型!更具体地说,它是通配符存在类型.整个事情可以像这样重写:

(x: Function1[Int,<:<[t,Any] forSome { type t }]) => someNumbers.map(x)

或者,没有任何语法糖(但在实现*略有不同):

new Function1[Function1[Int,Any] forSome { type t }],List[<:<[q,Any] forSome { type q }]] { 
  def apply(x) = someNumbers.map(x) 
}

现在,你不同意这几乎不能远离你想写的东西吗?

(编辑:李大同)

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

    推荐文章
      热点阅读