Elixir v1.11的ChangeLog

2020-09-12 17:54:12

PermalLink GitHub是5000多万开发人员的家园,他们一起工作,共同托管和审查代码、管理项目和构建软件。

报名。

在最近的版本中,Elixir团队一直专注于编译器,无论是在编译时捕获更多错误,还是在提高速度方面都是如此。ELEXIRV1.11在这两个方面都取得了很好的进展。此版本还包括许多其他优点,例如更紧密的Erlang集成、对更多保护表达式的支持、内置日期时间格式设置和其他日历增强。

在Elixir v1.10之后,我们进一步集成了Erlang的新日志记录器,添加了四个新的日志级别:通知、严重、警报和紧急,与syslog标准中的所有日志级别相匹配。Logger模块现在通过将映射和关键字列表传递给其各种功能来支持结构化日志记录。还可以通过Logger.put_module_level/2函数指定每个模块的日志级别。未来版本中将添加每个应用程序的日志级别。

IEX也得到了改进,可以直接从您的Elixir终端显示Erlang模块的文档。这可以与Erlang/OTP23+一起使用,并且要求已经使用文档块编译了Erlang模块。

Elixir v1.11构建在最近添加的编译跟踪程序之上,以跟踪应用程序边界。从本版本开始,如果您从现有模块调用函数,但此模块不属于您列出的任何依赖项,则Elixir将发出警告。

这两个条件看起来可能是矛盾的。毕竟,如果模块可用,那么它一定来自依赖项。在两种情况下并非如此:

Elixir和Erlang/OTP中的模块始终可用-即使它们的应用程序未明确列为依赖项

在伞形项目中,因为所有子应用程序都是在同一个VM中编译的,所以即使您不依赖于同级项目,也可能会有来自同级项目的模块可用。

这个新的编译器检查确保您调用的所有模块都作为依赖项的一部分列出,否则会发出如下警告:

