小编cod*_*ons的帖子

为什么非执行编译时代码会增加 Raku 的字节码大小?它会降低运行时性能吗?

考虑以下两个程序:

unit module Comp;
say 'Hello, world!'
Run Code Online (Sandbox Code Playgroud)

unit module Comp;
CHECK { if $*DISTRO.is-win { say 'compiling on Windows' }}
say 'Hello, world!'
Run Code Online (Sandbox Code Playgroud)

天真地,我希望两个程序编译成完全相同的字节码:CHECK块指定在编译结束时运行的代码;检查一个变量然后什么都不做对程序的运行时行为没有影响,因此(我原以为)不需要包含在编译的字节码中。

然而,编译这两个方案并没有产生相同的字节码。具体来说,编译没有CHECK块的版本会创建 24K 的字节码,而带有它的版本则是 60K。为什么这两个版本的字节码不同?字节码中的这种差异是否具有(或可能具有)运行时成本?(似乎必须如此,但我想确定一下)。

还有一个相关的问题:DOC CHECK块如何与上述内容相适应?我的理解是,即使编译器DOC CHECK在不使用--doc标志运行时也会跳过块。与此一致,当给定一个像上面那样的块时,hello-world 程序的字节码不会增加大小DOC CHECK。但是,如果块包含语句,它的大小确实会增加use。由此,我得出结论,这use是某种特殊情况,即使在DOC CHECK块中也能执行。那是对的吗?如果是这样,还有其他类似的特殊形式我应该知道吗?

bytecode compilation rakudo raku

7
推荐指数
1
解决办法
128
查看次数

是否可以在运行时内省标量的范围?

如果我有以下变量

my $a    = 0;
my $*b   = 1;
state $c = 2;
our $d   = 3;
Run Code Online (Sandbox Code Playgroud)

我可以很容易地确定这$*b是动态的,但$a不是下面的代码

say $a.VAR.dynamic;
say $*b.VAR.dynamic;
Run Code Online (Sandbox Code Playgroud)

有什么方法可以类似地确定它$c是状态变量$d还是包范围的变量?(我知道我可以用will每个变量声明的特征来做到这一点,但我希望有一种不需要注释每个声明的方法。也许有 ::(...) 插值?)

introspection rakudo raku

7
推荐指数
3
解决办法
106
查看次数

环视正则表达式和字符消耗

基于为乐的文档上环视断言,我读的正则表达式/ <?[abc]> <alpha> /的话说,“从左边,比赛开始,但不不消耗一个字符是abc和,一旦你找到了一个匹配,匹配和使用一个字母字符。 ”

因此,这个输出是有道理的:

'abc' ~~ / <?[abc]> <alpha> /     # OUTPUT: «?a?? alpha => ?a?»
Run Code Online (Sandbox Code Playgroud)

尽管该正则表达式有两个单字符术语,但其中一个没有捕获,因此我们的总捕获只有一个字符长。

但下一个表达让我感到困惑:

'abc' ~~ / <?[abc\s]> <alpha> /     # OUTPUT: «?ab?? alpha => ?b?»
Run Code Online (Sandbox Code Playgroud)

现在,我们的总捕获长度为两个字符,其中之一未被<alpha>. 那么环视到底是不是捕捉到了一些东西?还是我对环视的工作方式有其他误解?

regex rakudo regex-lookarounds raku

7
推荐指数
1
解决办法
71
查看次数

函数调用内的优先级

