Re: I need help setting up a method

2020-12-19 Thread ToddAndMargo via perl6-users

On 12/19/20 8:21 PM, Bruce Gray wrote:

With a custom `new` method, that could be shortened further to:
say BadMath.new(2, 2).BadAdd;


print BadMath.new(2, 2).BadAdd ~ "\n";
Default constructor for 'BadMath' only takes named arguments
  in block  at  line 1

What am I missing?


I need help understanding ".contains" method construction

2020-12-19 Thread ToddAndMargo via perl6-users

Hi All,

https://github.com/rakudo/rakudo/blob/master/src/core.c/Str.pm6

337:multi method contains(Str:D: Str:D $needle --> Bool:D) {

338:nqp::hllbool(nqp::isne_i(nqp::index($!value,$needle,0),-1))
339:}

I "presume" in

 "abcd".contains("bc")

"abcd" is `$!value`, and

"bc" is $needle.  Do I presume correctly?


Questions:

1) why is it "$needle" and not "$!needle" on line 338?
   Is this because it is an internal variable and not
   a variable from the class declaration?

2) where is variable ".value" defined on line 338?
   What kind of variable is .value?

3) the first "Str:D" goes to what on line 337?  To .value?

4) Is .value the default, if there is no name given?

Many thanks,
-T


Re: I need help setting up a method

2020-12-19 Thread ToddAndMargo via perl6-users

On 12/19/20 8:21 PM, Bruce Gray wrote:




On Dec 19, 2020, at 6:40 PM, ToddAndMargo via perl6-users 
 wrote:

Hi All,

I have so far:


   class BadMath {
   has Int $.A;
   has Int $.B;

   method BadAdd()  {
  my $Clinker = (-5..5).rand.truncate;
  return $!A + $!B + $Clinker;
   }
   }


   my $TwoPlusTwo = BadMath.new( A => 2, B=> 2 );
   print $TwoPlusTwo.BadAdd ~ "\n";


How do I modify the declaration such that I can
address the method as such?

 say (2,2).BadAdd;
 No such method 'BadAdd' for invocant of type 'List'


I want my 10 in 11 chance to win a participation trophy!

Many thanks,
-T


