Futher to Timo's explanation, below is a rewrite of your code to consider.

The documentation reference is https://docs.perl6.org/language/classtut#Constructors

class Etran {
        has $.dstamp is rw;
        has $.folio is rw;
        has $.ticker is rw;
        has $.way; # only used at initialisation
        has $.qty is rw;
        has $.amount is rw;
        has $.desc is rw;

        submethod BUILD ( :$!dstamp, :$!folio, :$!ticker, :$!qty, :$!amount, 
:$!way = 'B', :$!desc ) {
                $!qty = -$!qty if $!way ne 'B'; # set $way default to 'B' in 
signature
        }
} # end of class declaration
# your new does not use $cmd, so I omitted it

# in program

my Etran $transaction .= new( :dstamp('some value'), :folio('another val'),
        :qty( 15 ), :ticker( 'AXB' ), :amount( 4000 ), :desc('not alot') );
say $transaction;
my Etran $dummy .= new(:dstamp('some value'), :folio('another val'),
        :qty( 15 ), :ticker( 'AXB' ), :amount( 4000 ), :desc('not alot') , 
:way('C'));
say $dummy;
# no information given about shlex-fields, but it need to return a list of 
named pairs,

# running the code above results in
# Etran.new(dstamp => "some value", folio => "another val", ticker => "AXB", way => "B", qty => 
15, amount => 4000, desc => "not alot")
# Etran.new(dstamp => "some value", folio => "another val", ticker => "AXB", way => "C", qty => 
-15, amount => 4000, desc => "not alot")

...

The only reason BUILD is needed is because $!qty is initialised from :qty and :way.

If there was no special intialisation, then no BUILD would be needed.


Timo explained the underlying reason, but the way I think of the difference between ! and . twiggles is that if you specify eg "has $.folio" in the class then perl6 creates a getter and setter automatically, so that when you have an instance of the class (eg. $transaction in my snippet), then you can write code as:
$transaction.folio = "arbitrary thing";

# if you don't use the attribute on left, then there is no need for the "is rw" trait in the declaration.

my $val = $transaction.folio; # these are automatically created methods in the class.

...

If you had specified "has $!folio" in the class, then later in the program $transaction.folio is undefined.

However, the getter/setter methods are created towards the end of the class creation process, and so they are not available to new or BUILD.

But within the class definition code (for example the BUILD submethod or a method called new), $!folio is always available, even if it is specified by "has $.folio".

Timo mentioned that your method new needs an explicit 'self.bless'.

There should be no need to create a 'new' method for a class because one is created automatically using the BUILD submethod (if it exists), and if you haven't provided one, perl6 creates one for you.

Hope this helps.



On Thursday, July 20, 2017 05:51 PM, Mark Carter wrote:

I have a class definition:

class Etran {
         has $.dstamp is rw;
         has $.folio is rw;
         has $.ticker is rw;
         has $.qty is rw;
         has $.amount is rw;
         has $.desc is rw;

         method new($line) {
                 my ($cmd, $dstamp, $folio, $ticker, $qty, $amount, $way, 
$desc) = shlex-fields $line;
                 $!dstamp = $dstamp;
                 $!folio = $folio;
                 $!ticker = $ticker;
                 $!qty = $way == "B" ?? $qty !! - $qty;
                 $!amount = $amount;
                 $!desc = $desc;
         }

}**
which I instantiate with
        my $e = Etran.new($line);

However, it gives an error message:
        Cannot look up attributes in a Etran type object
at the line
        $!dstamp = $dstamp;

Why that, and how do I fix it?

Also, I don't really understand the difference between using the twigils "." and using 
"!",
and have yet to see an explanation that I understand.

Reply via email to