使用 Perl 6 自定义运算符
Posted
技术标签:
【中文标题】使用 Perl 6 自定义运算符【英文标题】:Using Perl 6 custom operators 【发布时间】:2017-03-28 13:21:04 【问题描述】:我在大学学习化学,想尝试用 Perl6 或 Perl 编写教科书示例,比如平衡化学公式或其他过程!
然后我遇到的问题是关于perl6自定义运算符。当我使用该功能时,我觉得我一直在重复我的代码和我自己。 很难读和写。我该如何简化呢?
#!/usr/bin/env perl6
use v6;
#basic SI(International System of Units) type
role MetricPrefix
method baseOn ( Str $base , Numeric $input )
given $base
when 'pico' return $input * 10**-12
when 'namo' return $input * 10**-9
when 'micro' return $input * 10**-6
when 'milli' return $input * 10**-3
when 'centi' return $input * 10**-2
when 'hecto' return $input * 10**2
when 'kilo' return $input * 10**3
when 'mega' return $input * 10**6
when 'giga' return $input * 10**9
when 'tera' return $input * 10**12
default fail "you must input a metric prefix which allow pico to tera"
class Mass does MetricPrefix
#basic Mass is g is different form si statda
has $.g;
submethod BUILD ( :$!g )
class Length does MetricPrefix
has $.Length ;
submethod BUILD ( :$!Length )
multi postfix:<(kg)>( $input )
return Mass.new( g => Mass.baseOn("kilo",$input) ) or fail "you Must input a number";
multi postfix:<(g)>( $input )
return Mass.new( g => $input ) or fail "you Must input a number";
multi infix:<+>( Mass $inputOne , Mass $inputTwo ) is assoc<right>
return Mass.new( g => $inputOne.g + $inputTwo.g) or fail "error in there ";
multi infix:<->( Mass $inputOne , Mass $inputTwo ) is assoc<right>
return Mass.new( g => $inputOne.g - $inputTwo.g) or fail "error in there ";
multi infix:<*>( Mass $inputOne , Mass $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> ) is tighter( &infix:</>)
return Mass.new( g => $inputOne.g * $inputTwo.g) or fail "error in there ";
multi infix:</>( Mass $inputOne , Mass $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> )
return Mass.new( g => $inputOne.g / $inputTwo.g) or fail "error in there ";
#the meterLeng
multi postfix:<(km)>( $input )
return Length.new( Length => Length.baseOn("kilo",$input) ) or fail "you Must input a number";
multi postfix:<(m)>( $input )
return Length.new( Length => $input ) or fail "you Must input a number";
multi infix:<+>( Length $inputOne , Length $inputTwo ) is assoc<right>
return Length.new( Length => $inputOne.Length + $inputTwo.Length) or fail "error in there ";
multi infix:<->( Length $inputOne , Length $inputTwo ) is assoc<right>
return Length.new( Length => $inputOne.Length - $inputTwo.Length) or fail "error in there ";
multi infix:<*>( Length $inputOne , Length $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> ) is tighter( &infix:</>)
return Length.new( Length => $inputOne.Length * $inputTwo.Length) or fail "error in there ";
multi infix:</>( Length $inputOne , Length $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> )
return Length.new( Length => $inputOne.Length / $inputTwo.Length) or fail "error in there ";
#just a test
say 10(kg) + 1(g);
say 10(m) + 1(m);
【问题讨论】:
这感觉像是一个代码审查问题,而不是你需要解决的问题。您可能(请先查看他们的帮助中心)在我们的姊妹网站codereview.stackexchange.com 上发现它更合适submethod BUILD
s 是不必要的,因为您将属性声明为公共。
是的,当我没有使用任何对象构造时,这个子方法BUILD是不必要的;
【参考方案1】:
我用在输入上声明类型替换了失败消息。这将使 Perl 6 担心是否输入了数字并在没有输入时给出适当的错误消息。我还建立了所有长度和质量都是正数的假设。
#!/usr/bin/env perl6
use v6;
#basic SI(International System of Units) type
role MetricPrefix
method baseOn ( Str $base , Numeric $input )
given $base
when 'pico' return $input * 10**-12
when 'namo' return $input * 10**-9
when 'micro' return $input * 10**-6
when 'milli' return $input * 10**-3
when 'centi' return $input * 10**-2
when 'hecto' return $input * 10**2
when 'kilo' return $input * 10**3
when 'mega' return $input * 10**6
when 'giga' return $input * 10**9
when 'tera' return $input * 10**12
default fail "you must input a metric prefix within the range of pico to tera"
class Mass does MetricPrefix
#basic Mass is g is different form si statda
has $.g where * > 0;
class Length does MetricPrefix
has $.Length where * > 0;
# Mass
multi postfix:<(kg)>( $input where * > 0)
return Mass.new( g => Mass.baseOn("kilo",$input) );
multi postfix:<(g)>( $input where * > 0)
return Mass.new( g => $input );
multi infix:<+>( Mass $inputOne , Mass $inputTwo ) is assoc<right>
return Mass.new( g => $inputOne.g + $inputTwo.g);
multi infix:<->( Mass $inputOne , Mass $inputTwo ) is assoc<right>
return Mass.new( g => $inputOne.g - $inputTwo.g);
multi infix:<*>( Mass $inputOne , Mass $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> ) is tighter( &infix:</>)
return Mass.new( g => $inputOne.g * $inputTwo.g);
multi infix:</>( Mass $inputOne , Mass $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> )
return Mass.new( g => $inputOne.g / $inputTwo.g);
#Length
multi postfix:<(km)>( $input where * > 0)
return Length.new( Length => Length.baseOn("kilo",$input) );
multi postfix:<(m)>( $input where * > 0)
return Length.new( Length => $input );
multi infix:<+>( Length $inputOne , Length $inputTwo ) is assoc<right>
return Length.new( Length => $inputOne.Length + $inputTwo.Length);
multi infix:<->( Length $inputOne , Length $inputTwo ) is assoc<right>
return Length.new( Length => $inputOne.Length - $inputTwo.Length);
multi infix:<*>( Length $inputOne , Length $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> ) is tighter( &infix:</>)
return Length.new( Length => $inputOne.Length * $inputTwo.Length);
multi infix:</>( Length $inputOne , Length $inputTwo ) is assoc<right> is tighter( &infix:<+> ) is tighter( &infix:<-> )
return Length.new( Length => $inputOne.Length / $inputTwo.Length);
#just a test
say 10(kg) + 1(g);
say 10(m) + 1(m);
【讨论】:
以上是关于使用 Perl 6 自定义运算符的主要内容,如果未能解决你的问题,请参考以下文章
Perl:将本地 .pm 文件中的自定义模块“安装”到 Perl 执行环境中?
为 SublimeLinter 添加自定义路径到 Perl 库