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

Scala函数在列表中丢失变量类型?

发布时间:2020-12-16 09:08:03 所属栏目:安全 来源:网络整理
导读:背景: 我试图通过动态创建/组合Scala中的匿名函数的部分函数(case …)来减少代码并改进Akka中的代码重用. 要创建这些部分函数,??我需要访问函数的参数类型(使用类型参数T),但遗憾的是这受到类型擦除的影响. 我发现使用TypeTags或TypeClasses我可以处理它,这
背景:

我试图通过动态创建/组合Scala中的匿名函数的部分函数(case …)来减少代码并改进Akka中的代码重用.

要创建这些部分函数,??我需要访问函数的参数类型(使用类型参数T),但遗憾的是这受到类型擦除的影响.

我发现使用TypeTags或TypeClasses我可以处理它,这很好.但是,我不是一次一个地将我的函数转换为部分函数,??而是想使用.map()批量执行此操作.

然而,这似乎是失败的;当通过地图使用该功能时,似乎T突然变为Nothing,导致我的功能功能失常(没有双关语意).

TL; DR:我可以得到lst(0)给String吗?

import scala.reflect.ClassTag
def fn = (s: String) => {}
def check[T](fn: T => Unit)(implicit ct: ClassTag[T]) = ct
check(fn)
//scala.reflect.ClassTag[String] = java.lang.String
val lst = List(fn).map(check)
lst(0)
//scala.reflect.ClassTag[Nothing] = Nothing

对于Akka好奇,我的实际功能有问题,而不是上面的check():

def caseFn[T](fn: T => Unit)(implicit ct: ClassTag[T]): Actor.Receive = {
  case ct(msg: T) => {
    fn(msg)
  }
}

解决方法

你可以通过改变来使它工作

val lst = List(fn).map(check)

val lst = List(fn).map(check(_))

这里发生了什么?

在map(check)的情况下,Scala执行所谓的eta-expansion将方法(check)转换为函数,参见Scala Language Specification Version 2.9的6.26.5:

6.26.5 Eta Expansion

Eta-expansion converts an expression of method type to an equivalent expression of function type. It proceeds in two steps. First,one identifies the maximal sub-expressions of e; let’s say these are e_1,…,e_m. For each of these,one creates a fresh name x_i. Let e’ be the expression resulting from replacing every maximal subexpression e_i in e by the corresponding fresh name x_i. Second,one creates a fresh name y_i for every argument type T_i of the method (i=1,…n). The result of eta-conversion is then:

06002

所以在map(check)中,Scala执行eta-expansion并且必须推断泛型方法检查的类型(在eta-expansion期间生成).由于Scala中类型推断的限制,它将推断Nothing而不是String,因此第一个版本不起作用,而第二个版本不起作用.

(编辑:李大同)

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

    推荐文章
      热点阅读