- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我经常阅读一些编程语言对模块的支持(“一流”)(OCaml,Scala,TypeScript [?]),并且最近偶然发现了这样的答案,即在Scala的显着特征中引用模块作为一流公民。
我以为我很清楚模块化编程的含义,但是在发生这些事件之后,我开始怀疑我的理解...
我认为模块没有什么特别的,只是某些充当微型库的类的实例。小型库代码进入一个类,该类的对象是模块。您可以将它们作为依赖项传递给需要该模块提供的服务的任何其他类,因此,任何体面的OOPL都具有一流的模块,但显然没有!
最佳答案
模块以及子例程是组织代码的一种方式。在开发程序时,我们将指令打包到子例程中,将子例程打包到结构中,将结构打包到包,库,程序集,框架,解决方案等中。因此,将其他所有内容放在一边,这只是一种组织代码的机制。
我们之所以使用所有这些机制,而不是仅仅线性地布置指令,根本原因是因为程序的复杂度相对于其大小呈非线性增长。换句话说,由每个都具有n
指令的m
片段构建的程序比从n*m
指令构建的程序更容易理解。当然,这并不总是正确的(否则,我们可以将程序分为任意部分并感到满意)。实际上,要做到这一点,我们必须引入一种称为抽象的基本机制。仅当每个部分都提供某种抽象时,我们才能从将程序拆分为可管理的子部分中受益。例如,我们可以将connect_to_database
,query_for_students
,sort_by_grade
和take_the_first_n
抽象打包为函数或子例程,并且更容易理解用这些抽象表示的代码,而不是试图去理解所有这些抽象的代码。内联函数。
因此,现在我们有了功能,很自然地引入了下一个组织层次-功能集合。经常看到一些函数围绕某个通用抽象构建族,例如student_name
,student_grade
和student_courses
等,它们都围绕着相同的抽象student
旋转。 connection_establish
,connection_close
等也是如此。因此,我们需要将这些功能结合在一起的某种机制。在这里,我们开始有选择。某些语言采用OOP路径,其中对象和类是组织的单位。一堆函数和一个状态称为对象。其他语言则采取了不同的方法,并决定将功能组合到称为模块的静态结构中。主要区别在于模块是静态的编译时结构,其中对象是必须在运行时中创建才能使用的运行时结构。结果,自然地,对象倾向于包含状态,而模块则不包含状态(仅包含代码)。对象本身就是常规值,您可以将其分配给变量,将其存储在文件中,以及进行其他可以处理数据的操作。与对象相反,经典模块没有运行时表示形式,因此您不能将模块作为参数传递给函数,也不能将它们存储在列表中,否则不能对模块执行任何计算。这基本上就是人们所说的头等公民的意思-一种将实体视为简单值(value)的能力。
返回可组合程序。为了使对象/模块可组合,我们需要确保它们创建了抽象。对于函数,抽象边界已明确定义-它是参数的元组。对于对象,我们有接口(interface)和类的概念。而对于模块,我们只有接口(interface)。由于模块本来就更简单(它们不包含状态),所以我们不必处理它们的构造和反构造,因此我们不需要类的更复杂的概念。类和接口(interface)都是通过某种标准对对象和模块进行分类的一种方法,因此我们无需研究实现即可推理出不同的模块,就像对connect_to_database
,query_for_students
等函数进行的操作一样-我们仅对它们进行推理基于它们的名称和界面(可能还有文档)。现在,我们可以拥有一个student
类或一个Student
模块,它们都定义了一个称为Student的抽象,因此我们可以节省很多脑力,而不必处理这些学生的实现方式。
除了使我们的程序更易于理解之外,抽象还为我们带来了另一个好处-泛化。由于我们不需要推理功能或模块的实现,因此这意味着所有实现在某种程度上都是可以互换的。因此,我们可以编写程序,以便它们能以一般方式表达其行为,而不会破坏抽象,然后在运行程序时选择特定的实例。对象是运行时实例,从本质上讲,它意味着我们可以选择运行时的实现。很好但是,类(class)很少是一等公民,因此我们必须发明不同的繁琐方法进行选择,例如Abstract Factory和Builder设计模式。对于模块而言,情况甚至更糟,因为它们本质上是编译时结构,因此我们必须在程序构建/准备时选择我们的实现。在现代世界中,这不是人们想要做的。
一流模块,是模块和对象的融合,它们为我们提供了两个世界的精华-易于推理的无状态结构,同时又是纯粹的一流公民,您可以可以存储在变量中,放入列表中,然后在运行时选择所需的实现。
说到OCaml,在引擎盖下,一流的模块只是功能的记录。在OCaml中,您甚至可以将状态添加到一流的模块中,从而几乎无法与对象区分开。这将我们带到了另一个主题-在现实世界中,对象与结构之间的分离还不是很清楚。例如,OCaml同时提供模块和对象,您可以将对象放入模块中,反之亦然。在C / C++中,我们具有编译单元,符号可见性,不透明的数据类型和头文件,它们可以进行某种模块化编程,并且具有结构和 namespace 。因此,有时很难说出区别。
因此,总结一下。模块是具有明确定义的接口(interface)的代码段,用于访问该代码。第一类模块是可以作为常规值进行操作的模块,例如,存储在数据结构中,分配变量并在运行时选择。
关于scala - “First Class”模块是什么(确切)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56575195/
我有一些 Scala 代码,它用两个不同版本的类型参数化函数做了一些漂亮的事情。我已经从我的应用程序中简化了很多,但最后我的代码充满了形式 w(f[Int],f[Double]) 的调用。哪里w()是
如果我在同一目录中有两个单独的未编译的 scala 文件: // hello.scala object hello { def world() = println("hello world") }
val schema = df.schema val x = df.flatMap(r => (0 until schema.length).map { idx => ((idx, r.g
环境: Play 2.3.0/Scala 2.11.1/IntelliJ 13.1 我使用 Typesafe Activator 1.2.1 用 Scala 2.11.1 创建一个新项目。项目创建好后
我只是想知道如何使用我自己的类扩展 Scala 控制台和“脚本”运行程序,以便我可以通过使用实际的 Scala 语言与其通信来实际使用我的代码?我应将 jar 放在哪里,以便无需临时配置即可从每个 S
我已经根据 README.md 文件安装了 ensime,但是,我在低级 ensime-server 缓冲区中出现以下错误: 信息: fatal error :scala.tools.nsc.Miss
我正在阅读《Scala 编程》一书。在书中,它说“一个函数文字被编译成一个类,当在运行时实例化时它是一个函数值”。并且它提到“函数值是对象,因此您可以根据需要将它们存储在变量中”。 所以我尝试检查函数
我有 hello world scala native 应用程序,想对此应用程序运行小型 scala 测试我使用通常的测试命令,但它抛出异常: NativeMain.scala object Nati
有few resources在网络上,在编写与代码模式匹配的 Scala 编译器插件方面很有指导意义,但这些对生成代码(构建符号树)没有帮助。我应该从哪里开始弄清楚如何做到这一点? (如果有比手动构建
我是 Scala 的新手。但是,我用 创建了一个中等大小的程序。斯卡拉 2.9.0 .现在我想使用一个仅适用于 的开源库斯卡拉 2.7.7 . 是吗可能 在我的 Scala 2.9.0 程序中使用这个
有没有办法在 Scala 2.11 中使用 scala-pickling? 我在 sonatype 存储库中尝试了唯一的 scala-pickling_2.11 工件,但它似乎不起作用。我收到消息:
这与命令行编译器选项无关。如何以编程方式获取代码内的 Scala 版本? 或者,Eclipse Scala 插件 v2 在哪里存储 scalac 的路径? 最佳答案 这无需访问 scala-compi
我正在阅读《Scala 编程》一书,并在第 6 章中的类 Rational 实现中遇到了一些问题。 这是我的 Rational 类的初始版本(基于本书) class Rational(numerato
我是 Scala 新手,我正在尝试开发一个使用自定义库的小项目。我在库内创建了一个mysql连接池。这是我的库的build.sbt organization := "com.learn" name :
我正在尝试运行一些 Scala 代码,只是暂时打印出“Hello”,但我希望在 SBT 项目中编译 Scala 代码之前运行 Scala 代码。我发现在 build.sbt 中有以下工作。 compi
Here链接到 maven Scala 插件使用。但没有提到它使用的究竟是什么 Scala 版本。我创建了具有以下配置的 Maven Scala 项目: org.scala-tools
我对 Scala 还很陌生,请多多包涵。我有一堆包裹在一个大数组中的 future 。 future 已经完成了查看几 TB 数据的辛勤工作,在我的应用程序结束时,我想总结上述 future 的所有结
我有一个 scala 宏,它依赖于通过包含其位置的静态字符串指定的任意 xml 文件。 def myMacro(path: String) = macro myMacroImpl def myMacr
这是我的功能: def sumOfSquaresOfOdd(in: Seq[Int]): Int = { in.filter(_%2==1).map(_*_).reduce(_+_) } 为什么我
这个问题在这里已经有了答案: Calculating the difference between two Java date instances (45 个答案) 关闭 5 年前。 所以我有一个这
我是一名优秀的程序员,十分优秀!