在尝试为 API 创建 JSON 消息时,我发现自己很难做一些我认为很简单的事情。我需要创建如下消息:
{ "list": [ { "foo": 1, "bar": 2 } ] }
Run Code Online (Sandbox Code Playgroud)
但是,我的第一次尝试没有奏效:
say to-json { foo => [ { a => 1, b => 2 } ] };
# {"foo":[{"a":1},{"b":2}]}
Run Code Online (Sandbox Code Playgroud)
试图简化事情让我更加困惑:
say { foo => [ { a => 1 } ] };
# {foo => [a => 1]}
# Note that this is not JSON, but I expected to see curly braces
Run Code Online (Sandbox Code Playgroud)
然后我尝试使用一些临时变量,并且有效:
my @list = { a => 1 };
say to-json { …
Run Code Online (Sandbox Code Playgroud) 我最近花了很多时间调试一个脚本,当我最终发现问题时,是因为代码看起来像这样:
class Foo {
has $.bar;
method () {
# do stuff
$!.bar;
}
}
Run Code Online (Sandbox Code Playgroud)
原来,问题是与$!.bar
,它应该是要么$!bar
或$.bar
。我明白了。
但这为什么不死?
详细看这个,它看起来像这里的问题是,我试图调用(不存在)的方法bar
上$!
,它在这一点上Nil
,因为再也没有出现过任何差错。
看起来我实际上可以调用我想要的任何方法,Nil
并且它们都默默地返回Nil
,包括像Nil.this-is-a-fake-method
和这样的东西Nil.reverse-entropy(123)
。
这是一个功能吗?如果是这样,理由是什么?
我知道我可以安排一个Promise
在给定的时间内保存
my $promise = Promise.in($seconds);
Run Code Online (Sandbox Code Playgroud)
但我怎样才能安排它被打破?具体来说,我正在考虑一个会“超时”的承诺,这样它就有一定的时间来保留,否则就会失败。
我可以用另一个来做到这一点Promise
,就像这样:
my $promise = Promise.new;
...
Promise.in($seconds).then: { $promise.break };
Run Code Online (Sandbox Code Playgroud)
但这感觉有点……浪费。有一个更好的方法吗?
最近我意识到我完全错误地编写了这样的 Raku 类之一:
class Foo {
has method bar {
return 'some string';
}
}
Run Code Online (Sandbox Code Playgroud)
我很惊讶地发现这has method
不是错误,并且按预期工作。
has
在这种情况下做什么?这是故意行为吗?
像这样的片段
# Contents of ./run
my $p = Proc::Async.new: @*ARGS;
react {
whenever Promise.in: 5 { $p.kill }
whenever $p.stdout { say "OUT: { .chomp }" }
whenever $p.ready { say "PID: $_" }
whenever $p.start { say "Done" }
}
Run Code Online (Sandbox Code Playgroud)
像
./run raku -e 'react whenever Supply.interval: 1 { .say }'
Run Code Online (Sandbox Code Playgroud)
我希望看到类似的东西
PID: 1234
OUT: 0
OUT: 1
OUT: 2
OUT: 3
OUT: 4
Done
Run Code Online (Sandbox Code Playgroud)
但我看到
PID: 1234
OUT: 0
Done
Run Code Online (Sandbox Code Playgroud)
我知道这与缓冲有关:如果我将该命令更改为类似
# The $|++ disables buffering
./run perl …
Run Code Online (Sandbox Code Playgroud) 我可以编写一个 UDP 服务器,它将使用 IO::Socket::Async 从客户端接收消息
my $socket = IO::Socket::Async.bind-udp: 'localhost', 3333;
react whenever $socket.Supply: :bin {
say "Received some junk: { .gist }";
}
Run Code Online (Sandbox Code Playgroud)
我可以将东西发送到该服务器:
given IO::Socket::Async.udp {
await .print-to: 'localhost', 3333, 'Hello';
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试让服务器发回消息响应时,我意识到我没有要发送消息的主机和端口。我怎样才能得到这些信息?
通常,我认为这个问题的答案是使用recvfrom
并传递一个指向sockaddr
结构的指针,该结构将填充传入连接的地址信息。但如果不使用 NativeCall 似乎就没有办法做到这一点(即使如此,我也不清楚如何做到这一点)。
或者我错过了什么?
我正在编写 Raku 绑定到 C 库,但不是要求 Raku 代码的用户自己安装 C 库,我想将 C 代码捆绑为发行版的一部分(它不是那么广泛分布式库)。
我读过有关发行版的%?RESOURCES
,这似乎很有用。但是我对如何将其应用于此的具体细节感到模糊。
我是否可以将 C 源代码捆绑在发行版中,并指定某种方式使其作为安装的一部分进行编译(例如,使用zef
)?或者我是否需要捆绑库的预编译版本,并获取代码以根据平台选择正确的版本?
或者这根本不可能,我应该向用户提供有关如何单独安装库的说明?
在Perl5中,您可以执行以下操作:
#!/usr/bin/env perl
use 5.010;
package Local::Class {
use Moo;
has [qw( x y )] => ( is => 'ro');
sub BUILDARGS { shift; return (@_) ? (@_ > 1) ? { @_ } : shift : {} }
}
use Local::Class;
# Create object directly
my $x = Local::Class->new( x => 1, y => 10 );
say $x->x, ' ', $x->y; # 1 10
# Arguments from a hash
my %hash = ( x => 5, y => 20 …
Run Code Online (Sandbox Code Playgroud) 我知道我可以通过将输入记录分隔符($/
)设置为未定义的值来吸引文件,例如
open my $fh, '<', $filename or die "Cannot read from $file: $!";
my $contents = do { local $/; <$fh> };
Run Code Online (Sandbox Code Playgroud)
但是最近我遇到了一个非常相似但又不同的成语:
open my $fh, '<', $filename or die "Cannot read from $file: $!";
my $contents = do { local $/ = <$fh> };
Run Code Online (Sandbox Code Playgroud)
(请注意,local $/ = <$fh>
而不是local $/; <$fh>
)。
这两种的工作,并且对两者的CPAN实例与分配所述变体与所述一个无(尽管后者并不奇怪,更为常见)。
但是我的问题是为什么它起作用?作业的变化形式是什么?
PS:我也知道我应该使用例如。File :: Slurper可以吞食文件,但是有时候生活很有趣。
与Perl5中的大多数内容一样,有许多方法可以创建支持其属性的自定义类型强制的类.这是一个简单的,从数组引用到哈希:
#!/usr/bin/env perl
package Local::Class {
use Moo;
use Types::Standard qw( HashRef ArrayRef );
has set => (
is => 'ro',
coerce => 1,
isa => HashRef->plus_coercions(
ArrayRef, sub { return { map { $_ => 1} @{$_[0]} } },
),
);
}
my $o = Local::Class->new({ set => [qw( a b b c )] });
# $o->set now holds { a => 1, b => 1, c => 1}
Run Code Online (Sandbox Code Playgroud)
我一直试图将这样的东西移植到Perl6,在那里看起来我需要的是一种强制转换Array
为a的方法SetHash
.到目前为止,我能够做到这一点的唯一方法是:
#!/usr/bin/env perl6
class Local::Class { …
Run Code Online (Sandbox Code Playgroud) 用一个代码片段
perl6 -e 'loop { FIRST say "foo"; last }'
Run Code Online (Sandbox Code Playgroud)
我明白了
WARNINGS for -e:
Useless use of LOOP_BLOCK_1 symbol in sink context (line 1)
foo
Run Code Online (Sandbox Code Playgroud)
我知道如何解决警告.我想知道警告的来源是什么.我发现这张门票,但似乎没有得到任何关注.
这个警告是关于什么的?
那怎么回事呢?
$ perl6 --version
This is Rakudo version 2018.06 built on MoarVM version 2018.06
implementing Perl 6.c.
Run Code Online (Sandbox Code Playgroud)