scala 提供类似 C++ 模板的东西吗?

2024-05-15

我来自 C++,并试图了解 scala 的类型系统。

考虑以下 C++ 模板类:

template<class T>
class Point2
{
  Point2( T x, T y ) :
     x(x),
     y(y)
  {}

  T x;
  T y;
  Point2<T> operator+( Point<T> const& other ) const
  {
     return Point<T>(x+other.x, y+other.y);
  }
  T sumComponents() const { return x+y; }
}

Point2<Double> p0(12.3, 45.6) 
Point2<Double> p1(12.3, 45.6) 
Point2<Double> p = p1+p2
Double d = p1.sumComponents()

我发现我想写这样的东西:

case class Point2[ T ] (x:T, y:T) {
   def +() Point2[T]: = x+y
   def sumComponents() T: = x+y
}

或者,(因为编译有问题),

trait Addable[T] {   // Require T supports the + operatory
   def +( that:T ):T
}
case class Point2[ T<:Addable[T] ] (x:T, y:T) {
   def +() Point2[T]: = x+y
   def sumComponents() T: = x+y
}

这也有类似的问题,因为我不能要求 Double 来扩展 Addable。

一般来说,我发现 scala 的类型系统有一组我不太理解的约束。

在 scala 中实现上述内容的惯用方法是什么?

C++ 模板程序员了解 scala 中泛型的限制的正确方法是什么? (why我不能在scala中这样做吗?例如是因为泛型是在实例化之前编译的吗?)


在 scala 中实现上述内容的惯用方法是什么?

通过指定适当的要求T,或使用类型类来提供所需的行为。我稍后再谈这个。

C++模板程序员正确的理解方式是什么 scala 中泛型的限制? (为什么我不能在 scala 中执行此操作?例如 是因为泛型是在实例化之前编译的吗?)

C++ 模板在使用站点“处”进行编译,并且为模板参数的每个组合生成不同的代码。所以如果你使用上面的类int and double,你会得到两个不同的Point2类已编译。

基本上,C++ 模板是宏,尽管远没有那么愚蠢#define宏。事实上,C++ 模板是图灵完备的。也许将来有可能完成类似的事情,为 Scala 2.11 及更高版本计划即将推出的宏功能,但现在让我们忽略这一点。

类型参数(Scala 相当于 Javagenerics)不要改变代码的编译方式。参数化类在编译时生成其字节码,而不是在使用时生成。所以,当一个人实例化一个Point2 with Double,生成字节码已经太晚了。

这意味着参数化类生成的代码必须与类可以实例化的所有类型兼容.

这就是麻烦的根源:任何调用的方法T必须知道存在于T当时Point2已编译。所以,T必须定义为具有定义此类方法的特征或类的上限,如您在示例中所示。

当然,正如您正确指出的那样,这并不总是可能的,这就是类型类的用武之地。类型类是为其定义了一组行为的一组类型。在 Scala 中实现的类型类被定义为其实例定义其他类的行为的类。

在您给出的示例中,您将使用Numeric类型类,或者Fractional如果您还需要分数除法,请键入 class 。类型类使用的一个简单示例是:

scala> import scala.math.Numeric
import scala.math.Numeric

scala> def sum[T](x: T, y: T)(implicit num: Numeric[T]): T = num.plus(x, y)
sum: [T](x: T, y: T)(implicit num: scala.math.Numeric[T])T

或者,使用称为“上下文边界”的特殊符号,

scala> def sum[T : Numeric](x: T, y: T): T = implicitly[Numeric[T]].plus(x, y)
sum: [T](x: T, y: T)(implicit evidence$1: scala.math.Numeric[T])T

符号T : Numeric可以读作T这样就有一个隐式实例Numeric[T]可用的。代码implicitly[X]返回类型的隐式值X如果可以找到(或在编译时失败)。

现在,请注意没有方法被调用x and y-- 相反,我们调用方法num谁的班级是Numeric[T]。班上Numeric[T]有一个方法plus它知道如何添加两个Ts.

因为我们需要的是类型类实例,所以可以轻松添加新类型来满足类型类。人们可以很容易地声明一个Numeric类型类Point2(假设它的所有方法都可以实现):

