首页 > 解决方案 > 为什么直接绑定 `our &foo` 不起作用,但通过动态查找间接绑定呢?

问题描述

为什么在模块 TEST 之外调用时 r1 和 r2 之间存在差异?

module TEST {
    our &r1 := OUR::{'&r1'} := sub {
        say 'routine 1'
    }

    r1();            # routine 1

    our &r2 := sub {
        say 'routine 2'
    }

    r2();            # routine 2
}

import TEST;

say TEST::.keys;     # (&r1 &r2)

TEST::r1();          # routine 1
TEST::r2();          # Cannot invoke this object (REPR: Uninstantiable; Callable) ...

尝试在定义它的模块 TEST 之外运行子例程 r2 时出错。

标签: modulerakusubroutinerakudo

解决方案


TL;DR绑定到 anour是没有意义的。绑定到一个OUR::<&foo>是有效的。我喜欢命名事物...看来您发明了一种技术,我在此将其称为“@jakar 的双重绑定our”。

为什么直接绑定只在模块内部有效

在对他对早期 SO jnthn 的回答的评论中得出结论,我们可能会收到一条错误消息或警告,大意是:

绑定到our变量是毫无意义的使用our.

(他的意思是绑定只在模块内部起作用,而不是在外部,正如您所发现的那样。)

有一个古老且仍然悬而未决的问题在 BEGIN 时间绑定变量不会在运行时停留,该问题深入讨论了一般问题。

为什么动态查找在模块外工作

以核心命名空间开头的符号总是被导出,jnthn 指出:

stashes 总是开放的,可以插入符号。

因此,忽略模块符号的使用,您的代码正在执行以下操作:

module TEST {
    OUR::{'&r1'} := sub { say 'routine 1' }
    our &r2;
}

import TEST;

TEST::r1();          # routine 1
TEST::r2();          # Cannot invoke this object (REPR: Uninstantiable; Callable) ...

@jakar 的双重绑定our

如果一个人希望能够声明一个符号并在模块内部和外部使用它并坚持使用绑定,那么使用双重绑定声明它的技巧可能是最好的技术:

    our &r1 := OUR::{'&r1'} := sub { ... }
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^ works *outside* module
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ works *inside* module

我很好奇的一些事情:

  • 您是否能够确认任何可以通过绑定而不是分配来获得的显着的具体实际our优势?

  • 人们是否想解决“绑定到our变量毫无意义”的问题?如果是这样,他们会乐意使用@jakar 的双重绑定our吗?

  • 你的技术适用于所有的印记吗?(我希望如此,但将留给您探索这些方面。:))


推荐阅读