美文网首页Raku Programming Language
你必须接受你所拥有的

你必须接受你所拥有的

作者: 焉知非鱼 | 来源:发表于2016-10-26 16:57 被阅读19次

有时你必须不择手段地得到一个东西。 如果它是一个文件,你可以使用 Jonathan Stowes 的 URI::FetchFile。 所述模块检查四个模块中的任何一个是否可用,并且采用第一个将 URI 保存为磁盘上的文件。 在他的代码中有一个有趣的触发了 ENODOC 的

$type = try require :: ($class-name);

这里 require 返回一个类型对象,该类型对象由模块声明,并且具有与该模块相同的名字。

检查 roast 这个巧妙的花招并把玩整个动态模块的魔法让我意识到,我们没有真正地在文档中覆盖这一点。 当我尝试处理一个 ENODOC 时我喜欢从一个可编译的例子开始。 这一次,我们需要两个文件

# M.pm6
unit module M;
class C is export { method m { 'method C::m' } };
class D is export { method m { 'method D::m' } };

# dynamic-modules.p6
use v6;
use lib '.';

subset C where ::('M::C');

my C $context = try { 
    CATCH { default { .note } };
    require ::('M');
    ::('M::C')
};

dd $context.HOW.^methods.elems;
dd $context.HOW.shortname($context);

通过 require 加载的任何符号在运行时将不可用。因此,我们不能进行静态类型检查。使用 subset 和动态查找,我们可以得到一个类型对象来检查。 where 从句将与类型对象进行智能匹配。由于动态查找很慢,所以像下面这样缓存类型对象可能是明智的:

subset C where $ //= ::('M::C');

where 会智能匹配给定的表达式,除非你用 *$_ 手动匹配。 给定的表达式本身不进行智能匹配,因此它将被求值。 由于 $ 是一个状态变量,它的初始化将只被执行一次(对于给定的thunk)。 所以我们最终得到一个状态变量 $,它填充了第一次使用subset时 ::('M::C') 后面的类型对象。 然后,针对该subset的每个约束检查,完成对该类型对象的智能匹配。

// 是 Defined-or 运算符。它返回第一个有定义的的操作数, 否则就返回最后的那个操作数。是短路运算符。

say Any // 0 // 42;   # 0
say Int // Mu // 42;  # 42
say Int // Mu // Str; # (Str)

Any 是类型对象(Type Object), 类型对象是未定义的(unfined)。如果你在类型对象上调用 .defined 方法, 它会返回 False
你可以用这种方法来找出一个对象到底是不是类型对象:

my $obj = Int; # Int 是类型对象
if $obj.defined {
    say "普通对象, 有定义的对象";
} else {
    say "类型对象";
}

而对于普通对象:

0.defined     # True
False.defined # True
True.defined  # True
"".defined    # True
[].defined    # True
().defined    # True

//= 是多余的,可以被一个简单的 = 替换,但它告诉读者,我期望 $ 是未定义的。 我使用定义或赋值语法,希望读者熟悉它。

> $a = Int  # $a 初始值是未定义的类型对象
(Int)
> $a //= 3  # 等价于 $a = $a // 3
3
> $a        # // 返回第一个有定义的操作数
3

现在我们得到一个类型约束来防止 require 不返回一个匹配我们期望的名称的类型。请注意,我们会检查名称,而不是类型或接口。如果您有机会设计动态加载的模块,您可能需要定义一个角色(甚至可能为空),这些角色必须由动态加载的类实现,以确保您可以真正调用所期望的方法。不只是具有相同名称的方法。

现在实际上我们可以按名字加载模块,并动态解析其中一个类,并从 try 块返回它。因为 M.pm6 定义了一个模块(如在 Perl6::Metamodel::ModuleHOW中)作为它的顶层包,我们不能简单地接受 require 的返回值,因为 Module 不是我们在 Perl 6 中最内省的东西。请注意,require 所加载的符号可在 try-block 外部通过动态查找获得。我不知道会发生什么如果你 go wild 并加载具有相同完全限定名的符号的模块。可能会有龙。

加载任何一组可能安装过也可能没有安装过的模块是一种相当普遍的情况,对我有限的知识,我们的生态系统中还没有那样一个模块。因此,我想挑战一下,写一个运行以下接口的模块。

sub load-any-module(*%module-name-to-adapter);
load-any-module({'Module::Name' => &Callable-adapter});

其中 Callable-adapter 提供了一个通用接口,将模块的 sub 或方法调用转换为用户代码需要的任何内容。有了这样的模块,Jonathan 可以将 URI::FetchFile 减少到 50 行代码。

相关文章

  • 你必须接受你所拥有的

    有时你必须不择手段地得到一个东西。 如果它是一个文件,你可以使用 Jonathan Stowes 的 URI::...

  • 无题

    你必须要努力 才对得起你所拥有的爱

  • 慧见!良善!法布施!

    慧见 良善 法布施 你只管善良 福报已在路上 [太阳][爱心][拥抱] 你只能给予你所拥有的[爱心] 珍惜我们所拥...

  • 《极简思维》整理你的人际关系

    不论你怎么比较,烦躁,思考,都不会改变此时此刻的你自己,你是谁,你的长相,你的成就,你所拥有的一切,就是你此刻所拥...

  • 你必须强迫自己接受应有的骄傲

    比起狂妄,我们其实更容易自卑。春风得意忘形时毕竟只是十之一二,大部分时候我们还是浸润在或浓或淡的痛感之中。启功先生...

  • 2018-09-25

    所有的破事都劈头盖脸的一拥而至,把你打的鼻青脸肿,你还必须心平气和的,对他温柔以待

  • 当下的力量

    当你尊重、认可并完全接受你当下的事实—无论你在哪儿,你是谁,现在你正在做什么—当你完全接受你所拥有的东西,你会对你...

  • 折腾

    有的人来了 有的人走了 这就是生活的真相 尽管心有波澜 但必须坦然接受这样的来来去去 有的人你爱 有的人你恨 明知...

  • 2020-09-27

    2020.927今日体验: 理解你所不能理解的是学习。接受你所不能接受的是成长。承认你所不能承认的是接纳。忘记你所...

  • 王开东谈教育

    真的教育必须是:你的心不再被恐惧占领,不再被理想、符号、词语所裹挟,你必须敞开你所有的心灵和毛孔,直接和世界肌肤接...

网友评论

    本文标题:你必须接受你所拥有的

    本文链接:https://www.haomeiwen.com/subject/vgzduttx.html