考虑以下两个程序:
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
块中也能执行。那是对的吗?如果是这样,还有其他类似的特殊形式我应该知道吗?
如果我有以下变量
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
每个变量声明的特征来做到这一点,但我希望有一种不需要注释每个声明的方法。也许有 ::(...) 插值?)
基于为乐的文档上环视断言,我读的正则表达式/ <?[abc]> <alpha> /
的话说,“从左边,比赛开始,但不不消耗一个字符是a
,b
或c
和,一旦你找到了一个匹配,匹配和使用一个字母字符。 ”
因此,这个输出是有道理的:
'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>
. 那么环视到底是不是捕捉到了一些东西?还是我对环视的工作方式有其他误解?
使用定义的或运算符(//
) 会产生我期望的结果:
say( \'nan\'.Int // 42); # OUTPUT: \xc2\xab42\xc2\xbb\n
Run Code Online (Sandbox Code Playgroud)\n然而,使用较低优先级orelse
运算符会引发错误:
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这个问题与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
变量或调用函数而不是第一个的变量。
该will
特性给人以编译时访问Variable
上,它被称为。还有其他方法可以访问Variable
将安装在给定词法范围内的s 吗?(我知道我可以访问Scalar
在运行时s,但我正在尝试访问Variable
s)。
特别是,我希望能够执行以下操作(不起作用):
multi trait_mod:<is>(Sub \fn, :$foo) {
for fn.lexical_variables { #`(do stuff) }
}
Run Code Online (Sandbox Code Playgroud)
有什么办法吗?
下面的 &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 选择哪个前景?
许多常见的操作都没有内置到 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)
这并不可怕,但我无法动摇它可能会好得多的感觉(在简洁性和可读性方面)。谁能看到我可能缺少什么优雅的操作组合?
我有点惊讶地发现下面的代码
\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打印1
、2
、3
和4
。
以下是“#comment”后的相关字符:
\nsay "\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(我意识到#4 在技术上不是一个问题,但我觉得有必要说一下)。
\n应该&set
, Set
, 和Set.new
有不同的语义吗?如果是这样,为什么?
考虑以下代码:
\nmy @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
中错误的结果?(我预计所有三个都会产生以下输出&set
Set
Set.new
\xe2\x80\x93 生成的输出,我是否遗漏了一些关于预期语义的内容?)