class Point2Numeric[T](implicit num: Numeric[T]) extends Numeric[Point2[T]] {
  def plus(x: Point2[T], y: Point2[T]): Point2[T] = x + y
  // etc
}
implicit def ToPoint2Numeric[T : Numeric] = new Point2Numeric[T]

有了这个,那么对于任何T其中有一个Numeric[T],还会有一个Numeric[Point2[T]].

除了普通类型继承(类型上限)之外,类型类是 Scala 中最常见的类型约束形式。还有其他更复杂的形式,对于它们是类型类还是不同的东西(例如磁铁模式)存在一些讨论。看着无形的 https://github.com/milessabin/shapeless举个例子来说明人们可以在这些事情上走多远。

另一种类型约束曾经很常见,但现在使用得更加谨慎,它们是视图边界。我不会详细介绍(事实上,搜索上下文边界和视图边界以从我自己那里找到有关它的长答案),但它们可以用于使类型类在使用时更具可读性。例如:

scala> import scala.math.Numeric.Implicits._
import scala.math.Numeric.Implicits._

scala> def sum[T : Numeric](x: T, y: T): T = x + y
sum: [T](x: T, y: T)(implicit evidence$1: scala.math.Numeric[T])T

导入的定义包含隐式转换,可以使用类型的值T其中有一个Numeric[T]就好像他们自己有这样的方法+ or -.

最后一点,重要的是要认识到这会经历许多间接级别,因此可能不太适合高性能代码。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

scala 提供类似 C++ 模板的东西吗? 的相关文章

  • 从另一个命令 Handle() 方法中调用命令

    嗨 我正在使用简易注射器 https simpleinjector orgDI 库并一直在关注一些关于围绕命令模式设计的架构模型的非常有趣的材料 同时 在我的架构的命令方面 https cuttingedge it blogs steven
  • 多个源的 makefile

    在学习 make 文件时 我试图为多个源目录编写一个 make 文件 似乎我在某个地方错了 这是我的代码结构 directory common fun2 c inc fun h src fun1 c main c 这是我的生成文件 CC c
  • 添加 Nullable int 时保持 null?

    我想添加可为空的int 并保留null当所有值都是null 我想要这个结果 1 2 3 1 null 1 null null null O null 0 问题是 如果我将一个值与 null 相加 结果为 null int i1 1 int
  • 如何在另一个应用程序中挂钩 api 调用

    我正在尝试挂钩另一个应用程序的 ExtTextOut 和 DrawTextExt GDI 方法调用 我知道我需要使用 GetProcAddress 来查找 gdi32 dll 中那些方法的地址 并用我的函数的地址覆盖我想要挂钩的进程中的地址
  • 在 OnModelCreating 期间设置列名称

    Issue 我目前正在尝试通过设置的属性为我的表及其列添加前缀 我正在使用实体框架核心 我已经正确地为表名添加了前缀 但我似乎无法弄清楚列的前缀 我有一种感觉 我需要使用反射 我已经留下了我的 可能很糟糕的 反思尝试 有人有办法在实体中设置
  • 将完整模板参数值映射到原始类型

    我想将数字映射到类型 在这个例子中 我将创建一个函数 将 sizeof 结果映射到有符号的原始类型 我想知道是否有更好的方法来完成我在现代 C 中所做的事情 即采用模板化值并将其转换为类型 现在 这可以将大小转换为已知类型 但我似乎无法在标
  • 从代码中,如何创建对存储在附加属性中的对象的属性的绑定?

    我们有一个继承的附加属性来存储一个对象 在可视化树的更下方 我们希望从代码绑定到该对象的属性 通常我们像这样构建绑定的路径部分 var someBinding new Binding Path new PropertyPath Attach
  • C# 开源 NMEA 解析器 [已关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找 C 开源 NMEA 解析器 嗯 我自己也不熟悉 但是一些快速搜索显示了一个代码项目 htt
  • 如何在 Bean Validation 1.0 中构造 ConstraintViolationException?

    我对 javax validation API 感到困惑 我正在编写一个简单的测试来理解它 Sample sample new Sample Set
  • 获取 boost Spirit 语法中的当前行

    我正在尝试使用 boostspirit 获取正在解析的文件的当前行 我创建了一个语法类和结构来解析我的命令 我还想跟踪在哪一行找到命令并将其解析到我的结构中 我将 istream 文件迭代器包装在 multi pass 迭代器中 然后将其包
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 使用 C# 和 wpf 创建类似 Dock 的应用程序

    我需要创建一个与我们购买笔记本电脑时获得的应用程序类似的应用程序 仅当鼠标指针到达窗口顶部时它才可见 那么我怎样才能使用 C 4 0 来做到这一点呢 http www notebookcheck net uploads pics win2
  • 如何对 NServiceBus.Configure.WithWeb() 进行单元测试?

    我正在构建一个 WCF 服务 该服务接收外部 IP 上的请求并将其转换为通过 NServiceBus 发送的消息 我的单元测试之一调用Global Application Start 它执行应用程序的配置 然后尝试将 Web 服务解析为 验
  • 如何在三个 IEnumerable 上使用 Zip [重复]

    这个问题在这里已经有答案了 可能的重复 使用 Linq 从 3 个集合创建项目 https stackoverflow com questions 5284315 create items from 3 collections using
  • C#6 中的长字符串插值行

    我发现 虽然字符串插值在应用于现有代码库的字符串 Format 调用时非常好 但考虑到通常首选的列限制 字符串对于单行来说很快就会变得太长 特别是当被插值的表达式很复杂时 使用格式字符串 您将获得一个可以拆分为多行的变量列表 var str
  • 在 asp.net MVC 中使用活动目录进行身份验证

    我想使用活动目录对我的 asp net mvc 项目中的用户进行身份验证 在网上冲浪了几个小时后 我没有找到任何对我有用的东西 我已经看到了所有结果 但什么也没有 我尝试按照许多帖子的建议编辑我的 web config 如果有人可以帮助我提
  • 搜索实体的所有字段

    我正在尝试在客户数据库上实现 多功能框 类型的搜索 其中单个查询应尝试匹配客户的任何属性 这是一些示例数据来说明我想要实现的目标 FirstName LastName PhoneNumber ZipCode Mary Jane 12345
  • 如何使用 NPOI 按地址(A1、A2)获取 Excel 单元格值

    我有一个 Excel 单元格地址 例如 A1 A2 如何使用 C 中的 NPOI 框架以编程方式访问此单元格 我找到的一些 Java POI 示例代码 CellReference cr new CellReference A1 row my
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • Java:一个函数有多种返回类型...可以使用泛型吗?

    为了简单起见 我有一些程序 如下所示 public String fetchValueAsString String key public DateTime fetchValueAsDateTime String key 我想要类似的东西

