具有重复参数(可变参数)的磁铁模式

2024-04-18

是否可以使用磁铁图案 http://spray.io/blog/2012-12-13-the-magnet-pattern/与可变参数:

object Values {
  implicit def fromInt (x : Int ) = Values()
  implicit def fromInts(xs: Int*) = Values()
}
case class Values()

object Foo {  
  def bar(values: Values) {}
}

Foo.bar(0)
Foo.bar(1,2,3) // ! "error: too many arguments for method bar: (values: Values)Unit"

?


正如 gourlaysama 已经提到的,将 varargs 变成单个Product从语法上来说,就可以解决这个问题:

implicit def fromInts(t: Product) = Values()

这使得以下调用可以正常编译:

Foo.bar(1,2,3)

这是因为编译器自动将 3 个参数提升为Tuple3[Int, Int, Int]。这适用于任意数量的参数,最多可达 22 个。现在的问题是如何使其类型安全。因为它是Product.productIterator是在方法体内取回参数列表的唯一方法,但它返回一个Iterator[Any]。我们不能保证该方法只会被调用Ints。这应该不足为奇,因为我们实际上从未在签名中提到我们只想要Ints.

好的,所以无约束之间的主要区别Product可变参数列表的特点是在后一种情况下每个元素都具有相同的类型。我们可以使用类型类对其进行编码:

abstract sealed class IsVarArgsOf[P, E]
object IsVarArgsOf {
  implicit def Tuple2[E]: IsVarArgsOf[(E, E), E] = null
  implicit def Tuple3[E]: IsVarArgsOf[(E, E, E), E] = null
  implicit def Tuple4[E]: IsVarArgsOf[(E, E, E, E), E] = null
  implicit def Tuple5[E]: IsVarArgsOf[(E, E, E, E, E), E] = null
  implicit def Tuple6[E]: IsVarArgsOf[(E, E, E, E, E), E] = null
  // ... and so on... yes this is verbose, but can be done once for all
}

implicit class RichProduct[P]( val product: P )  {
  def args[E]( implicit evidence: P IsVarArgsOf E ): Iterator[E] = {
    // NOTE: by construction, those casts are safe and cannot fail
    product.asInstanceOf[Product].productIterator.asInstanceOf[Iterator[E]]
  }
}

case class Values( xs: Seq[Int] )
object Values {
  implicit def fromInt( x : Int ) = Values( Seq( x ) )
  implicit def fromInts[P]( xs: P )( implicit evidence: P IsVarArgsOf Int ) = Values( xs.args.toSeq )
}


object Foo {  
  def bar(values: Values) {}
}

Foo.bar(0)
Foo.bar(1,2,3)

我们改变了方法签名形式

implicit def fromInts(t: Product)

to:

implicit def fromInts[P]( xs: P )( implicit evidence: P IsVarArgsOf Int )

在方法体内,我们使用新方法args获取我们的 arg 列表。

请注意,如果我们尝试调用bar与一个不是元组的元组Ints,我们将得到一个编译错误,这使我们恢复了类型安全。


UPDATE:正如 0__ 所指出的,我的上述解决方案不能很好地适应数字加宽。换句话说,以下内容无法编译,尽管如果bar只需要 3Int参数:

Foo.bar(1:Short,2:Short,3:Short)
Foo.bar(1:Short,2:Byte,3:Int)

为了解决这个问题,我们需要做的就是修改IsVarArgsOf这样所有的隐式都允许 元组元素可转换为通用类型,而不是全部为同一类型:

abstract sealed class IsVarArgsOf[P, E]
object IsVarArgsOf {
  implicit def Tuple2[E,X1<%E,X2<%E]: IsVarArgsOf[(X1, X2), E] = null
  implicit def Tuple3[E,X1<%E,X2<%E,X3<%E]: IsVarArgsOf[(X1, X2, X3), E] = null
  implicit def Tuple4[E,X1<%E,X2<%E,X3<%E,X4<%E]: IsVarArgsOf[(X1, X2, X3, X4), E] = null
  // ... and so on ...
}