You cannot do that.
(Except that you *technically* can, but shouldn't; see 
https://docs.raku.org/syntax/augment , which shows how to do it, and also says 
..."strongly discouraged. For almost all situations, there are better 
solutions.")

You can combine the object creation and the method call in one statment:
say BadMath.new( A => 2, B=> 2 ).BadAdd;
With a custom `new` method, that could be shortened further to:
say BadMath.new(2, 2).BadAdd;
But your desired syntax (`(2,2).BadAdd`) seems to hinge on never moving (2,2) 
into a BadMath object.
To make that work, you would have to add the `BadAdd` method to Raku's built-in 
List type via `MONKEY-TYPING` and `augment`.
Very highly non-recommended.

We do have `.&` syntax for when you want to call a sub like a method:
sub BadAdd ( ($a, $b) ) {   # Notice the extra parentheses
$a + $b + (-5..5).rand.truncate;
}
#   say (2,2).BadAdd;   # Will fail
say (2,2).  # Works!
You get to use BadAdd *almost* like a method, and you do not need to define a 
Class or any other OO stuff.

We also offer easy do-it-yourself custom operators:
multi sub infix:<+bad+> ($a, $b) {
return $a + $b + (-5..5).rand.truncate;
}
say 2 +bad+ 2;  # Said '6' when I ran it.

The `.&` syntax or user-defined operator are the best I can offer at the moment.
This may be a XY problem. If not, more info on your intended use case may 
inspire other ideas..
https://xyproblem.info/

By the way, `(-5..5).rand.truncate` does not do what it appears to do, so 
either it is calculating incorrectly, or it will be confusing to any future 
maintenance programmer.
$ raku -e 'my %h = bag map {(-5..5).rand.truncate}, ^100_000; .say for 
%h.sort(+*.key);'
 -4 => 9892
 -3 => 9972
 -2 => 9889
 -1 => 10072
 0 => 20126  # !!! Twice the average of the rest!
 1 => 10029
 2 => 9943
 3 => 10053
 4 => 10024
A reader would see that -5 and 5 are the endpoints, but the effect of 
`rand.truncate` is to produce integers ±4 , not ±5.
Also, 0 has twice the chance of occurring as any other number.
For the behaviour that I suspect you want (a unweighted random integer between 
-5 and 5), use:
(-5..5).pick
If the current behavior is really what you want, then the code would be less 
mystifying as:
(0, |(-4..4)).pick

For more detail on Raku Randomess, you might enjoy the first third of my 2018 
talk:
https://www.youtube.com/watch?v=DJCp6k1ts3g
Perl 6 and the Emergent Program.*
3m22s - 13m33s




Thank you!

I was not after ±5 specifically, just a bad
answer.





--
~~
Computers are like air conditioners.
They malfunction when you open windows
~~


Re: I need help setting up a method

2020-12-19 Thread Bruce Gray



> On Dec 19, 2020, at 6:40 PM, ToddAndMargo via perl6-users 
>  wrote:
> 
> Hi All,
> 
> I have so far:
> 
> 
>   class BadMath {
>   has Int $.A;
>   has Int $.B;
> 
>   method BadAdd()  {
>  my $Clinker = (-5..5).rand.truncate;
>  return $!A + $!B + $Clinker;
>   }
>   }
> 
> 
>   my $TwoPlusTwo = BadMath.new( A => 2, B=> 2 );
>   print $TwoPlusTwo.BadAdd ~ "\n";
> 
> 
> How do I modify the declaration such that I can
> address the method as such?
> 
> say (2,2).BadAdd;
> No such method 'BadAdd' for invocant of type 'List'
> 
> 
> I want my 10 in 11 chance to win a participation trophy!
> 
> Many thanks,
> -T

You cannot do that.
(Except that you *technically* can, but shouldn't; see 
https://docs.raku.org/syntax/augment , which shows how to do it, and also says 
..."strongly discouraged. For almost all situations, there are better 
solutions.")

You can combine the object creation and the method call in one statment:
say BadMath.new( A => 2, B=> 2 ).BadAdd;
With a custom `new` method, that could be shortened further to:
say BadMath.new(2, 2).BadAdd;
But your desired syntax (`(2,2).BadAdd`) seems to hinge on never moving (2,2) 
into a BadMath object.
To make that work, you would have to add the `BadAdd` method to Raku's built-in 
List type via `MONKEY-TYPING` and `augment`.
Very highly non-recommended.

We do have `.&` syntax for when you want to call a sub like a method:
sub BadAdd ( ($a, $b) ) {   # Notice the extra parentheses
$a + $b + (-5..5).rand.truncate;
}
#   say (2,2).BadAdd;   # Will fail
say (2,2).  # Works!
You get to use BadAdd *almost* like a method, and you do not need to define a 
Class or any other OO stuff.

We also offer easy do-it-yourself custom operators:
multi sub infix:<+bad+> ($a, $b) {
return $a + $b + (-5..5).rand.truncate;
}
say 2 +bad+ 2;  # Said '6' when I ran it.

The `.&` syntax or user-defined operator are the best I can offer at the moment.
This may be a XY problem. If not, more info on your intended use case may 
inspire other ideas..
https://xyproblem.info/

By the way, `(-5..5).rand.truncate` does not do what it appears to do, so 
either it is calculating incorrectly, or it will be confusing to any future 
maintenance programmer.
$ raku -e 'my %h = bag map {(-5..5).rand.truncate}, ^100_000; .say for 
%h.sort(+*.key);'
-4 => 9892
-3 => 9972
-2 => 9889
-1 => 10072
0 => 20126  # !!! Twice the average of the rest!
1 => 10029
2 => 9943
3 => 10053
4 => 10024
A reader would see that -5 and 5 are the endpoints, but the effect of 
`rand.truncate` is to produce integers ±4 , not ±5.
Also, 0 has twice the chance of occurring as any other number.
For the behaviour that I suspect you want (a unweighted random integer between 
-5 and 5), use:
(-5..5).pick
If the current behavior is really what you want, then the code would be less 
mystifying as:
(0, |(-4..4)).pick

For more detail on Raku Randomess, you might enjoy the first third of my 2018 
talk:
https://www.youtube.com/watch?v=DJCp6k1ts3g
Perl 6 and the Emergent Program.*
3m22s - 13m33s

-- 
Hope this helps,
Bruce Gray (Util of PerlMonks)


Checking for nil return

2020-12-19 Thread yary
Is this a known issue, or my misunderstanding?

> subset non-Nil where * !=== Nil;
(non-Nil)
> sub out-check($out) returns non-Nil { return $out }

> out-check(44)
44
> out-check(Nil)
Nil

^ Huh, I expected an exception on "out-check(Nil)" saying the return value
failed the "returns" constraint.

The subtype works as I expect as an the argument check

> sub in-check (non-Nil $in) { $in }

> in-check(33)
33
> in-check(Nil)
Constraint type check failed in binding to parameter '$in'; expected
non-Nil but got Nil (Nil)
  in sub in-check at  line 1
  in block  at  line 1

$ raku --version
This is Rakudo version 2020.07 built on MoarVM version 2020.07
implementing Raku 6.d.

Is this my understanding of return type checking that's off, or a known
issue, or something I should add to an issue tracker?

-y


Re: Missing NullPointerException

2020-12-19 Thread yary
Going back to Dec 3rd explanation:

"... I had a chain of methods which should do some side effect.
It all went fine only the side effect was not there. I then figured
out after some time that one of methods returned Nil and
somehow silently it did not do what I expected."

This looks like an incomplete set of rules – an API contract that needs
filling in – more than a language issue. From the illustrative example now
in play

$drone.engine.start;

the original code as described in the Dec 3rd extract above, implies these
rules:

Each method
- has a side effect on success, no side effect on failure.
- returns a defined object on success. return behavior on failure not
explicitly defined.
Expectation- failure should show more than lack of side effects plus Nil
return value at final step.

Now if all of the "$drone" object/class, the "engine" method, and the
"start" method are app code, then we can fill out the contract so that
$drone.engine.start does the right thing. If on the other hand it was a
Rakudo call which returned Nil instead of failing, then there is a language
issue. Which is what E.M. posted on Dec 3rd:

Nil is really a Failure that doesn't throw.  It indicates the absence of a
> value where there is one expected.
> That is why Nil doesn't throw.  If you want to indicate a soft failure,
> you should use fail().
> If the chain of methods you mention are core methods, and one of them is
> returning Nil, then perhaps we have a bug.  Could you elaborate on the
> situation where you encountered this?


For the sake of discussion, let's fill out the contract each method adheres
to. Side effect has no change
- has a side effect on success, no side effect on failure.

To fulfill the expectation that a failure anywhere "shows up" early, there
are a few tweaks available.
1. On failure, method throws an exception/"die"s -
https://docs.raku.org/language/exceptions
2. On failure, method returns an failure object -
https://docs.raku.org/type/Failure
3. Methods never return Nil. - requires a little work to check at the
returns.

Any of those will make a failure show up closer to where it happened.

I can only recommend #3 in the case where there must be an engine.

A slight modification to the example can show why a method may want to
return Nil on success, and also show that the behavior of Nil with method
calls is actually rather useful:

$drone.wheels.lock;

If a drone has no wheels, the "wheels" method returns Nil and the code
still works. For a drone with wheels, it can throw an exception or return a
failure if there's a problem with the "wheels" method– or if the brakes
don't work, then "lock" can die or return a failure.

-y


On Fri, Dec 18, 2020 at 12:58 PM Konrad Bucheli via perl6-users <
perl6-us...@perl.org> wrote:

>
>
> On 16.12.20 12:39, Brad Gilbert wrote:
> >  with $drone.engine {
> >  .start;
> >  say "engine started";
> >  }
>
> Now we get the inverse pyramid of doom. Above code does not the same as
> mine, it only improves the debugging output, but does not fail:
>
>   with $drone.engine {
>   .start;
>   say "engine started";
>   }
>   orelse {
>   die "looks like we lost the engine";
>   }
>
> My point is that I never expected the engine to be lost, because it is
> an integral part of the drone. And that is correct because it was only a
> bug in `engine` which was revealed during testing and when fixed I do
> not need all this any more.
>
> So to understand all the implications of
>
>  $drone.engine.start;
>
> I need in depth Raku understanding. Is that already tribal knowledge?.
> Or you have already been hurt by it as I was. It is definitively not
> beginner friendly and not even intermediate friendly.
>
> I feel uncomfortable with that. Whenever I see something like this I
> have to be aware that the normally obvious assumptions are incorrect.
> These bugs are more difficult to find because the program continues and
> only later on you will see that some data or state is incorrect. And the
> problem with incorrect data is that you might not even spot it.
>
>
> >
> > On Tue, Dec 15, 2020, 11:10 PM Konrad Bucheli via perl6-users
> > mailto:perl6-us...@perl.org>> wrote:
> >
> >
> > Hi Ralph
> >
> > Thanks a lot for the extensive answer.
> >
> > I still consider it a trap because it does not do what it tells it
> does.
> >
> > If I have:
> >
> > say "launching drone";
> > $drone.engine.start;
> > say "engine started";
> >
> > After I run the above I got both messages, but no propeller
> > spinning. So I checked start() in and out, because that is where the
> > problem is obviously.
> > But it was not, it was in engine().
> > And I want my programming language/runtime to tell me if I am doing
> > obviously stupid things.
> > Note that it has nothing to do with the "pyramid of doom". It would
> > make sense in a pure functional environment, but Raku is
> > 

Re: How do I address individual elements inside an object

2020-12-19 Thread ToddAndMargo via perl6-users

On 12/19/20 4:49 PM, Brad Gilbert wrote:

You can interpolate a method call in a string, but you need the parens.

     say "$FruitStand.location() has $FruitStand.apples() apples in stock";


Cool!  Now four ways of doing it:

  print $FruitStand.location ~ "has " ~ $FruitStand.apples ~" 
apples in stock\n";


  print "Fruitstand in {$FruitStand.location} has 
{$FruitStand.apples} apples\n";


  print "Fruitstand in ", $FruitStand.location,  "has ", 
$FruitStand.apples, " apples\n";


  print "$FruitStand.location() has $FruitStand.apples() apples in 
stock";


Re: How do I address individual elements inside an object

2020-12-19 Thread Brad Gilbert
You can interpolate a method call in a string, but you need the parens.

say "$FruitStand.location() has $FruitStand.apples() apples in stock";

On Sat, Dec 19, 2020 at 4:28 AM Laurent Rosenfeld via perl6-users <
perl6-us...@perl.org> wrote:

> Yeah, right. $FruitStand.apples is not a direct access to the attribute,
> but a method invocation (a call to a method implicitly created by Raku), so
> it doesn't get interpolated within the string. So it should be outside the
> string or used with a code interpolation block.
>
> For example:
>
> say "Fruitstand in {$FruitStand.location} has {$FruitStand.apples}
> apples.";
>
> or
>
> say "Fruitstand in ", $FruitStand.location,  "has ", $FruitStand.apples,
> " apples.";
>
> or the construct with the ~ concatenation operator that you used.
>
> Cheers,
> Laurent..
>
>
> 
>  Garanti
> sans virus. www.avast.com
> 
> <#m_8010816652420510664_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>
> Le ven. 18 déc. 2020 à 23:55, ToddAndMargo via perl6-users <
> perl6-us...@perl.org> a écrit :
>
>> On 12/18/20 9:42 AM, William Michels via perl6-users wrote:
>> > Hi Laurent, I get:
>> >
>> > Fruitstand in Fruit<140431957910656>.location has
>> >   Fruit<140431957910656>.apples apples.
>> >
>> > [Rakudo v2020.10]
>> >
>> > Best, Bill.
>> >
>>
>> Hi Bill,
>>
>>  From my notes in progress:
>>
>> -T
>>
>>
>> *** addressing values inside and object ***
>>
>> Reading:
>>say $FruitStand.apples
>>400
>>
>>$FruitStand.apples.say
>>400
>>
>>print $FruitStand.location ~ " has " ~ $FruitStand.apples ~"
>> apples in stock\n";
>>Cucamonga has 400 apples in stock
>>
>>Note: an "oops!".  Separate the variables from the string, or else:
>>say "$FruitStand.location has $FruitStand.apples apples in
>> stock";
>>Fruit<79300336>.location has Fruit<79300336>.apples apples in
>> stock
>>
>>Writing (must be declared as "rw"):
>>
>


I need help setting up a method

2020-12-19 Thread ToddAndMargo via perl6-users

Hi All,

I have so far:


   class BadMath {
   has Int $.A;
   has Int $.B;

   method BadAdd()  {
  my $Clinker = (-5..5).rand.truncate;
  return $!A + $!B + $Clinker;
   }
   }


   my $TwoPlusTwo = BadMath.new( A => 2, B=> 2 );
   print $TwoPlusTwo.BadAdd ~ "\n";


How do I modify the declaration such that I can
address the method as such?

 say (2,2).BadAdd;
 No such method 'BadAdd' for invocant of type 'List'


I want my 10 in 11 chance to win a participation trophy!

Many thanks,
-T


Re: How do I address individual elements inside an object

2020-12-19 Thread ToddAndMargo via perl6-users

apples.";


Is the "." at the end of the apples literal or syntax?


Re: How do I address individual elements inside an object

2020-12-19 Thread William Michels via perl6-users
Great, Laurent!
Works fine (and Todd's as well).
Thank you for the explanation.

--B.

On Sat, Dec 19, 2020 at 2:27 AM Laurent Rosenfeld via perl6-users <
perl6-us...@perl.org> wrote:

> Yeah, right. $FruitStand.apples is not a direct access to the attribute,
> but a method invocation (a call to a method implicitly created by Raku), so
> it doesn't get interpolated within the string. So it should be outside the
> string or used with a code interpolation block.
>
> For example:
>
> say "Fruitstand in {$FruitStand.location} has {$FruitStand.apples}
> apples.";
>
> or
>
> say "Fruitstand in ", $FruitStand.location,  "has ", $FruitStand.apples,
> " apples.";
>
> or the construct with the ~ concatenation operator that you used.
>
> Cheers,
> Laurent..
>
>
> 
>  Garanti
> sans virus. www.avast.com
> 
> <#m_8427144409934787973_DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>
>
> Le ven. 18 déc. 2020 à 23:55, ToddAndMargo via perl6-users <
> perl6-us...@perl.org> a écrit :
>
>> On 12/18/20 9:42 AM, William Michels via perl6-users wrote:
>> > Hi Laurent, I get:
>> >
>> > Fruitstand in Fruit<140431957910656>.location has
>> >   Fruit<140431957910656>.apples apples.
>> >
>> > [Rakudo v2020.10]
>> >
>> > Best, Bill.
>> >
>>
>> Hi Bill,
>>
>>  From my notes in progress:
>>
>> -T
>>
>>
>> *** addressing values inside and object ***
>>
>> Reading:
>>say $FruitStand.apples
>>400
>>
>>$FruitStand.apples.say
>>400
>>
>>print $FruitStand.location ~ " has " ~ $FruitStand.apples ~"
>> apples in stock\n";
>>Cucamonga has 400 apples in stock
>>
>>Note: an "oops!".  Separate the variables from the string, or else:
>>say "$FruitStand.location has $FruitStand.apples apples in
>> stock";
>>Fruit<79300336>.location has Fruit<79300336>.apples apples in
>> stock
>>
>>Writing (must be declared as "rw"):
>>
>


Re: How do I address individual elements inside an object

2020-12-19 Thread Laurent Rosenfeld via perl6-users
Yeah, right. $FruitStand.apples is not a direct access to the attribute,
but a method invocation (a call to a method implicitly created by Raku), so
it doesn't get interpolated within the string. So it should be outside the
string or used with a code interpolation block.

For example:

say "Fruitstand in {$FruitStand.location} has {$FruitStand.apples} apples.";

or

say "Fruitstand in ", $FruitStand.location,  "has ", $FruitStand.apples, "
apples.";

or the construct with the ~ concatenation operator that you used.

Cheers,
Laurent..


Garanti
sans virus. www.avast.com

<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

Le ven. 18 déc. 2020 à 23:55, ToddAndMargo via perl6-users <
perl6-us...@perl.org> a écrit :

> On 12/18/20 9:42 AM, William Michels via perl6-users wrote:
> > Hi Laurent, I get:
> >
> > Fruitstand in Fruit<140431957910656>.location has
> >   Fruit<140431957910656>.apples apples.
> >
> > [Rakudo v2020.10]
> >
> > Best, Bill.
> >
>
> Hi Bill,
>
>  From my notes in progress:
>
> -T
>
>
> *** addressing values inside and object ***
>
> Reading:
>say $FruitStand.apples
>400
>
>$FruitStand.apples.say
>400
>
>print $FruitStand.location ~ " has " ~ $FruitStand.apples ~"
> apples in stock\n";
>Cucamonga has 400 apples in stock
>
>Note: an "oops!".  Separate the variables from the string, or else:
>say "$FruitStand.location has $FruitStand.apples apples in
> stock";
>Fruit<79300336>.location has Fruit<79300336>.apples apples in
> stock
>
>Writing (must be declared as "rw"):
>