随机推荐

  • 无法添加钥匙串项目。使用 KeychainItemWrapper 更改标识符后出现错误 - 25299?

    我想用 KeychainItemWrapper 将 UUID 保存在钥匙串中 所以我在中添加以下方法MyKeychainManager m define keychain idenentify com myapp bundle1 void
  • 使用 Java 的 Apache Http 摘要身份验证

    我目前正在开发一个 Java 项目 但无法使 http 摘要身份验证正常工作 我尝试使用 Apache 网站 但没有帮助 我有一个需要 HTTP 摘要身份验证的网站 DefaultHttpClient httpclient new Defa
  • 代表 Git 存储库的数学结构是什么

    我正在学习 Git 如果我能描述一下代表 Git 存储库的数学结构 那就太好了 例如 它是一个有向无环图 它的节点代表提交 它的节点有代表分支等的标签 每个节点最多一个标签 没有标签使用两次 我知道这个描述不正确 我只是想解释我正在寻找的内
  • 为什么 Application.Exit 无法工作?

    我有一个应用程序在取消对话框时出现奇怪的错误 如果该框被取消 应用程序将无法继续 因此它会退出 但由于某种原因它无法工作 因此它会继续运行并崩溃 我调试了这个问题 并且不知何故应用程序在 Application Exit 调用之后运行 我正
  • 视图无法解析为类型

    这里的视图似乎有什么问题 我该如何解决它 错误 视图无法解析为类型 public void onItemClick AdapterView
  • 在Android中使用RxJava2插入SQLiteDatabase

    我在学习RxJava2在安卓中 谁能解释一下我们如何使用将数据插入 SQLiteDatabaseRxJava2 这是我尝试使用的代码示例 但它将数据插入数据库六次 单击时 getCompletableObservable subscribe
  • Netbeans 8.1 Gnome 3 GTK+ UI 字体和选项卡高度

    我刚刚在运行 GNOME 3 桌面的 Ubuntu 16 04 上安装了 NetBeans 8 1 如果可能的话 我想继续使用 IDE 的 GTK 外观和感觉 但 UI 上的字体 尤其是选项卡中的字体 太小且重叠 我尝试添加 fontsiz
  • 有没有办法从主活动中调用另一个自定义适配器内项目的自定义适配器的notifyDataSetChanged()?

    我一直在尝试解决这个问题 但我还没有弄清楚 在我的布局中有一个带有自定义适配器的列表视图 在每个视图中 我都有许多对象存储在名为 ViewHolder 的静态类中 一个是带有另一个自定义适配器的画廊 我的问题是 在我的 Activity 上
  • 需要 RegEx 返回第一段或前 n 个单词

    我正在寻找一个正则表达式来返回段落中的前 n 个单词 或者如果该段落包含少于 n 个单词 则返回完整的段落 例如 假设我最多需要前 7 个单词 p one two p
  • Response.Redirect() 将绝对 URL 作为相对 URL 处理

    我有一个 net C 页面 它重定向到绝对 url 例如 Response Redirect rtsp myvideoServer com myVideoAddress mp4 ticket 1234 dt 1234 但重定向后会导致 ht
  • 在编译时构建类型列表 - 无 C++11

    我想做准确的this https stackoverflow com a 18704609 2566773获取类型 类的列表 但我不能使用 C 11 有什么建议如何将类型附加到模板列表吗 编辑 我想做的一些代码 include
  • 如何从 ui 和事件获取类/id

    如何从中获取任何元素的 id 和类名ui event任何函数 请参阅下文以获得清晰的理解 div div div div div div div div JS function drag class draggable drop class
  • 如何通过 JNI 将本机枚举公开给 Java?

    我正在从现有项目导入标头以将端口移植到 Android NDK 在某些情况下 我想在 Java 层使用本机标头中定义的枚举 怎样才能做到这一点呢 理想情况下 我想以某种方式将常量公开给 Java 层 但我没有找到这样做的方法 最明显的可能性
  • jquery float 条形图多系列

    为了使事情易于理解 我提供代码 http jsbin com otaruq http jsbin com otaruq 我们这里有一个像这样的数据集 查看源代码以获取更多信息 label scott data 1317427200000 1
  • ASP.NET Web API 依赖注入

    我想知道是否可以在 ASP NET Web API 中进行依赖项注入 自定义构造函数 而无需使用第三方库 例如 Unity 或 StructureMap 且无需实体框架 我想要实现的是拥有一个带有构造函数的控制器 例如 public Con
  • 如何获取进程的错误信息?

    For vsinstr coverage hello exe 我可以使用 C 代码如下 Process p new Process StringBuilder sb new StringBuilder COVERAGE sb Append
  • 使用 Javascript 从字符串中提取 url

    这听起来像是你可以用谷歌搜索的东西 但已经寻找了几个小时 基本上有这个字符串我从另一个网站ajax function onclick event toFacebook http www domain com au deal url test
  • 如何更改便携式 xamarin ios 项目中的启动屏幕?

    我正在使用便携式 xamarin 形式 其中项目是 IOS 项目 在 IOS 项目中 我想创建闪屏 我在 ios 项目属性中添加了 Iphone 启动图像和 iPad 启动图像 当我运行该应用程序时 它显示默认的启动屏幕 我还尝试从 inf
  • 是否以root 身份启动supervisord?

    Supervisor 运行在 3 0 上 pip freeze grep supervisor supervisor 3 0 从命令行启动supervisord时 sudo VIRTENV supervisord nodaemon conf
  • scala 提供类似 C++ 模板的东西吗?

    我来自 C 并试图了解 scala 的类型系统 考虑以下 C 模板类 template