使用定义的或运算符(// ) 会产生我期望的结果:

\n
say( \'nan\'.Int // 42); # OUTPUT: \xc2\xab42\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

然而,使用较低优先级orelse运算符会引发错误:

\n
say( \'nan\'.Int orelse 42); \n# OUTPUT: \xc2\xabError: Unable to parse expression in argument list; \n#                 couldn\'t find final \')\' \n#                 (corresponding starter was at line 1)\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

关于优先级的工作原理,我缺少什么?

\n

(或者这个错误是一个错误,我只是想太多了?)

\n

operator-precedence rakudo raku

7
推荐指数
1
解决办法
108
查看次数

使用特征将代理应用于变量(不是属性)

这个问题与Apply a proxy using traits几乎重复。但是,这个问题涉及将代理应用于属性,我想对变量做同样的事情。从乔纳森的回答中,我明白我

需要安排将 Proxy 绑定到属性中,以便那里有一个 Proxy 而不是通常由类初始化逻辑创建的 Scalar 容器。

但是,即使在编译时,我似乎也无法成功绑定到 Variable:D。(包括 nqp::bind)。我将不胜感激任何指向正确方向的指针。

(理想情况下,我想支持使用带有赋值语法的变量/特征。在一个完美的世界中,我的语法如下:

my $thing is custom-proxy = 42;
Run Code Online (Sandbox Code Playgroud)

其结果将是$thing在代理内部容器化,而不是在标量中。但是,如果这不可能,我会满足于通过绑定来使用它:=

[编辑:建立在下面接受的答案的基础上,主要可以使用以下代码来做到这一点:


multi trait_mod:<is>(Variable \v, :$tom) {
    v.block.add_phaser(
        'ENTER',
        v.willdo(<-> $_ {
            $_ = Proxy.new:
                     STORE => -> $, $v { say "store $v" },
                     FETCH => { say "fetch!"; 42}
                }, 1))
}
Run Code Online (Sandbox Code Playgroud)

这适用于未初始化为不同值的state变量或调用函数而不是第一个的变量。

rakudo raku

6
推荐指数
2
解决办法
117
查看次数

在编译时访问变量

will特性给人以编译时访问Variable上,它被称为。还有其他方法可以访问Variable将安装在给定词法范围内的s 吗?(我知道我可以访问Scalar在运行时s,但我正在尝试访问Variables)。

特别是,我希望能够执行以下操作(不起作用):

multi trait_mod:<is>(Sub \fn, :$foo) {
    for fn.lexical_variables { #`(do stuff) }
}
Run Code Online (Sandbox Code Playgroud)

有什么办法吗?

compilation metaprogramming rakudo compile-time raku

6
推荐指数
1
解决办法
85
查看次数

`is pure` 特性和默认参数

下面的 &greet 函数是纯的,可以适当地标上is pure trait。

sub greet(Str:D $name) { say "Hello, $name" }
my $user = get-from-db('USER');
greet($user);
Run Code Online (Sandbox Code Playgroud)

然而,这不是:

sub greet { 
    my $name = get-from-db('USER');
    say "Hello, $name" 
}

greet($user);
Run Code Online (Sandbox Code Playgroud)

不过这个呢?

sub greet(Str:D $name = get-from-db('USER')) { say "Hello, $name" }

greet();
Run Code Online (Sandbox Code Playgroud)

从函数的“内部”来看,它看起来很纯粹——当参数绑定到相同的值时,它总是产生相同的输出,没有副作用。但是从函数的外部来看,它似乎是不纯的——当使用相同的参数调用两次时,它会产生不同的返回值。Raku/Rakudo 选择哪个前景?

functional-programming rakudo purely-functional raku

6
推荐指数
2
解决办法
105
查看次数

Raku 中的简洁(一行?)二分搜索

许多常见的操作都没有内置到 Raku 中,因为它们可以用(元)运算符和/或函数的组合来简洁地表达。这感觉就像折半查找有序数组的应该是那样的可表达的(也许用.rotor?或者?),但我还没有找到一个特别好的办法这样做。

例如,我想出的用于搜索已排序的 Pairs 数组的最佳方法是:

sub binary-search(@a, $target) {
    when +@a ? 1 { @a[0].key == $target ?? @a[0] !! Empty }
    &?BLOCK(@a[0..^*/2, */2..*][@a[*/2].key ? $target], $target)
}
Run Code Online (Sandbox Code Playgroud)

这并不可怕,但我无法动摇它可能会好得多的感觉(在简洁性和可读性方面)。谁能看到我可能缺少什么优雅的操作组合?

algorithm binary-search rakudo raku

6
推荐指数
1
解决办法
174
查看次数

什么算作 Raku *源* 文件的换行符?

我有点惊讶地发现下面的代码

\n
# comment \xe2\x80\xa9say 1;\n# comment \xe2\x80\xa8say 2;\n# comment say 3;\n# comment say 4;\n
Run Code Online (Sandbox Code Playgroud)\n

打印1234

\n

以下是“#comment”后的相关字符:

\n
say "\xe2\x80\xa9\xe2\x80\xa8".uninames.raku;\n# OUTPUT: \xc2\xab("PARAGRAPH SEPARATOR", "LINE SEPARATOR", "<control-000B>", "<control-000C>").Seq\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n

请注意,许多/所有这些字符在大多数字体中都是不可见的。至少对于我的编辑器来说,没有一个会导致以下文本打印在新行上。至少有一个(<control-000C>,又名Form Feed,有时打印为^L)在 Vim/Emacs 中相当广泛地用作节分隔符。

\n

这提出了几个问题:

\n
    \n
  1. 这是故意的还是错误?
  2. \n
  3. 如果是故意的,那么用例是什么(除了赢得混淆代码竞赛!)
  4. \n
  5. 是只有这4个角色,还是还有其他角色?(我发现这些是因为它们共享强制中断Unicode 属性。该属性(或其他一些 Unicode 属性?)是否控制 Raku 认为的换行符?)
  6. \n
  7. 只是,真的,哇。
  8. \n
\n

(我意识到#4 在技术上不是一个问题,但我觉得有必要说一下)。

\n

unicode comments newline rakudo raku

6
推荐指数
1
解决办法
124
查看次数

set() 与 Set() 与 Set.new 的语义

应该&set, Set, 和Set.new有不同的语义吗?如果是这样,为什么?

\n

考虑以下代码:

\n
my @array = 1, 2;\nmy @other-array = ([3, 4],);\n\ndd set(@array, @other-array);      #OUTPUT: Set.new(1,2,[3, 4])\ndd Set(@array, @other-array);      #OUTPUT: Set.new(1,2,[3, 4])\ndd Set.new: @array, @other-array;  #OUTPUT: Set.new([1, 2],[[3, 4],])\n
Run Code Online (Sandbox Code Playgroud)\n

不同的输出是故意的还是/Set.new中错误的结果?(我预计所有三个都会产生以下输出&setSetSet.new\xe2\x80\x93 生成的输出,我是否遗漏了一些关于预期语义的内容?)

\n

set rakudo semantics raku

6
推荐指数
1
解决办法
162
查看次数