- 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/
我最近在我的机器上安装了 cx_Oracle 模块,以便连接到远程 Oracle 数据库服务器。 (我身边没有 Oracle 客户端)。 Python:版本 2.7 x86 Oracle:版本 11.
我想从 python timeit 模块检查打印以下内容需要多少时间,如何打印, import timeit x = [x for x in range(10000)] timeit.timeit("
我盯着 vs 代码编辑器上的 java 脚本编码,当我尝试将外部模块包含到我的项目中时,代码编辑器提出了这样的建议 -->(文件是 CommonJS 模块;它可能会转换为 ES6 模块。 )..有什么
我有一个 Node 应用程序,我想在标准 ES6 模块格式中使用(即 "type": "module" in the package.json ,并始终使用 import 和 export)而不转译为
我正在学习将 BlueprintJS 合并到我的 React 网络应用程序中,并且在加载某些 CSS 模块时遇到了很多麻烦。 我已经安装了 npm install @blueprintjs/core和
我需要重构一堆具有这样的调用的文件 define(['module1','module2','module3' etc...], function(a, b, c etc...) { //bun
我是 Angular 的新手,正在学习各种教程(Codecademy、thinkster.io 等),并且已经看到了声明应用程序容器的两种方法。首先: var app = angular.module
我正在尝试将 OUnit 与 OCaml 一起使用。 单元代码源码(unit.ml)如下: open OUnit let empty_list = [] let list_a = [1;2;3] le
我在 Angular 1.x 应用程序中使用 webpack 和 ES6 模块。在我设置的 webpack.config 中: resolve: { alias: { 'angular':
internal/modules/cjs/loader.js:750 return process.dlopen(module, path.toNamespacedPath(filename));
在本教程中,您将借助示例了解 JavaScript 中的模块。 随着我们的程序变得越来越大,它可能包含许多行代码。您可以使用模块根据功能将代码分隔在单独的文件中,而不是将所有内容都放在一个文件
我想知道是否可以将此代码更改为仅调用 MyModule.RED 而不是 MyModule.COLORS.RED。我尝试将 mod 设置为变量来存储颜色,但似乎不起作用。难道是我方法不对? (funct
我有以下代码。它是一个 JavaScript 模块。 (function() { // Object var Cahootsy; Cahootsy = { hello:
关闭。这个问题是 opinion-based 。它目前不接受答案。 想要改进这个问题?更新问题,以便 editing this post 可以用事实和引文来回答它。 关闭 2 年前。 Improve
从用户的角度来看,一个模块能够通过 require 加载并返回一个 table,模块导出的接口都被定义在此 table 中(此 table 被作为一个 namespace)。所有的标准库都是模块。标
Ruby的模块非常类似类,除了: 模块不可以有实体 模块不可以有子类 模块由module...end定义. 实际上...模块的'模块类'是'类的类'这个类的父类.搞懂了吗?不懂?让我们继续看
我有一个脚本,它从 CLI 获取 3 个输入变量并将其分别插入到 3 个变量: GetOptions("old_path=s" => \$old_path, "var=s" =
我有一个简单的 python 包,其目录结构如下: wibble | |-----foo | |----ping.py | |-----bar | |----pong.py 简单的
这种语法会非常有用——这不起作用有什么原因吗?谢谢! module Foo = { let bar: string = "bar" }; let bar = Foo.bar; /* works *
我想运行一个命令: - name: install pip shell: "python {"changed": true, "cmd": "python <(curl https://boot
我是一名优秀的程序员,十分优秀!