develooper Front page | perl.perl6.users | Postings from September 2018

Coercion/type checking: manually reproduce Perl6 standards

Thread Next
From:
Vadim Belman
Date:
September 2, 2018 00:34
Subject:
Coercion/type checking: manually reproduce Perl6 standards
Message ID:
15047F0E-E65C-4AC3-B5DF-7B4CCA53082A@lflat.org
Hi everybody,

I'm just transferring here a StackOverflow topic https://stackoverflow.com/questions/52117678/coercion-type-checking-manually-reproduce-perl6-standards because what was a question over there turned immediately into a discussion which doesn't fit into SO format. Not sure if I gonna get any concrete answers. But hope to make it a food for thought about some of the language rough edges I stumbled upon over the last month or so. Also please keep in mind that despite my 20 years with Perl 5 I'm a complete newby in Perl 6 with roughly just 2.5 months of real life use on my hands.

First of all, I would like to answer the most important question raiph (sorry, don't know your real name) has asked me: why? 

My motivation for writing AttrX::Mooish was very much strait-forward: I have a work project on my hands which I wanna implement in Perl6. Yet, I have an internal framework for such projects written in Perl 5. I wanted to adapt the framework for the new language because me trying to avoid intermixing Perl5 and Perl6 as much as it only possible. Since the framework is based on Moo and utilizing all the lazy, triggers, etc. stuff it was desirable to get it all for Perl6. Of all Moo's functionality the existing Perl6 modules were only about laziness and their implementation wasn't even close resembling Moo/Moose behavior.

So, the key point of my module: I needed it a month ago. Hopefully, this sufficiently explains the approach I chose.

Now, on the decisions I made while implementing it.

First of all, I wanted to make the module as transparent for a user a possible. It basically means that one should not be worried much about using 'is mooish' trait and what side effects would it cause to his code. This is why Proxy is used as an attribute container. It allows for using of auto-generated accessors or user-provided ones without extra headache of how to deal with conflicts. It's being said that Proxy is problematic in many aspects, but it would be eventually fixed, wouldn't it? So far it does the job for me.

This is where I get to the original point of SO subject. It is clear that with Proxy I had to use an external storage for attribute values. It also means that the default Perl's coercion and type checking rules are not applicable. But as it was told above, I wanted

has Str @.a;

and

has Str @.a is mooish(...);

to be totally identical. Which is non-trivial as in the second case the actual array would be stored as value in a hash (the external storage). This is why mimicking the default Perl's rules had to be done manually by AttrX::Mooish. I wish I could re-delegate it to Perl6 itself, but so far my research of the core source didn't provide any useful results. Though, frankly, I didn't have enough time for it. (While writing this I have achieved an acceptable level of compatibility which allows me to proceed with the main project.)

Hope the above answers most of raiph questions. Now, I'd try to answer a couple of others.

Aiui the existing implementation of Proxys suffers from repeated calls. So a read or write can happen several times where you might expect only one.

So far, I only seen this bug with say. And no, this is not the problem.

What is confusing me is that it's the second time I get advised against use of Proxy because of its problems. Is it a first-class member of Perl6 class family or is it just a play toy? 

my Array[Str] $a = ["a", "b", "c"];
my Str @a = ["a", "b", "c"];

Regarding the explanations on differences between these two lines. Well, when you explain this it makes sense. But look at the situation from the decent user (which is what I am most of the time) perspective. He takes the second line, sees that it works as excepted. Then he takes what @a.WHAT reports back and sees that it is actually Array[Str]. He tries the first line and... boomer? "Type check failed in assignment to $a; expected Array[Str] but got Array"!! What??? On SO raiph says:

because the = is doing list assignment, i.e. assigning each of the elements on the right into a Str type constrained Scalar on the left and all of those assignments pass the individual scalar type checks. 

But this difference between list and scalar assignment isn't mentioned anywhere on docs.perl6.org. All one can find is that they exists and have different precedence. Otherwise the difference between the two assignments is quite counterintuitive and, to my view, it contradicts to DWIM.

Similar case is with Array ~~ List against List ~~ Array. If for any reason one needs to test if a value could be assigned to a container prior to the actual assignment it would really be hard to grasp for the first time why my @a = <a b c> works whereas my Array $a = <a b c> fails.

PS. BTW, while researching the core sources I discovered a potential problem with DefiniteHOW and SubsetHOW. They both define their own find_method() which is re-delegating to their base type HOW.find_method. But they don't support named parameters. Combined with classes with FALLBACK this may cause some unwanted side-effects. Shall it be reported as a bug? (BTW, quick grepping has also found RolePunning, MethodDelegation with potentially same problem).

Best regards,
Vadim Belman


Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About