使用依赖于其他参数的函数参数的默认值

EZM*_*EZM 9 raku

我想创建一个脚本,它需要一个输入文件和一个可选的输出文件。当您不传递输出文件时,脚本将使用与输入相同的文件名,但扩展名已更改。我不知道如何编写更改扩展名的默认参数。

#!/usr/bin/env raku

unit sub MAIN(
  Str $input where *.IO.f, #= input file
  Str $output = $input.IO.extension("txt"), #= output file
  Bool :$copy, #= copy file
  Bool :$move, #= move file
);
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用:

No such method 'IO' for invocant of type 'VMNull'
  in block <unit> at ./copy.raku line 5
Run Code Online (Sandbox Code Playgroud)

我怎样才能做这样的事情呢?

Mus*_*dın 5

错误消息不太好,但预计程序无法工作,因为您在签名中包含

\n
Str $output = $input.IO.extension("txt")\n
Run Code Online (Sandbox Code Playgroud)\n

但右侧返回一个IO::Path具有该扩展名的对象,但是$output类型为字符串。这是一个错误:

\n
>>> my Str $s := "file.csv".IO.extension("txt")\nType check failed in binding; expected Str but got IO::Path (IO::Path.new("file.t...)\n  in block <unit> at <unknown file> line 1\n
Run Code Online (Sandbox Code Playgroud)\n
>>> sub fun(Str $inp, Str $out = $inp.IO.extension("txt")) { }\n&fun\n\n>>> fun "file.csv"\nType check failed in binding to parameter \'$out\'; expected Str but got IO::Path (IO::Path.new("file.t...)\n  in sub fun at <unknown file> line 1\n  in block <unit> at <unknown file> line 1\n
Run Code Online (Sandbox Code Playgroud)\n

有时编译器会检测到不兼容的默认值:

\n
>>> sub yes(Str $s = 3) { }\n===SORRY!=== Error while compiling:\nDefault value \'3\' will never bind to a parameter of type Str\n------> sub yes(Str $s = 3\xe2\x8f\x8f) { }\n    expecting any of:\n        constraint\n
Run Code Online (Sandbox Code Playgroud)\n

但你所拥有的远非字面意思,所以运行时检测。

\n

要修复它,您可以

\n
    \n
  • 更改为Str() $output = $inp.IO.extension("txt")whereStr()表示“接受任何对象,然后将其转换为 Str”。所以$output最终会变成一个像这样的字符串"file.txt"MAIN 中可用的字符串。

    \n
      \n
    • 类似的替代方案:Str $output = $inp.IO.extension("txt").Str但它是重复的Str.
    • \n
    \n
  • \n
  • 改成IO::Path() $output = $inp.IO.extension("txt")。类似地,这会转换为IO::Path对象收到的任何内容,因此,例如,您将"file.txt".IO$output. 如果您这样做,您可能也想这样做$input以保持一致性。由于IO::Path对象是幂等的.IO(在eqv某种意义上),因此代码的其他部分不需要更改。

    \n
  • \n
\n