好吧,实际上我撒谎了,我们还没有结束。因为我们现在接受不同类型的元素(只要它们可以转换为通用类型,我们就不能将它们强制转换为预期类型(这会导致运行时强制转换错误),而是必须应用隐式转换。我们可以这样修改它:

abstract sealed class IsVarArgsOf[P, E] {
  def args( p: P ): Iterator[E]
}; object IsVarArgsOf {
  implicit def Tuple2[E,X1<%E,X2<%E] = new IsVarArgsOf[(X1, X2), E]{
    def args( p: (X1, X2) ) = Iterator[E](p._1, p._2)
  }
  implicit def Tuple3[E,X1<%E,X2<%E,X3<%E] = new IsVarArgsOf[(X1, X2, X3), E]{
    def args( p: (X1, X2, X3) ) = Iterator[E](p._1, p._2, p._3)
  }
  implicit def Tuple4[E,X1<%E,X2<%E,X3<%E,X4<%E] = new IsVarArgsOf[(X1, X2, X3, X4), E]{
    def args( p: (X1, X2, X3, X4) ) = Iterator[E](p._1, p._2, p._3, p._4)
  }
  // ... and so on ...
}
implicit class RichProduct[P]( val product: P ) {
  def args[E]( implicit isVarArg: P IsVarArgsOf E ): Iterator[E] = {
    isVarArg.args( product )
  }
}

这解决了数字加宽的问题,并且在混合不相关类型时我们仍然得到编译:

scala> Foo.bar(1,2,"three")
<console>:22: error: too many arguments for method bar: (values: Values)Unit
          Foo.bar(1,2,"three")
                 ^
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有重复参数(可变参数)的磁铁模式 的相关文章

  • 写入 Delta 表时检测到架构不匹配 - Azure Databricks

    我尝试将 small radio json json 加载到 Delta Lake 表 在此代码之后我将创建表 我尝试创建 Delta 表 但收到错误 写入 Delta 表时检测到架构不匹配 可能与分区有关events write form
  • Scala 2.10、Double.isNaN 和拳击

    在 Scala 2 10 中 是someDouble isNaN预计装箱 运行我的代码调用 isNaN通过反编译器 我仍然看到对double2Double在我的代码中 鉴于新的AnyVal在 2 10 中工作 我希望它不会比java lan
  • 不使用 CPU 时 Cassandra 超时

    我使用 Phantom DSL 和 Datastax Cassandra 驱动程序时遇到 Cassandra 超时 然而 Cassandra 似乎并没有超载 以下是我得到的异常 com datastax driver core except
  • 如何在 Akka Stream 中记录流量?

    我有一个带有单个流 图的 Akka Stream 应用程序 我想测量源头的流量并每 5 秒记录一次 例如 在过去 5 秒内收到 3 条消息 我尝试过 someOtherFlow groupedWithin Integer MAX VALUE
  • scala.collection.breakOut 与视图

    这个答案 https stackoverflow com a 1716558 936869描述如何scala collection breakOut可用于防止创建浪费的中间集合 例如 这里我们创建一个中间体Seq String String
  • Spark:用列的平均值替换数据框中的空值

    如何创建 UDF 以编程方式将每列中 Spark 数据框中的空值替换为列平均值 例如 在示例中 数据 col1 空值的值为 2 4 6 8 5 5 5 示例数据 col1 col2 col3 2 null 3 4 3 3 6 5 null
  • Scala 组合器解析器 - 区分数字字符串和变量字符串

    我正在做 Cay Horstmann 的组合器解析器练习 我想知道区分代表数字的字符串和代表匹配语句中变量的字符串的最佳方法 def factor Parser ExprTree wholeNumber expr ident case a
  • 如何检查字符串中是否包含某个字符?

    我想检查字符串是否包含该字符 我正在编写一个刽子手代码 例如 下面是要猜测的单词 scala 但看起来像 至用户 假设用户输入字母 a 那么它一定看起来像 a a def checkGuess if result contains user
  • 了解如何使用 apply 和 unappy

    我试图更好地理解 的正确用法apply and unapply方法 考虑到我们想要序列化和反序列化的对象 这是正确的用法吗 即斯卡拉方式 的使用apply and unapply case class Foo object Foo appl
  • 哪些 ORM 与 Scala 配合得很好? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Spark RDD默认分区数

    版本 Spark 1 6 2 Scala 2 10 我正在执行以下命令spark shell 我试图查看 Spark 默认创建的分区数量 val rdd1 sc parallelize 1 to 10 println rdd1 getNum
  • 自定义 NIO 文件系统无法通过 SBT 的测试任务加载

    为了进行测试 我使用内存中的 NIOFileSystem执行 memoryfs https github com openCage memoryfs 我以前已经利用过它 并且它似乎运行良好 例如梅文 然而 现在 在SBT项目中 不可能初始化
  • 我想使用 EtherPad(或克隆版本)。我的站点正在运行 Ruby on Rails。 API 还是本地安装?

    我想在我的网站上使用 etherpad 界面 两个问题 1 是否有任何带有 etherpad api 的网站可以让我远程调用 2 如果没有 安装scala并让两者同时运行有多麻烦 Thanks 查看http piratepad net ht
  • 新式(“内联”)宏需要 scala.meta

    我刚刚更新到 scala meta 2 0 0 M1 和最新的 scala 2 12 3 现在宏不再编译 我所做的唯一更改是将元版本从 1 8 0 更改为 2 0 0 M1 错误 新式 内联 宏需要 scala meta 有谁知道是否有快速
  • 如何抑制spark输出控制台中的“Stage 2===>”?

    我有数据帧并试图获取不同的计数并且能够成功获取不同的计数 但是每当 scala 程序执行时我都会收到此消息 Stage 2 gt 1 1 2 我如何在控制台中抑制特定的此消息 val countID dataDF select substr
  • 如何捕获 Oozie Spark 输出

    有没有办法捕获spark的输出然后将其输入到shell上 我们当前正在使用 scala 创建 jar 文件 并希望我们的 Spark 输出成为 shell 输入 我的想法是使用 wf actionData spark XXXX var 我只
  • Java 表达式树 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否有相当于 net的 LINQ 下的表达式树JVM 我想实现一些类似 LINQ 的代码结构Scala
  • 缓存 Slick DBIO 操作

    我正在尝试加快 SELECT FROM WHERE name 的速度Play 中的查询类型 Scala 应用程序 我正在使用 Play 2 4 Scala 2 11 play slick 1 1 1 包 该软件包使用Slick 3 1版本
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht
  • 在 Scala 中,使用“_”和使用命名标识符有什么区别?

    为什么当我尝试使用时会出现错误 而不是使用命名标识符 scala gt res0 res25 List Int List 1 2 3 4 5 scala gt res0 map gt item toString

随机推荐

  • gdb 输入文件中的十六进制值

    我正在尝试通过使用 gdb 内的 run 我可以成功地溢出程序 但在将十六进制值附加到字符串时遇到问题 我尝试过引用 将 mem addr 的值转换为 ascii 以及各种转义尝试 但没有成功 输入文件示例 AAAA x42 在上面的示例中
  • 监控 REST API 的最佳方式是什么? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我创建了一个基于 RESTful 模式的 API 我想知道监视它的最佳方法是什么 我可以以某种方式收集每个请求的统计信息以及我可以监控
  • jsfiddle问题[重复]

    这个问题在这里已经有答案了 我无法让这个极其简单的 jsfiddle 工作 它只是应该在单击按钮时提醒测试 我在这里缺少什么 http jsfiddle net u9nG6 2 http jsfiddle net u9nG6 2 您必须将加
  • CSS 滤色器叠加

    我正在尝试在图像上创建颜色叠加层 就像在这个应用程序中一样 图像上的绿色叠加层 https i stack imgur com FdgdA png https i stack imgur com FdgdA png 对我来说 他们看起来并不
  • Word 2007 VBA:ActiveDocument.CustomXMLParts

    In 本教程 https learn microsoft com en us archive blogs erikaehrli data driven document generation with word 2007 and the o
  • 从 ViewPager 中删除由 FragmentStatePagerAdapter 填充的所有片段

    我有一个 ViewPager 我使用 FragmentStatePagerAdapter 填充片段 代表 arrayListOfObjects 中的对象 一切正常 mMyFragmentPagerAdapter new fragmentAd
  • 更少的 css 编译器。无法使用变暗属性

    我正在开发一个项目 使用 LESS 作为我的 CSS 编译器 我已经有一个完全工作的循环 可以正确设置背景颜色 我的问题是这样的 使用我当前的代码 当我尝试使用 darken 属性时 编译结果是这样的 SyntaxError 错误评估函数d
  • 我应该使用哪个功能接口?

    我正在学习编写一些 lambda 表示形式功能接口 https docs oracle com en java javase 11 docs api java base java lang FunctionalInterface html
  • UIView 的 viewDidLoad 吗?

    是什么viewDidLoad for UIView 我有一个UIView与 xib 一起 我想在加载时隐藏它的子视图之一 我尝试使用这个 id initWithCoder NSCoder aDecoder theView hidden YE
  • 使用 Json.NET 反序列化空数组

    我有一个使用 Json NET v7 0 1 的 C 应用程序 作为 REST 调用的结果 我以以下形式返回一些 JSON messages phoneNumber 123 456 7890 smsText abcd1234 phoneNu
  • 如何使用 Jquery 更改辅助样式表?

    我的网站上有我的 base css 和 red css 我喜欢在按下某个按钮时将 red css 更改为 blue css 而不丢失 base css 如何执行此操作 我试过这个
  • Dataframe 根据其他列创建新列

    我有一个数据框 df lt data frame a c 1 2 3 4 5 b c 1 20 3 4 50 df a b 1 1 1 2 2 20 3 3 3 4 4 4 5 5 50 我想根据现有列创建一个新列 像这样的事情 if df
  • for 语句后的大括号

    我是新手 编写一个代码来打印从 1 到 10 的数字之和 事情是这样的 for a 1 a lt 10 a sum a cout lt
  • excel函数“R中决策函数的搜索

    我有一个问题 R中是否可以实现excel函数 决策搜索 R中有没有函数或者需要在R中创建一个脚本 需要结合以下方程来求解X值得到 1 126 作为结果 1 126 X X 0 2 EXP X 0 2 1 您可以使用以下方法找到该方程的解un
  • .vimrc 控制键映射不起作用

    我的 vimrc 中有以下映射 用于映射控制键 1 2 3 用于切换选项卡 我在 ubuntu 11 10 中使用 gnome 终端 控制键映射似乎不起作用 谁能告诉我我做错了什么 VIM Vi 改进版 7 3 154 map
  • 如何在不关闭vim的情况下重置vim的设置(包括插件,.vimrc文件)?

    我已经使用 vim 两年了 我使用 pathogen 进行插件管理 我在寻找 一种在不关闭 vim 的情况下重置所有 vim 设置 包括插件 vimrc 文件 的方法 是 有什么想法吗 PS 在某些情况下 重新加载 vimrc 与重新打开
  • Android 在其他设备上共享显示

    我正在努力与通过 WiFi 连接的多个表 全部有根 共享平板电脑显示屏 我正在使用以下方法 全部在一个线程内 1 我截屏 Process sh Runtime getRuntime exec su null null OutputStrea
  • 涵盖 .NET 中的 TDD、DDD 和设计模式的书籍

    我想要一本能够真正让我全面了解使用 C TDD ASP NET MVC DDD 和设计模式 例如存储库模式 的现代 ASP NET 开发的书 我非常擅长 C 和 ASP NET MVC 但想填补空白 如果您对涵盖这些主题的一两本书有很好的体
  • 如何更改 graphviz 的默认字体大小?

    我使用 doxygen graphviz 来记录我的代码 graphviz 在生成图像方面做得很好 有什么方法可以更改 graphviz 的默认字体大小吗 默认值为 14 但我想使用 12 更改单个元素 例如节点 子图 边缘等 的字体大小确
  • 具有重复参数(可变参数)的磁铁模式

    是否可以使用磁铁图案 http spray io blog 2012 12 13 the magnet pattern 与可变参数 object Values implicit def fromInt x Int Values implic