Sneaky Arguments
While playing with .WHY
I stepped onto an ENODOC. Method refers to Signature. Both fail to mention the default signature of a method. The documentation of automatic signatures fails to mention that %_
is always added to methods. Asking greppable6 for mentioning of it revealed plenty of redundant uses of *%_
in methods.
my method m1(:$named) {}
my method m2(:$named, *%_) {}
say &m1.signature;
say &m2.signature;
# OUTPUT: (Mu: :$named, *%_)
(Mu: :$named, *%_)
The reason why I spotted this is .WHY
. In Raku we can add comments that are attached to the language objects that follow them.
class Commented {
#| this is an attribute
has $.a-documented-attribute;
#| this is a method
method works {
say ‚working as intended‘;
}
}
say $c.^can('works')[0].WHY;
say $c.^attributes[0].WHY;
# OUTPUT: this is a method
this is an attribute
The docs fail to state how to access WHY
-nodes for attributes and methods at runtime. We have to go through the MOP here because methods and attributes can be added to a type object at runtime. At least for methods I found a nicer way to handle this.
method works {
return &?ROUTINE.WHY if %_;
say ‚working as intended‘;
}
put $c.works(:why);
Oddly, this leads to the awkward situation that I add an undocumented argument to a method that returns the documentation for that method. To be explicit we got the trait is implementation-detail
. Being forced to use a multi makes things more cumbersome though.
#| No comment! We are sneaky!
multi method sneaky { say ‚working as intended‘ }
multi method sneaky('why') is implementation-detail {
return self.^lookup('sneaky').candidates[0].WHY;
}
say $c.sneaky('why');
That leaves the question why I need .WHY
on attributes. I do agree with the assessment that JSON is lacking in general. My biggest objection is the lack of comments. For config files being able to tell a co-worker to keep his dirty fingers of a certain line can save lives. Debian is making good use of comments in such files too. It can save a lot of time if you don’t have to read a man page just to change one value. With inline comments on attributes I could express both the structure of data stored in a config file and instructions how to use the config file without another HEREDOC that can get out if sync with the actual code. I really like the structure of NestedText and am playing with adding type information. In NestedText leafs default to Str
so that can be omitted. In Raku we get string representations for types for free, we can just add them as text.
I can define the structure of my config file as follows.
use Data::TypedNestedText;
class Phone {
has $.mobile;
has $.home;
has $.office;
}
class Contact {
has $.name;
#| this can be multiline
has $.address;
has $.phone;
has @.additional-roles;
}
For the output I wrote a naive deparser that can produce a NestedText with type annotations.
president[Contact]:
# this can be multiline
address:
> 138 Almond Street
> Topika, Kansas 20697
name: Katheryn McDaniel
phone[Phone]:
home: 1-210-555-8470
mobile: 1-210-555-5297
treasurer[Contact]:
# this can be multiline
address:
> 3636 Buffalo Ave
> Topika, Kansas 20692
name: Fumiko Purvis
phone[Phone]:
office: 1-268-555-0280
additional-roles:
- hug task force
- Christmas party team
This is much easier to read and edit then JSON. Writing the parse might not. I will report back shortly if it turns out to be easier then expected.
-
October 12, 2020 at 21:102020.41 A First Year – Rakudo Weekly News