我有一个应用程序,我希望创建一个新的运算符来处理我的自定义类之一。定义 (sub infix:<\xce\xb1>) 编译时没有任何抱怨,但是当我尝试使用该运算符时,Raku连续报告两个术语。
\n我想我的模块文件中做了一些奇怪的事情。有时,问题可以通过退出并重新初始化交互式 Raku 来解决 - 但它可能太明显了,我看不到它。
\n**更新
\n**
\n在模块中嵌入这些语句按预期工作 - 这使我怀疑我在模块中做错了什么,可能与导出有关(“连续两个术语”消息意味着编译器无法识别模块文件之外的客户操作员)。
我的模块没有什么秘密或神奇之处:
\n########################################################################\n### Convert goofy old Perl5 module to Raku\n########################################################################\n\nunit module Format;\n\nuse List::Util;\n\n=begin comment\nClass supporting a bidrectional map lookup. Given a hash containing \nkeys and aliases (e.g., key=>alias) two lookaside hashes are created\nto convert between the two values.\n=end comment\nclass Bidirectional is export {\n has Any %!aliasMap = ();\n has Any %!keyMap = ();\n has Any %.map = ();\n has Bool $!initialized = False;\n\n =begin comment\n Do nothing if this object has already been initialized, otherwise loop\n through the supplied map and populate the alias and key maps.\n =end comment\n method !initialize () {\n if !($!initialized) {\n for self.map.kv -> $key, $alias {\n %!aliasMap{$alias} = $key;\n %!keyMap{$key} = $alias;\n }\n\n $!initialized = True;\n\n say %!aliasMap;\n say %!keyMap;\n }\n\n return self;\n }\n\n =begin comment\n Convert from an alias to a key value\n =end comment\n method aliasToKey (Str $alias) {\n self!initialize();\n return %!aliasMap{$alias} || $alias;\n }\n\n =begin comment\n Convert from a key to an alias value.\n =end comment\n method keyToAlias (Str $key) {\n self!initialize();\n return %!keyMap{$key} || $key;\n }\n\n =begin comment\n Return either a key from an alias (first priority) or an alias from a key\n (second priority). \n =end comment\n method either (Str $candidate) {\n return self.aliasToKey($candidate) || self.keyToAlias($candidate);\n }\n}\n\nsub infix:<\xce\xb1> (Format::Bidirectional $name, Str $value) is export {\n return $name.keyToAlias($value);\n}\n\nsub infix:<\xce\xba> (Format::Bidirectional $name, Str $value) is export {\n return $name.aliasToKey($value);\n}\n\nsub infix:<\xe2\x88\xa8> (Format::Bidirectional $name, Str $value) is export {\n return $name.either($value);\n}\n\nclass Formatter {\n has Str $.span is rw;\n has Str $.border is rw;\n has Str $.top is rw;\n has Str $.reading_order is rw;\n has Bool $.locked is rw;\n has Str $.left is rw;\n has Str $.right_color is rw;\n has Str $.font_outline is rw;\n has Str $.rotation is rw;\n has Str $.shrink is rw;\n has Str $.text_wrap is rw;\n has Str $.right is rw;\n has Str $.bottom is rw;\n has Str $.indent is rw;\n has Str $.left_color is rw;\n has Str $.font_encoding is rw;\n has Str $.color is rw;\n has Str $.font_script is rw;\n has Str $.fg_color is rw;\n has Str $.font_strikeout is rw;\n has Str $.bg_color is rw;\n has Bool $.hidden is rw;\n has Str $.align is rw;\n has Str $.valign is rw;\n has Str $.font_charset is rw;\n has Str $.num_format is rw;\n has Str $.top_color is rw;\n has Bool $.italic is rw;\n has Str $.font_family is rw;\n has Bool $.bold is rw;\n has Str $.bottom_color is rw;\n has Str $.size is rw;\n has Str $.pattern is rw;\n has Str $.font is rw;\n has Str $.font_shadow is rw;\n has Str $.text_justlast is rw;\n has Str $.underline is rw;\n\n =begin comment\n Map any properties with aliases. The property name and the alis name\n will return the same results with Bidirectional objects.\n =end comment\n has Bidirectional $!map = Bidirectional.new(:map(\n font_encoding => <_font_encoding>;\n ));\n\n =begin comment\n Convert an attribute name such as is used by get_value and set_value\n to a property name which keys the .object() hash.\n =end comment\n method !a2p (Str $candidate) { \n return $candidate.substr(2) if $candidate.match(/^\\$\\W/);\n }\n\n =begin comment\n Convert the property name to an attribute name that can be used with \n get_value and set_value.\n =end comment\n method !p2a (Str $candidate, Str $prefix='$!') {\n return $prefix ~ $candidate if !$candidate.match(/^\\$\\W/);\n }\n\n =begin comment\n Given an attribute key, return its attribute alias.\n =end comment\n method alias (Str $candidate) {\n return $!map.keyToAlias($candidate);\n }\n\n =begin comment\n Given an attribute alias, return its attribute key.\n =end comment\n method key (Str $candidate) {\n return $!map.aliasToKey($candidate);\n }\n\n =begin comment\n Set the attribute values of the object. Any name supplied in the argument\n must be a valid attribute and it must not be a private attribute.\n =end comment\n method set (%object) {\n my @attributes = self.^attributes(:local);\n\n for %object.kv -> $key, $value {\n my $attribute = first { $_ ~~ /$key/ }, @attributes;\n\n if $attribute && ($attribute.has_accessor) {\n $attribute.set_value(self, $value);\n }\n }\n }\n\n =begin comment\n Coverts a Format::Formatter object to a Hash containing only the public \n attributes and values. \n =end comment\n method object (Format::Formatter:D $override?) {\n my %answer = ();\n my $victim = $override ?? $override !! self;\n\n for $victim.^attributes(:local) -> $attribute {\n next if !$attribute.has_accessor;\n\n my $candidate = $attribute.get_value($victim);\n my $property = self!a2p($attribute.name);\n\n if $candidate {\n %answer{$property} = $candidate;\n }\n }\n\n return %answer;\n }\n\n =begin comment\n Determine whether two Format::Formatter objects are the same. This comparison\n is carried out against the .object() form of both objects, which excludes any\n private attributes. If the two .object() values have the same keys and values,\n True is returned; else False \n =end comment\n method same (Any $other) {\n if $other.WHAT \xe2\x88\x89 (Hash, Format::Formatter) {\n X::TypeCheck.new(operation=>'Format::Formatter comparison', \n got=>$other.WHAT, expected=>Format::Formatter).throw;\n }\n\n my $left = self.object;\n my $right = $other ~~ Format::Formatter ?? $other.object !! $other;\n my $answer = $left eqv $right;\n\n return $answer;\n }\n}\n\n=begin comment\nOverride === operator for Format::Formatter equivalence - this may have \nunforseen results, and the .same() method should probably be used instead \n\nThe first form covers the case of $format1===$format2 -- both arguments\nare converted to hashes using .object()\n\nThe second form covers the case of $format1==$hash2 -- the first argument\nis converted to a hash using .object()\n=end comment\nmulti sub infix:<===> (Format::Formatter:D $left, Format::Formatter:D $right) is export {\n return $left.object eqv $right.object;\n}\n\nmulti sub infix:<===> (Format::Formatter:D $left, Hash:D $right) is export {\n return $left.object eqv $right;\n}\nRun Code Online (Sandbox Code Playgroud)\n我尝试了以下方法。我希望自定义运算符执行我指定的操作。
\n[2] > my $m = Format::Bidirectional.new(map=>{a => <_a>})\nFormat::Bidirectional.new(map => (my Any % = :a("_a")))\n[3] > say $m.WHAT\n(Bidirectional)\n[3] > $m ~~ Format::Bidirectional\nTrue\n[4] > my $t = 'test'\ntest\n[5] > $t ~~ Str\nTrue\n[6] > sub infix:<\xce\xb1> (Format::Bidirectional $name, Str $value) {\n return $name.keyToAlias($value);\n}\n&infix:<\xce\xb1>\n[7] > $m \xce\xb1 $t\n===SORRY!=== Error while compiling:\nTwo terms in a row\n------> $m\xe2\x8f\x8f \xce\xb1 $t\n expecting any of:\n infix\n infix stopper\n statement end\n statement modifier\n statement modifier loop\nRun Code Online (Sandbox Code Playgroud)\n但使用 Raku 文档中的示例是可行的:
\nsub infix:<:=:>( $a is rw, $b is rw ) {\n ($a, $b) = ($b, $a)\n}\n \nmy ($num, $letter) = ('A', 3);\nsay $num; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n \n# Swap two variables' values \n$num :=: $letter;\n \nsay $num; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \n\nA\n3\n3\nA\nRun Code Online (Sandbox Code Playgroud)\n尝试使用仅替换我的操作的示例(尽管此处“is rw”是虚假的),我得到“无法进行分配”(请注意,在尝试此操作之前,我退出了交互 shell 并重新进入):
\n[3] > sub infix:<:==:>($a is rw, $b is rw) { return $a.keyToAlias($b) }\n&infix:<:==:>\n[4] > $m :==: 'a'\n===SORRY!=== Error while compiling:\nCannot make assignment out of := because list assignment operators are too fiddly\n------> $m :==\xe2\x8f\x8f: 'a'\nRun Code Online (Sandbox Code Playgroud)\n我想这可能是我使用的 unicode 字符(小 alpha)或类,所以:
\n[0] > use lib "."\nNil\n[1] > use Format\nNil\n[2] > my $aa = {a=>'_a', b=>'_b'}\n{a => _a, b => _b}\n[3] > sub infix:<alias>($a, $b) { return $a=>$b }\n&infix:<alias>\n[4] > $aa alias 'a'\n===SORRY!=== Error while compiling:\nTwo terms in a row\n------> $aa\xe2\x8f\x8f alias 'a'\n expecting any of:\n infix\n infix stopper\n statement end\n statement modifier\n statement modifier loop\nRun Code Online (Sandbox Code Playgroud)\n雪上加霜的是,认为像“别名”这样的字面术语可能行不通:
\n[4] > sub infix:<swap>( $a is rw, $b is rw ) {\n ($a, $b) = ($b, $a)\n}\n \nmy ($num, $letter) = ('A', 3);\nsay $num; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n \n# Swap two variables' values \n$num swap $letter;\n \nsay $num; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \nA\n3\n3\n[4] > \nRun Code Online (Sandbox Code Playgroud)\n也许这是我使用的特定词?
\n[4] > sub infix:<alias>( $a is rw, $b is rw ) {\n ($a, $b) = ($b, $a)\n}\n \nmy ($num, $letter) = ('A', 3);\nsay $num; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n \n# Swap two variables' values \n$num alias $letter;\n \nsay $num; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n===SORRY!=== Error while compiling:\nTwo terms in a row\nat line 10\n------> $num\xe2\x8f\x8f swap $letter;\n expecting any of:\n infix\n infix stopper\n statement end\n statement modifier\n statement modifier loop\nRun Code Online (Sandbox Code Playgroud)\n但随后我退出并重新初始化:
\n[3] > sub infix:<alias>( $a is rw, $b is rw ) {\n ($a, $b) = ($b, $a)\n}\n \nmy ($num, $letter) = ('A', 3);\nsay $num; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n \n# Swap two variables' values \n$num alias $letter;\n \nsay $num; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \nA\n3\n3\nRun Code Online (Sandbox Code Playgroud)\n为了更好地衡量:
\n my $a = {a=>"_a", b=>"_b"}\n{a => _a, b => _b}\n[3] > sub infix:<\xce\xb1>( $a is rw, $b is rw ) {\n ($a, $b) = ($b, $a)\n}\n \nmy ($num, $letter) = ('A', 3);\nsay $num; # OUTPUT: \xc2\xabA\xe2\x90\xa4\xc2\xbb \nsay $letter; # OUTPUT: \xc2\xab3\xe2\x90\xa4\xc2\xbb \n \n# Swap two variables' values \n$num \xce\xb1 $letter;\n \nsay $num;\nA\n3\n3\nRun Code Online (Sandbox Code Playgroud)\n在模块文件中,我定义了这些自定义运算符。低音炮不起作用,多低音炮起作用:
\nsub infix:<\xce\xb1> (Format::Bidirectional $name, Str $value) is export {\n return $name.keyToAlias($value);\n}\n\nsub infix:<\xce\xba> (Format::Bidirectional $name, Str $value) is export {\n return $name.aliasToKey($value);\n}\n\nsub infix:<\xe2\x88\xa8> (Format::Bidirectional $name, Str $value) is export {\n return $name.either($value);\n}\n\nmulti sub infix:<===> (Format::Formatter:D $left, Format::Formatter:D $right) is export {\n return $left.object eqv $right.object;\n}\n\nmulti sub infix:<===> (Format::Formatter:D $left, Hash:D $right) is export {\n return $left.object eqv $right;\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
101 次 |
| 最近记录: |