Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

perl6 custom operator problem

by freakcoco (Sexton)
on Mar 28, 2017 at 09:07 UTC ( [id://1186215]=perlquestion: print w/replies, xml ) Need Help??

freakcoco has asked for the wisdom of the Perl Monks concerning the following question:

hi monk I am studying chemistry in the university,
and then I try to write all the things in the textbook with Perl6 or Perl,
like balancing the chemical formula or other process!
Then I encountered the problem is on perl6 custom operator.
I feel I have been repeating my code and myself when i use the feature.
It is hard to read and write, and what is the way to deal with such problems?

#!/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 Mu +st 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 fai +l "you Must input a number"; } multi postfix:<(m)>( $input ) { return Length.new( Length => $input ) or fail "you Must input a nu +mber"; } 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);

Replies are listed 'Best First'.
Re: perl6 custom operator problem
by NetWallah (Canon) on Mar 28, 2017 at 23:54 UTC
    This could help you improve "MetricPrefix":
    my %to_num = map { $_[0]=> 10**$_[1] }, (qw|pico nano micro milli centi hecto kilo mega giga tera| Z (-12, {$_+3}... -3,-2,2,3,{$_+3}... 12)) ;
    Uses "Lazy lists" and the Zip (Z) operator.

    I'm still learning p6, and I agree - there HAS to be a better way to avoid all that boilerplate code, so I'll keep a watch for responses.

            ...it is unhealthy to remain near things that are in the process of blowing up.     man page for WARP, by Larry Wall

Re: perl6 custom operator problem
by bduggan (Pilgrim) on Mar 29, 2017 at 02:24 UTC
    A few ideas:
    • A few enums could make sense in this situation, depending on what syntax you are aiming for
    • I'm not sure that you need to specify the associativity and precedence when they are the same as the default for those operations
    • A postcircumfix operator would allow you to send things like 'kg' as a parameter
    • I'm not sure you need to list the submethod BUILD since it behaves like the default
    • You can avoid some redundancy in defining your operators if Mass and Length have a common ancestor

    Here's another version that accomplishes something similar:
    enum Prefixes ( :pico(10.0 ** -12), :nano(10.0 ** -9), :micro(10.0 ** -6), :milli(10.0 ** -3), :centi(10.0 ** -2), :one(1.0), :hecto(10.0 ** 2), :kilo(10.0 ** 3), :mega(10.0 ** 9), :giga(10.0 ** 9), :tera(10.0 ** 12), ); enum MassAbbrevs ( :g(one), :kg(kilo) ); enum LengthAbbrevs ( :m(one), :km(kilo) ); class SI { } class Mass is SI { has $.v; } class Length is SI { has $.v; } multi postcircumfix:<[ ]>(Real $n, MassAbbrevs $abbrev ) { return Mass.new(v => $n * $abbrev); } multi postcircumfix:<[ ]>(Real $n, LengthAbbrevs $abbrev ) { return Length.new(v => $n * $abbrev); } multi infix:<+>( SI $x , SI $y where .isa($x) ) { $x.WHAT.new( v => $x.v + $y.v); } say 10[kg] + 1[g]; say 1[km] + 1[m];

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1186215]
Approved by haukex
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others admiring the Monastery: (7)
As of 2024-04-19 06:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found