给定一个参数,Array
构造函数将其展平.这会导致问题:
my %hash = (a => 1; b => 2);
my @array = [ %hash ]; # result: [a => 1 b => 2], expected [{ a => 1, b => 2 }]
Run Code Online (Sandbox Code Playgroud)
List构造函数没有这个怪癖(单参数规则),但遗憾的是,创建单元素列表没有简短的语法:
List.new(%hash); # result is ({a => 1, b => 2}), as expected
Run Code Online (Sandbox Code Playgroud)
解决方法:如果您的参数是标量,则不会自动展平:
my $hash = %hash;
my @array = [ $%hash ]; # or my @array = [ $%hash ], or just my @array = $%hash
# result: [{a => 1, …
Run Code Online (Sandbox Code Playgroud) 在perl 5中,我将使用任何Carp函数.在perl 6中,搜索没有帮助,跟踪编译指示将打印所有堆栈,而不仅仅是我想要的堆栈.我只能使用抛出异常,捕获它并打印它的旧hack:
try {
X::AdHoc.new(payload => 'Stack').throw;
CATCH { when X::AdHoc { .say; } }
}
Run Code Online (Sandbox Code Playgroud)
或者,有点懒惰:
{
die;
CATCH { default { .say } }
}
Run Code Online (Sandbox Code Playgroud)
这样做的正确方法是什么?
Git 2.17更新日志描述了此选项:
- 有人介绍了克隆和获取的机制,这又涉及包装和拆包对象,该机器已被告知如何使用
另一个主题引入的过滤机制来省略某些对象。现在
,它知道将生成的包标记为允诺包,以容忍丢失的
对象,为“狭窄”克隆奠定基础。
这个标志准备好使用了吗,还是很有可能很不稳定?有谁知道正确的语法通过?我通过的所有标志都被视为无效的过滤器规范而被拒绝。例如,这些是我尝试按目录过滤的:
git clone file://path --depth=1 --filter '--subdirectory-filter Assets' TestRepo
git clone file://path --depth=1 --filter --subdirectory-filter Assets TestRepo
git clone file://path --depth=1 --filter Assets TestRepo
Run Code Online (Sandbox Code Playgroud) 以下是基于更大语法的测试用例 - 目标是解析Unity3D资产文件中使用的YAML子集.有趣的功能是键控数组匹配器.这个匹配器循环,匹配data[i]: val
为<array-name(index)><indexer-and-value(index, name)>
.<array-name>
重载,所以第一次调用时,它将匹配任何名称.后续迭代 - 当索引非零时 - 将仅匹配所看到的相同名称.
问题的关键在于当index> 0时,数组应始终有一个已知的名称,并且应该作为参数传递给匹配器.它不是 - 解释器给出以下错误:
Cannot resolve caller array-name(Match.new(...): 1, Nil, 1); none of these signatures match:
(Prefab $: Int $ where { ... }, $prevName, Int $indent, *%_)
(Prefab $: Int $idx, Match $ (@ (Any $prevName, *@)), Int $indent, *%_)
(Prefab $: Int $idx, @ (Any $prevName, *@), Int $indent, *%_)
Run Code Online (Sandbox Code Playgroud)
所以索引是1,但之前没有匹配的名称.那个参数是Nil
没有意义的.注意该函数中注释掉的块:#{ }
.如果取消注释,测试用例将停止失败.没有基于最长匹配(|
运算符或proto
匹配器)的分支,因此在匹配器中添加额外的东西不应该更改解析.
测试输入包含在测试用例中.这里是: …
给定代表枚举的数据,例如:
my %enums := {
Color => { red => 0, black => 1, green => 2 },
Status => { fail => 0, pass => 1 }
};
Run Code Online (Sandbox Code Playgroud)
如何使用Metamodel::ClassHOW
创建等效于以下内容的枚举:
enum Color ( red => 0, black => 1, green => 2 );
enum Status ( fail => 0, pass => 1 );
Run Code Online (Sandbox Code Playgroud)
Timo的ADT库提供了一个如何创建类的示例ClassHOW
,但它不包含枚举:https://github.com/timo/ADT/blob/master/lib/ADT.pm6
我的输入有多个标签和空格,以便于阅读.我想使用修改字段perl -a
,然后以原始形式打印出该行.(数据来自findup
,显示重复文件的数量和他们浪费的空间.)输入是:
2 * 4096 backup/photos/photo.jpg photos/photo.jpg
2 * 111276032 backup/books/book.pdf book.pdf
Run Code Online (Sandbox Code Playgroud)
输出会将字段3转换为千字节,如下所示:
2 * 4 KB backup/photos/photo.jpg photos/photo.jpg
2 * 108668 KB backup/books/book.pdf book.pdf
Run Code Online (Sandbox Code Playgroud)
在我的梦想世界中,这将是我的代码,因为我可以将perl自动重新组合@F
并保留原始空白:
perl -lanE '$F[2]=int($F[2]/1024)." KB"; print;'
Run Code Online (Sandbox Code Playgroud)
在现实生活中,加入单个空间似乎是我唯一的选择:
perl -lanE '$F[2]=int($F[2]/1024)." KB"; print join(" ", @F);'
Run Code Online (Sandbox Code Playgroud)
是否有任何自动变量可以记住分隔符?如果我有这样的魔术数组,代码将是:
perl -lanE 'BEGIN{use List::Util "reduce";} $F[2]=int($F[2]/1024)." KB"; print reduce { $a . shift(@magic) . $b } @F;'
Run Code Online (Sandbox Code Playgroud) 我的场景是:文件接收器应该包含所有内容。另一个接收器应包含信息消息,但需要注意的是 Microsoft.* 消息很烦人,因此这些消息应仅限于警告。两个sink如何单独配置?我尝试的第一件事是:
string outputTemplate = "[{Level:u3}] {SourceContext}: {Message:lj}{NewLine}";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.File("Logs/all.log", outputTemplate: outputTemplate)
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning)
.WriteTo.File("Logs/some.log", outputTemplate: outputTemplate)
.CreateLogger();
var msLogger = Log.Logger.ForContext(Constants.SourceContextPropertyName, "Microsoft.AspNet.Example");
var logger = Log.Logger.ForContext(Constants.SourceContextPropertyName, "MyClass");
msLogger.Verbose("example log; should not go in the minimal file");
msLogger.Information("example log; should not go in the minimal file");
msLogger.Warning("example log");
logger.Verbose("example log; should not go in the minimal file");
logger.Information("example log");
Run Code Online (Sandbox Code Playgroud)
在这种情况下,两个日志文件都是选择性的,并且“all.log”不包含所有日志消息。接下来,我尝试使用子记录器来完成此任务:
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.File("Logs/all.log", outputTemplate: outputTemplate)
.WriteTo.Logger(lc => lc
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", Serilog.Events.LogEventLevel.Warning) …
Run Code Online (Sandbox Code Playgroud) 鉴于一些代码对1到500000的每个数字进行了一些数学/转换,我们有以下选项:
简单的循环:for ^500000 -> $i { my $result = ($i ** 2).Str; }
.在我不科学的基准测试中,这需要2.8秒.
最规范的并行版本在a中完成每一项工作Promise
,然后等待结果.await do for ^500000 -> $i { start { my $result = ($i ** 2).Str; } }
需要19秒.这很慢!创建一个新的promise必须有太多的开销才能进行这样一个简单的计算.
使用并行map
操作相当快.在2.0秒时,操作似乎几乎不足以利用并行化:(^500000).race.map: -> $i { my $result = ($i ** 2).Str; }
第三种选择似乎最好.不幸的是,它看起来像一个黑客.我们不应该map
在sink上下文中编写迭代代码,因为在源代码中读取"map"的其他人可能会认为目的是构建一个列表,这根本不是我们的意图.使用map
这种方式的沟通很差.
有没有任何规范的快速方法来使用Perl 6的内置并发?如果一个超级运算符可以接受一个块而不仅仅是函数,那么它将是完美的:
(^500000)».(-> $i { my $result = ($i ** 2).Str; }) # No such method 'CALL-ME' for invocant of type 'Int'
Run Code Online (Sandbox Code Playgroud) 我的问题与集合操作中的用户定义函数有关,但我认为我可以切入问题的核心:
如何选择特定的散列函数?例如,如果我想进行基于值的匹配而不是引用匹配,并且我想查看某个元组是否存在(或者只是删除它):
my %data := SetHash.new: (1, 2), (3, 4);
%data{$(1, 2)}:delete; # False
Run Code Online (Sandbox Code Playgroud)
在C++或C#中,我可以为构造函数提供自定义哈希/比较函数.在C#中,如果我的数据类型是a struct
(值类型而不是引用类型),则会自动按值进行散列.Perl 6在某种程度上进行了值类型哈希Pair
(如果Pair不包含任何容器),但我不知道如何使它适用于任何其他复杂类型.
一方面,我明白为什么这不是最安全的操作 - 很容易定义哈希代码插入后可以更改的对象.但这并没有阻止.NET和C++ STL允许自定义散列.
一种可能的API使用(与由激发了链式散列逻辑此,最初来自升压)将是:
class MyHasher does Hasher of Array[Int] {
method get-hash-value(Int @array) {
reduce
-> $a, $b {$a +^ ($b + 0x9e3779b97f4a7c16 + ($a +< 6) + ($a +> 2))},
0,
|@array;
}
method equals(Int @a, Int @b) { @a eqv @b; }
}
my %data := SetHash.new(
my Int @=[1, 2], my …
Run Code Online (Sandbox Code Playgroud) 其他一些高级语言(如Haskell和Perl 6)提供了语法糖,即使在语法需要对象的地方也可以抛出异常.当使用该值时,它就好像变成抛出的异常(在下面非常人为的例子中会立即出现):
enum BuildMode { Debug, MemoryProfiling, Release };
bool IsDebugMode(BuildMode mode)
{
return mode == BuildMode.Debug ? true
: mode == BuildMode.MemoryProfiling ? true
: mode == BuildMode.Release ? false
: ThrowException<bool>("Unhandled mode: " + mode);
}
Run Code Online (Sandbox Code Playgroud)
上面的帮助器允许从允许值但不是语句的地方抛出异常.我可以按如下方式编写这个函数,虽然它不像Haskell或Perl 6代码那么酷,因为没有懒惰的评估:
T ThrowException<T>(string message)
{
#line hidden
throw new Exception(message);
#line default
}
Run Code Online (Sandbox Code Playgroud)
有没有任何规范的方法来做到这一点,或者有什么好的理由不去做?
编辑:
throw new Exception()
在发布之前,我实际上没有尝试在C#7中使用它作为值.这或多或少都是答案.我将把它留下来,以防将来人们搜索与Perl 6 Failure
类或Haskell 相当的C#error
.