:ssl.connect/2在application:ssl中定义,当前应用程序使用,但当前应用程序不直接依赖:ssl。要解决此问题,您必须执行以下操作之一:1.如果:SSL是Erlang/Elixir的一部分,则必须将其包含在您的Mix.exs 2中的:Extra_Applications Inside";def application";下面。如果:SSL是一个依赖项,请确保它列在您的Mix.exs 3中的";def deps";下面。如果您不想向:SSL添加要求,您可以选择添加[xref:

这在伞形项目中带来了额外的好处,因为它要求子应用程序显式列出它们的依赖项,完全拒绝兄弟项之间的循环依赖项。

在Elixirv1.11中,编译器还跨函数体跟踪结构和映射字段。例如,假设您想要编写以下代码:

如果:age字段有拼写错误或:age字段尚未定义,编译器将相应失败。但是,如果您编写了以下代码:

编译器不会捕获缺少的字段,并且只会在运行时引发错误。在1.11版中,Elixir将跟踪同一函数中所有map和struct字段的使用情况,并在上述情况下发出警告:

警告:表达式:#example.exs:7user.age`中未定义的字段`age`需要以下字段之一:name,address,where";user";在:#example.exs:7%user{}=userExample.exs:7:Check.drive?/1中被赋予类型%user{}=userConflict

编译器还检查二进制构造函数。考虑到您必须使用基于长度的编码通过线路发送字符串,其中字符串的前缀是其长度,最高可达4MBs。您的初始尝试可能如下所示:

但是,上面的代码有一个错误。除非另有说明,否则在<;<;>;>;之间给出的每个段必须是整数。对于Elixir v1.11,编译器会告诉您:

警告:不兼容的类型:表达式中的<;<;byte_size(string)::integer()-size(32),()!~INTEGER(),其中";String";在:#foo.exs:4<;<;byte_size(string)::integer()-size(32),String>;>;WHERE";String";中被赋予类型INTEGER()。在:#foo.exs:3IS_BINARY(字符串)中被赋予类型BINARY()提示:除非另有说明,否则假定给予二进制文件的所有表达式都是INTEGER()类型。例如,<;<;expr&>;>;假定";expr&34;是整数。传递修饰符,如<;<;expr::Float>;>;或<;<;expr::Binary>;>;以更改默认行为。foo.exs:4:Check.run_length/1处发现的冲突。

虽然其中一些警告可以由编译器自动修复,但未来的版本也将跨函数执行这些检查,并可能跨模块执行这些检查,在这些情况下,自动修复是不需要的(也是不可能的)。

Elixir v1.11对编译器跟踪文件依赖关系的方式进行了许多改进,这样,接触一个文件会导致重新编译的文件更少。在以前的版本中,Elixir跟踪三种类型的依赖关系:

编译时依赖关系-如果A在编译时(如使用宏)依赖于B,则每当B更改时,都会重新编译A。

结构依赖关系-如果A依赖于B';的结构,则每当B';的结构定义更改时,都会重新编译A。

但是,因为依赖关系是可传递的,所以如果A在编译时依赖于B,而B在运行时依赖于C,那么A将在编译时依赖于C。因此,减少编译时依赖项的数量非常重要。

Elixir v1.11将结构依赖项替换为";导出依赖项。换句话说,如果A依赖于B,则每当B public的接口改变时,A都会被重新编译。B的公共接口由它的结构定义以及它的所有公共函数和宏组成。

此更改允许我们将导入标记为导出依赖项,而不是编译时依赖项。这大大简化了依赖关系图。例如,在Hex.pm项目中,更改Elixir v1.10中的user.ex文件将发出以下代码:

为了让事情变得更好,Elixir v1.11还为路径依赖引入了更细粒度的文件跟踪。在以前的版本中,来自路径依赖项的模块始终被视为编译时依赖项。这通常意味着,如果您有一个伞形项目,更改应用程序将导致兄弟应用程序中的许多模块重新编译。幸运的是,如果合适的话,Elixirv1.11将把依赖项中的模块标记为导出,从而大大改进了那些使用路径依赖项的模块。

为了总结编译器增强的列表,现在Elixirv1.10中添加的--profile=time选项还包括编译每个单独文件的时间。例如,在Plug项目中,现在可以获得:

[PROFILE]lib/Plug/Conn.ex编译,耗时935ms[PROFILE]lib/Plug/ssl.ex编译,耗时147ms(加上744ms等待)[PROFILE]lib/Plug/static.ex编译,耗时238ms(加上654ms等待)[PROFILE]lib/Plug/CSRF_PROTECT.EX编译,耗时237ms(加上790ms等待)[PROFILE]lib/Plug/debugger.ex编译,耗时719ms(加上947ms等待)[PROFILE]编译完成。

在实现这些特性的同时,我们还使--长编译-阈值标志更加精确。在以前的版本中,--long-pilation-Threshold会同时考虑一个文件编译所花费的时间和等待其他文件所花费的时间。在Elixir v1.11中,它只考虑编译时间。这意味着较少的误报,并且您现在可以通过通过--long-编译-阈值2有效地获取编译时间超过2秒的所有文件。

为了使上一节中描述的编译器跟踪改进更具可见性,我们还添加了混合外部参照的新功能。混合外部参照是一项描述项目中文件之间的交互参考的任务。混合外部参照图子部分重点介绍它们之间的依存关系图。

首先,我们制作了现有的--LABEL标志来考虑传递依赖关系。使用--SINK文件和--LABEL COMPILE是一种强大的组合,可以在给定文件发生更改时找出哪些文件将更改。例如,在Hex.pm项目中,我们获得:

$MIX外部参照图形--接收库/hexpm/Accounts/user.ex--标签编译器库/hexpm/billing/hexpm.ex└──库/hexpm/billing/billing.ex(编译)库/hexpm/billing/local.ex└──库/hexpm/billing/billing.ex(编译)库/hexpm/emails/bambo.ex├──库/hexpm/account/email.。Hexpm_Web/Views/Email_View.ex(compile)lib/hexpm_web/controllers/api/docs_controller.ex└──库/hexpm_web/Controlders/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/key_controller.ex└──库/hexpm_web/Controlators/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/organization_controller.ex└──库/hexpm_web/Controller/auth_helpers.ex(编译)库/hexpm_。Web/controllers/api/organization_user_controller.ex└──lib/hexpm_web/Controlders/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/owner_controller.ex└──lib/hexpm_web/Controlders/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/package_controller.ex└──lib/hexpm_web/Controller/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/release_controller.ex└──lib/。Hexpm_Web/Controlders/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/repository_controller.ex└──库/hexpm_web/Controlders/auth_helpers.ex(compile)lib/hexpm_web/controllers/api/retirement_controller.ex└──库/hexpm_web/Controls/auth_helpers.ex(compile)lib/hexpm_web/controllers/blog_controller.ex└──库/hexpm_web/Views/blog_view.ex(编译)库/hexpm_web/。Exsession.ex├──库/hexpmWeb/Plug_parser.ex(编译)└──库/hexpmWeb/session.ex(编译)。

如果lib/hexpm/account/user.ex更改,根目录下的所有文件都将重新编译。他们的孩子描述了原因。例如,如果用户发生更改,repository_control er.ex文件将重新编译,因为它在编译时依赖于auth_helpers.ex,而auth_helpers.ex依赖于user.ex。这种间接的编译时间依赖通常是重新编译的来源,现在Elixir v1.11使发现它们变得微不足道,因此最终可以解决它们。

对混合外部参照图的另一个改进是增加了--格式循环,它将打印编译依赖图中的所有循环。如果您想要丢弃较短的周期,可以使用--min-cle-size标志。

ElixirV1.9引入了一个特定于版本的新配置文件,名为config/release ases.exs。发行版是包含Erlang VM、Elixir和您的应用程序的独立构件,可以在生产中运行。

Config/release ases.exs的添加非常有用,但不幸的是,它只适用于发行版。不使用发行版的开发人员必须使用config/config.exs文件,该文件通常在编译时过早加载。对于任何动态配置,开发人员都必须求助于第三方工具或变通方法来实现所需的结果。

Elixir v1.11通过引入名为config/runtime.exs的新配置文件来解决此问题。这个新的配置文件恰好在应用程序启动之前加载,此时代码已经完全编译。无论您使用的是MIX还是发行版,它都会在开发、测试和生产中加载。因此,它为Elixir中的运行时配置提供了统一的API。

Config/runtime.exs与任何其他配置文件的工作方式相同。但是,鉴于config/runtime.exs可以在混合或不混合的情况下运行,开发人员不能在config/runtime.exs中使用Mix.env()或Mix.target()。相反,它们必须使用已添加到Config模块的新config_env()和config_target()。

虽然将继续支持config/release ases.exs,但开发人员可以迁移到config/runtime.exs,而不会丢失功能。例如,如下所示的config/release ases.exs文件

可以作为config/runtime.exs按原样运行。但是,鉴于config/runtime.exs在所有环境中运行,您可能希望将部分配置限制为:Prod环境:

如果这两个文件都可用,版本将选择现在首选的config/runtime.exs,而不是config/release ases.exs。

总而言之,Mix还包括一个名为Mix app.config的新任务。此任务加载所有应用程序并对其进行配置,而不启动它们。每当您编写自己的混合任务时,通常都希望在运行自己的代码之前调用Mix app.start或Mix app.config。哪一个更好取决于您是要运行应用程序还是只希望配置应用程序。

ELIXIRV1.11添加了IS_STRUCT/2、IS_EXCEPTION/1和IS_EXCEPTION/2保护。它还在卫士中添加了对map.field语法的支持。

Calendar模块附带一个新的Calendar.strftime/3函数,该函数提供基于strftime格式的日期时间格式。日期模块获得了用于处理周和月的新函数,如Date.start_of_Month/1和Date.end_of_Week/2。最后,所有日历类型都具有与格里高利时间戳相互转换的函数,如Date.from_Gregorian_Days/2和NaveDateTime.to_Gregorian_Second/1。

Mix还包括两个新任务:Mix app.config(用于应用程序运行时配置)和Mix test.coverage(为伞形项目和跨流程划分的测试套件生成聚合覆盖报告)。

[日历]向日历模块添加线性整数表示法:Date.From_Gregorian_Days/2、Date.to_Gregorian_Days/1、NaveDateTime.From_Gregorian_Second/3、NaveDateTime.to_Gregorian_Second/1、Time.from_Second_After_午夜/1和Time.To_Second_After_午夜/1。

[代码]添加Code.can_AWAIT_MODULE_COMPILATION?/0检查并行编译器是否已启用,是否可以等待其他模块编译

[内核]如果未使用类似编译器变量的变量(如__MODULE__),则发出警告。

[Kernel.ParallelCompiler]提高:LONG_COMPILITY_THRESHOLD的精度,使其只考虑编译时间(而不考虑等待时间)。

[ExUnit]将@tag:tmp_dir支持添加到ExUnit。临时目录是在每次测试之前自动创建和删除的。

[MIX]允许通过@Requirements模块属性列出混合任务的要求。

[MIX COMPILE]支持关于MIX何时重新编译给定模块的自定义行为的__MIX_RECOMPILE__?/0回调。

[混合编译e.elixir]如果模块已更改但其公共接口相同,则将路径依赖项的模块标记为";导出依赖项。

[混合编译e.elixir]跟踪Elixir编译器中的应用程序边界。如果您从Erlang或Elixir标准库调用代码,并且不依赖正确的应用程序,则会发出警告。如果您从不依赖的伞形同级调用代码,也会发出警告-有效地禁止应用程序之间的循环依赖。

[混合版本]在交互模式下的Configuration下启动一个版本,然后切换到嵌入式模式(如果在Erlang/OTP 23+上运行)

[混合发布]添加REL_TEMPLATES_PATH配置模板文件的来源,如";env.sh.eex";,";vm.args.eex";和";overays";

[混合外部参照]默认情况下,使混合外部参照图形的--label选项可传递,并仅为直接从属关系添加--only--direct选项。

[混合外部参照]添加对混合外部参照图形的支持,以便同时使用--source和--ink。

[kernel]修复在Windows上elixirc不接受带反斜杠(\)分隔符的路径的问题。

[Kernel.SpecialForms]将|/2添加到特殊表单列表以避免重写行为不一致。

[IEx.Pry]确保从同一进程调用IEx.pry时可以触发两次以上。

[MIX COMPILE]修复了从伞形根运行MIX COMPILE时新协议实现不会传播的问题