Well, this is disappointing.

2023-10-02 Thread Sean McAfee
A little while ago I developed a Raku program to look up file ownership in
a Github CODEOWNERS file.  My first attempt worked by converting the
glob-like CODEOWNERS patterns into regexes, eg:

app/views/**/*.rb --> /^ 'app/views/' [<-[/]>+]* % '/' '/' <-[/]>* '.rb' $/

Surprisingly, this approach was so slow as to be a non-starter, no matter
how I tweaked it.  So, I wrote another implementation that uses a recursive
subroutine to compare path components against the CODEOWNERS patterns.
Originally it was a series of multi subs, but I recast it as a single sub
when I thought that might make it faster:

sub matches(@strs, @patterns) {
if @patterns ~~ ('',) {
True;
} elsif @patterns ~~ ('**', **) {
?grep { matches @strs[$_..*], @patterns[1..*] }, @strs.keys;
} elsif @strs && @patterns {
my $str = @strs[0];
my $pattern = @patterns[0];
do if $pattern.contains('*') {
my @words = $pattern.split('*');
$str.starts-with(@words[0]) && $str.ends-with(@words[*-1]) &&
sub has-words($start, [$word, *@rest]) {
my $n = $str.index($word, $start);
$n.defined && (!@rest || has-words($n + $word.chars, @rest))
}(0, @words);
} else {
$str eq $pattern;
} && matches @strs[1..*], @patterns[1..*];
} else {
@strs == @patterns == 0;
}
}

Instead of using a regex to match the asterisk wildcard pattern, I split
the pattern into asterisk-delimited chunks, then check that the test string
starts with the first chunk, that it ends with the last one, and that the
chunks occur in the string in order and without overlapping.  (Real
CODEOWNERS patterns can have a question mark wildcard, but my company
doesn't use any and so I've omitted that case here for simplicity.)

This seemed to work well enough for me.  It could look up a single filename
in our ≈900 line CODEOWNERS file in about a second.  More than that to look
up all of the files in a modest-sized pull request, but still tolerable.
Then I decided I wanted to share my work with the rest of my company.  The
high-level language of choice here is Ruby, so I translated the above code
into it and tried it out.

I expected rough parity, but the Ruby version *killed* the original Raku
version.  Checking the ownership of a hundred files takes the Ruby version
about a quarter of a second; Raku takes *ten times as long.*

I was flabbergasted.  Although it seemed futile, I looked for ways to speed
up the Raku version.  Surprisingly, I found one right away.  I've rarely
employed smart-matching with arrays as I do with @patterns in the first two
branches above, but to make sure the Raku version had exactly the same
logic as in Ruby, I rewrote them:

if @patterns ~~ ('',) --> if @patterns == 1 && @patterns[0] eq ''
if @patterns ~~ ('**', **) --> if @patterns && @patterns[0] eq '**'

This change cuts the execution time in *half*.  Apparently list
smart-matching is *really, really expensive!*

So that was a big win, but Raku still took five times as long as the Ruby
version.  I couldn't see anything else obvious to try in the matches
subroutine, so I looked at the main loop over the CODEOWNERS lines.  Cut
down a bit, it looks like this:

for $repo-path.add('CODEOWNERS').lines.kv -> $n, $line {
my ($pattern, @owners) = $line.words;
my @patterns = $pattern.split('/');

for %paths.kv -> $file, @path {
if matches(@path, @patterns) {
# record who owns this file
}
}
}

I tried skipping the bulk of the work entirely by changing if
matches(@path, @patterns) to if False.  Of course this shortens the
execution time by a lot...but it still takes twice as long as the Ruby
version that does all of the matching work.

So, yeah.  This was a very disappointing exercise.  I'm posting it here to
share my experience and to vent a bit, but if anyone can see anything I
missed that could significantly pare down the execution time, I'm all ears.


Strange behavior with sequence of functions

2023-06-29 Thread Sean McAfee
I was trying to construct a sequence of functions using the sequence
operator, and encountered some very puzzling behavior.  I was able to
reduce it down to some very simple examples.

[1] > my @s = +*, ->  {  } ... *
[...]
[2] > @s[0]
Too few positionals passed; expected 1 argument but got 0
  in block  at  line 1

I expected that this would create a lazy sequence where the first element
is the WhateverCode function +*, and the generator function ->  {  }
just returns the previous element unchanged.  But it doesn't work that way.

Strangely, I can call any element of this sequence, even the first one that
I supplied explicitly and is somehow unprintable, with any arguments and
get a list of the arguments back:

[3] > @s[0](1, 'x', pi)
(1 x 3.141592653589793)

Here's another couple of odd cases:

[4] > (1, +*, 2, 3, 4 ... *)[^10]
(1 1 1 1 1 1 1 1 1 1)

My experience has led me to expect that the ... operator only uses the list
element immediately preceding it as a generator, so I can't explain this.
Similarly:

[5] > (1, * + 1, 0, 0, 0, * + 2 ... *)[^10]
(1 2 3 4 5 6 7 8 9 10)

It looks like maybe the ... operator looks at the list on its left-hand
side, uses the first callable element it finds as the generator, and
discards everything after that...?  Is that the correct behavior?  Is that
the *intended* behavior?

Oh, actually, I see that the operator doc page
 says that "Custom generators
need to be the last element of the list before the '...' operator."  So, I
guess this is a bug...?

This is all in Rakudo 2023.06.


Re: `lines.contains( / \h / )` returning True for input strings not containing horizonal whitespace

2023-01-26 Thread Sean McAfee
On Thu, Jan 26, 2023 at 12:05 PM William Michels via perl6-users <
perl6-us...@perl.org> wrote:

> ~$ raku -e 'put "1\n2\n3";' | raku -e 'put lines.contains(/ \h /) ?? True
> !! False;'
> True
>

lines() returns a Seq.  The contains method for a Seq coerces its argument
to a Str and calls contains on that Str.  And:

$ raku -e 'put "1\n2\n3"' | raku -e 'put lines.Str'
1 2 3

There's your horizontal whitespace.


Re: $/ not always set after a regex match?

2022-12-30 Thread Sean McAfee
On Fri, Dec 30, 2022 at 4:12 PM The Sidhekin  wrote:

> On Fri, Dec 30, 2022 at 8:51 PM Vadim Belman  wrote:
>
>> It is not "untrue". The sequence you produced goes nowhere. Thus the sink
>> context.
>>
>
>   "Sink context" is true.
>
>   "Useless use" is debatable, at least.
>

 It's not useless because there's a side effect: setting $/.


Re: $/ not always set after a regex match?

2022-12-30 Thread Sean McAfee
Ah, got it, thanks.

It's mildly vexing, but the kind of side-effecty coding I described isn't a
great idea in general.  I only stumbled across the phenomenon while code
golfing.

As a side note, code like this:

sub f { 1 ... * ~~ /9/; $/ }

...produces an untrue warning "Useless use of ... in sink context".  Not
sure if it's worth filing a bug report...

On Wed, Dec 28, 2022 at 12:49 PM Elizabeth Mattijsen  wrote:

> That's because it at one time was decided that smart-match would set $/ in
> the caller's scope.  Which is a pain for implementation and optimizations.
> I would be very much in favour of getting rid of that "feature", fwiw.
>
> > On 28 Dec 2022, at 18:45, Sean McAfee  wrote:
> >
> > But if a sequence has its own $/, why does * ~~ /9/ set $/?
> >
> > Actually it's not just sequences, as a little more experimentation
> showed:
> >
> > [0] > first /9/, ^Inf
> > 9
> > [1] > $/
> > Nil
> > [2] > grep /9/, ^10
> > (9)
> > [3] > $/
> > Nil
> >
> > The * ~~ "trick" sets $/ in these cases too.
> >
> >
> > On Wed, Dec 28, 2022 at 12:01 PM Elizabeth Mattijsen 
> wrote:
> > This isn't specific to the REPL:
> >
> > $ raku -e 'say 1 ... /9/; say $/'
> > (1 2 3 4 5 6 7 8 9)
> > Nil
> >
> > I can only assume that the sequence has its own scope for $/, and thus
> isn't visible outside of it.
> >
> >
> > Liz
> >
> > > On 28 Dec 2022, at 16:47, Sean McAfee  wrote:
> > >
> > > In a fresh 2022.12 Raku REPL, when the endpoint of a sequence is a
> Regex, the $/ variable seems not to be set:
> > >
> > > [0] > 1 ... /9/
> > > (1 2 3 4 5 6 7 8 9)
> > > [1] > $/
> > > Nil
> > >
> > > If I match more explicitly using a WhateverCode, it works:
> > >
> > > [2] > 1 ... * ~~ /9/
> > > (1 2 3 4 5 6 7 8 9)
> > > [3] > $/
> > > 「9」
> > >
> > > Is this the intended behavior, or a bug?
> > >
> >
>
>


Re: $/ not always set after a regex match?

2022-12-28 Thread Sean McAfee
But if a sequence has its own $/, why does * ~~ /9/ set $/?

Actually it's not just sequences, as a little more experimentation showed:

[0] > first /9/, ^Inf
9
[1] > $/
Nil
[2] > grep /9/, ^10
(9)
[3] > $/
Nil

The * ~~ "trick" sets $/ in these cases too.


On Wed, Dec 28, 2022 at 12:01 PM Elizabeth Mattijsen  wrote:

> This isn't specific to the REPL:
>
> $ raku -e 'say 1 ... /9/; say $/'
> (1 2 3 4 5 6 7 8 9)
> Nil
>
> I can only assume that the sequence has its own scope for $/, and thus
> isn't visible outside of it.
>
>
> Liz
>
> > On 28 Dec 2022, at 16:47, Sean McAfee  wrote:
> >
> > In a fresh 2022.12 Raku REPL, when the endpoint of a sequence is a
> Regex, the $/ variable seems not to be set:
> >
> > [0] > 1 ... /9/
> > (1 2 3 4 5 6 7 8 9)
> > [1] > $/
> > Nil
> >
> > If I match more explicitly using a WhateverCode, it works:
> >
> > [2] > 1 ... * ~~ /9/
> > (1 2 3 4 5 6 7 8 9)
> > [3] > $/
> > 「9」
> >
> > Is this the intended behavior, or a bug?
> >
>
>


$/ not always set after a regex match?

2022-12-28 Thread Sean McAfee
In a fresh 2022.12 Raku REPL, when the endpoint of a sequence is a Regex,
the $/ variable seems not to be set:

[0] > 1 ... /9/
(1 2 3 4 5 6 7 8 9)
[1] > $/
Nil

If I match more explicitly using a WhateverCode, it works:

[2] > 1 ... * ~~ /9/
(1 2 3 4 5 6 7 8 9)
[3] > $/
「9」

Is this the intended behavior, or a bug?


Regex surprises

2022-09-12 Thread Sean McAfee
Hello--

I stumbled across a couple of bits of surprising regex behavior today.

First, consider:

S:g[ x { say 1 } ] = say 2 given "xx"

I expected this to print 1, 2, 1, 2, but it prints 1, 1, 2, 2.  So it looks
like, in a global substitution like this, Raku doesn't look for successive
matches and then evaluate the replacements as it goes, but finds all of the
matches *first* and then works through the substitutions.  In my actual
problem I was mutating state in the regex code block, and then it didn't
work because all of the mutations happened before even a single replacement
was evaluated.  Is it really meant to work this way?

Next, consider:

> "y" ~~ /(x)|(y)/
「y」
 0 => 「y」

y is in the second set of grouping parentheses, so I expected it to be in
group 1, but it's in group 0.  So it looks like the group index starts from
0 in every branch of an alternation.  I do so much regex slinging I'm
amazed it took me so long to discover this, if it's not a relatively recent
change.  I'm accustomed to being able to determine which alternation branch
was matched by checking which group is defined (in other languages too, not
just Raku).  This kind of thing:

S:g[(x)|(y)] = $0 ?? x-replacement !! y-replacement

I guess instead I need to do this:

S:g[x|y] = $/ eq 'x' ?? x-replacement !! y-replacement

It seems very strange that I need to re-examine the match to know what
matched.  The match should be able to tell me what matched.  Or is there
perhaps some alternate way for me to tell which alternative matched?


Re: Using Inline::Python

2022-09-09 Thread Sean McAfee
Good enough reason to try!  I got the 2022.07 release from brew.  Then zef
install -v Inline::Python --exclude=python3 (the same incantation I used
before) failed with:

===> Searching for: Inline::Python
===> Found: Inline::Python:ver<0.5>:auth [via
Zef::Repository::LocalCache]
===> Building: Inline::Python:ver<0.5>:auth
[Inline::Python] Command: /usr/local/Cellar/rakudo-star/2022.07/bin/rakudo
-MMONKEY-SEE-NO-EVAL -e exit((require
::(q|Distribution::Builder::MakeFromJSON|)).new(:meta(EVAL($*IN.slurp(:close.build(q|/Users/seanmcafee/.zef/store/Inline-Python-0.5.tar.gz/Inline-Python-0.5|)??0!!1)
===> Building [FAIL]: Inline::Python:ver<0.5>:auth
Aborting due to build failure: Inline::Python:ver<0.5>:auth (use
--force-build to override)

Not much there to tell me what's wrong.  I gamely added --force-build and
tried again.  This time the unit tests for Inline::Python failed (eg.
"SystemError: frame does not exist" (looks like a Python error), "This
container does not reference a native unsigned integer").  It looks like
this somewhat old but unaddressed open issue:
https://github.com/niner/Inline-Python/issues/44.  There was a suggestion
to add --force-test to override.  I tried that and returned to the previous
status quo: empty array, "instance has no attribute 'sql'".


On Fri, Sep 9, 2022 at 11:48 AM Elizabeth Mattijsen  wrote:

> Well, if you would like people to look into possible core issues, then it
> would help using the latest released version (aka 2022.07).  Especially
> since 2021.04 is from before the new-disp work being merged, so it is not
> completely unlikely it functions better now.
>
> > On 9 Sep 2022, at 20:44, Sean McAfee  wrote:
> >
> > I still see the same behavior.  That is, if I do say spark.sql('select
> 1+1'); twice, the first time prints an empty array, and the second produces
> the "instance has no attribute 'sql'" error message.
> >
> > I forgot to mention, this is on a somewhat old version of Raku,
> 2021.04.  But then, Inline::Python seems to be mostly even older.
> >
> >
> > On Fri, Sep 9, 2022 at 11:35 AM Elizabeth Mattijsen 
> wrote:
> > To rule out any REPL artefacts, do you see the same thing if you put the
> code in a script and run the script?
> >
> > > On 9 Sep 2022, at 20:17, Sean McAfee  wrote:
> > >
> > > Hello--
> > >
> > > I recently started playing around with PySpark.  It soon occurred to
> me that it would be a lot more fun to work in Raku instead of Python, and I
> recalled that it's supposed to be possible to get handles to Python objects
> from Raku and call methods on them seamlessly, so I tried to make it
> happen.  I got pretty far, but now I'm stymied.  Here are the steps I can
> take in the Raku interpreter:
> > >
> > > > use Inline::Python
> > > Nil
> > > > my \python = Inline::Python.new
> > > Inline::Python.new
> > >
> > > Self-explanatory.
> > >
> > > > python.run('from pyspark.sql import SparkSession')
> > > (Any)
> > >
> > > No errors, that looks promising...
> > >
> > > > my \spark = python.run('SparkSession.builder.getOrCreate()', :eval)
> > > ... spam from initialization of Spark session deleted...
> > > Inline::Python::PythonObject.new(ptr =>
> NativeCall::Types::Pointer.new(4461193984), python => Inline::Python.new)
> > >
> > > Now we're getting somewhere!  (I had to source-dive to guess that I
> needed that :eval; without it, an Any is returned.)
> > >
> > > > my \sql = spark.sql('select 1+1')
> > > []
> > >
> > > Uh...what?  I was expecting to get another Python object back, a
> DataFrame.  (I think; I'm much more familiar with the Scala interface to
> Spark.)  Instead I have an empty array.
> > >
> > > Even more puzzlingly, if I re-run that last statement, I get an error:
> "instance has no attribute 'sql'".  If I re-run the statement over and
> over, the response alternates between an empty array and that error.
> > >
> > > Does anyone have any insight into what's going on?
> > >
> >
>
>


Re: Using Inline::Python

2022-09-09 Thread Sean McAfee
I still see the same behavior.  That is, if I do say spark.sql('select
1+1'); twice, the first time prints an empty array, and the second produces
the "instance has no attribute 'sql'" error message.

I forgot to mention, this is on a somewhat old version of Raku, 2021.04.
But then, Inline::Python seems to be mostly even older.


On Fri, Sep 9, 2022 at 11:35 AM Elizabeth Mattijsen  wrote:

> To rule out any REPL artefacts, do you see the same thing if you put the
> code in a script and run the script?
>
> > On 9 Sep 2022, at 20:17, Sean McAfee  wrote:
> >
> > Hello--
> >
> > I recently started playing around with PySpark.  It soon occurred to me
> that it would be a lot more fun to work in Raku instead of Python, and I
> recalled that it's supposed to be possible to get handles to Python objects
> from Raku and call methods on them seamlessly, so I tried to make it
> happen.  I got pretty far, but now I'm stymied.  Here are the steps I can
> take in the Raku interpreter:
> >
> > > use Inline::Python
> > Nil
> > > my \python = Inline::Python.new
> > Inline::Python.new
> >
> > Self-explanatory.
> >
> > > python.run('from pyspark.sql import SparkSession')
> > (Any)
> >
> > No errors, that looks promising...
> >
> > > my \spark = python.run('SparkSession.builder.getOrCreate()', :eval)
> > ... spam from initialization of Spark session deleted...
> > Inline::Python::PythonObject.new(ptr =>
> NativeCall::Types::Pointer.new(4461193984), python => Inline::Python.new)
> >
> > Now we're getting somewhere!  (I had to source-dive to guess that I
> needed that :eval; without it, an Any is returned.)
> >
> > > my \sql = spark.sql('select 1+1')
> > []
> >
> > Uh...what?  I was expecting to get another Python object back, a
> DataFrame.  (I think; I'm much more familiar with the Scala interface to
> Spark.)  Instead I have an empty array.
> >
> > Even more puzzlingly, if I re-run that last statement, I get an error:
> "instance has no attribute 'sql'".  If I re-run the statement over and
> over, the response alternates between an empty array and that error.
> >
> > Does anyone have any insight into what's going on?
> >
>
>


Using Inline::Python

2022-09-09 Thread Sean McAfee
Hello--

I recently started playing around with PySpark.  It soon occurred to me
that it would be a lot more fun to work in Raku instead of Python, and I
recalled that it's supposed to be possible to get handles to Python objects
from Raku and call methods on them seamlessly, so I tried to make it
happen.  I got pretty far, but now I'm stymied.  Here are the steps I can
take in the Raku interpreter:

> use Inline::Python
Nil
> my \python = Inline::Python.new
Inline::Python.new

Self-explanatory.

> python.run('from pyspark.sql import SparkSession')
(Any)

No errors, that looks promising...

> my \spark = python.run('SparkSession.builder.getOrCreate()', :eval)
... spam from initialization of Spark session deleted...
Inline::Python::PythonObject.new(ptr =>
NativeCall::Types::Pointer.new(4461193984), python => Inline::Python.new)

Now we're getting somewhere!  (I had to source-dive to guess that I needed
that :eval; without it, an Any is returned.)

> my \sql = spark.sql('select 1+1')
[]

Uh...what?  I was expecting to get another Python object back, a
DataFrame.  (I think; I'm much more familiar with the Scala interface to
Spark.)  Instead I have an empty array.

Even more puzzlingly, if I re-run that last statement, I get an error:
"instance has no attribute 'sql'".  If I re-run the statement over and
over, the response alternates between an empty array and that error.

Does anyone have any insight into what's going on?


div & mod don't coerce arguments to Int?

2021-12-18 Thread Sean McAfee
While coding today, I was a little surprised to discover that the div
operator doesn't coerce its arguments to integers.  So for example, the
expressions 25 div '5' and pi div 5 raise errors.  I checked the Operators
doc page and saw that, sure enough, div (and mod, I found) accept only
actual Ints.  Of all numeric operators at the multiplicative and additive
levels of precedence, they're alone in that respect.

Is there a particular reason these two operators are so restrictive?


Re: Subscripting, semicolons, and adverbs

2021-12-11 Thread Sean McAfee
On Sat, Dec 11, 2021 at 11:28 AM Ralph Mellor 
wrote:

> On Fri, Dec 10, 2021 at 9:49 PM Sean McAfee  wrote:
> >
> > @array[-1]:exists is a syntax error, even though it looks like
> > it should just evaluate to True.
>
> In Raku `foo[-N]` is invalid. At compile-time if N is statically
> known, otherwise at run-time.
>

It's not, though, if certain adverbs such as :exists are present, as in my
original message.

> @array[-1]:exists  <-- compile time error

> my $i = -1; @array[$i]:exists  <-- evaluates to False

To me it appears that the first case should also evaluate to False, but
that the compiler is trying to aggressively catch negative-indexing errors
without considering whether any adverbs are present that might make the
expression sensible.

Another example is the :v adverb.  I was recently delighted to discover
that I could easily have a sliding window over an array, where the window
might hang over either end of the array.

> my @a = 
[a b c d e]
> say @a[^3 + $_]:v for -2 .. 4
(a)
(a b)
(a b c)
(b c d)
(c d e)
(d e)
(e)

But anyway, my original use case was driven by a desire to simplify a
routine similar to the following.  Given a 2-D array and an x- and
y-coordinate, I want to increment the number at the given coordinates, but
only if the coordinates are valid.  My first effort went like this:

sub increment(@array, $x, $y) {
++@array[$y][$x] if 0 <= $y < @array && 0 <= $x < @array[$y];
}

Then I remembered semicolon subscripting and :exists, and tried changing
the body of the routine to this:

++@array[$y; $x] if @array[$y; $x]:exists;

I thought that was a vast improvement; let Raku figure out if the indices
are valid!  But while it does work--that is, I get the right answers at the
end--it results in a slew of "unhandled Failure detected in DESTROY"
warnings.  I haven't observed this ever happening when using :exists with a
single index, only with subscripts that use semicolons.  So for now, I'm
getting by with:

++@array[$y; $x] if @array[$y]:exists and @array[$y][$x]:exists;

[snipped a bunch of comments about the pitfalls of using negative numbers
to index from the end of arrays, with which I am in total agreement]


Re: Subscripting, semicolons, and adverbs

2021-12-10 Thread Sean McAfee
On Fri, Dec 10, 2021 at 1:48 PM I wrote:

> So this looks pretty buggy, but I wonder if I'm somehow invoking undefined
> behavior by combining semicolons and adverbs while subscripting.  The
> online docs cover both features separately, but not in tandem that I can
> see.
>

Actually, immediately after sending my message, I found that the online
docs actually DO cover this case, and it appears to be explicitly allowed.
So I can't really tell what I'm doing wrong here...


Subscripting, semicolons, and adverbs

2021-12-10 Thread Sean McAfee
I was writing some code that involved accessing an array-of-arrays.  I
wanted to check whether both of a given pair of indices were in bounds, so
I wrote:

return () if @array[$y]:!exists or @array[$y][$x]:!exists or ...

The double index check bugged me a bit, since I wondered if there might be
a shorter way to express it.  Then I remembered nested arrays can be
accessed by separating the indices with semicolons, so I tried:

return () if @array[$y;$x]:!exists or ...

A whole bunch of errors ensued when I ran the program.  I experimented some
more on the console and saw some pretty strange behavior.

> my @a = , 
[(a b c) (d e f)]
> my $i = -1
-1
> @a[$i;$i]:exists
False

(Indexing with $i instead of a literal -1 is necessary to get around the
fact that providing a negative literal as an array index is apparently a
compilation error, not a runtime error, meaning that @array[-1]:exists is a
syntax error, even though it looks like it should just evaluate to True.
That confused me for a little while.)

So anyway, that last evaluation appears correct, but if I repeat it over
and over, eventually I get this error:

WARNING: unhandled Failure detected in DESTROY. If you meant to ignore
it, you can mark it as handled by calling .Bool, .so, .not, or .defined
methods. The Failure was:
Index out of range. Is: -1, should be in 0..^Inf
  in block  at  line 1

Actually, I get a bunch of those errors, as if they were stored up by all
my previous evaluations of @a[$i;$i]:exists.  If I continue to evaluate the
expression repeatedly, I get a run of Falses, then another batch of errors
at some later point.

So this looks pretty buggy, but I wonder if I'm somehow invoking undefined
behavior by combining semicolons and adverbs while subscripting.  The
online docs cover both features separately, but not in tandem that I can
see.


Re: how do I turn a real into and array of Integers?

2021-11-01 Thread Sean McAfee
On Mon, Nov 1, 2021 at 1:53 AM sisyphus  wrote:

> Note that what you have there is a 200-decimal-digit (around 658-bit)
> precision representation of the square root of 2 - which is quite different
> to the (53-bit precision) Real  sqrt(2).
>

Always gotta be careful with reals.  I also attempted to get the digits of
the real square root of 2 using a numeric-only method:

(2.sqrt, { 10 * ($_ - .truncate) } ...^ 0)>>.truncate

This gives:

(1 4 1 4 2 1 3 5 6 2 3 7 3 0 9 5 1 0 1 0 6 5 7 0 0 8 7 3 7 3 2 5 6 6 8
3 3 4 9 6 0 9 3 7 5)

That's a lot more digits than you see in the string representation of
2.sqrt, but checking showed that most of them--all of them after the
7-3-0-9-5---are wrong.


Re: how do I turn a real into and array of Integers?

2021-10-31 Thread Sean McAfee
On Sun, Oct 31, 2021 at 6:51 PM ToddAndMargo via perl6-users <
perl6-us...@perl.org> wrote:

> >> How do I get more digits out of sqrt?
>
> On 10/31/21 17:50, Kevin Pye wrote:
>  > You don't.
>  >
>  > sqrt is a function which acts on 64-bit floating point numbers, and
> there's no more meaningful digits available. If you need more precision
> you're on your own.
>
> Dang!  I was hoping ther was some thing like UInt.
>

Fortunately, it's easy.

Wikipedia describes the following recurrence formula for approximating the
square root of 2 from an initial guess a₀:

aₙ₊₁ = (aₙ / 2 + 1 / aₙ)

So just iterate this sequence until successive terms become close enough
for you, using the unlimited precision FatRat type, for example:

(2.FatRat, { $_ / 2 + 1 / $_ } ... (* - *).abs < 1e-100).tail

This gives the root to a precision of one in a googol.


Re: how do I turn a real into and array of Integers?

2021-10-31 Thread Sean McAfee
On Sun, Oct 31, 2021 at 9:08 AM Andinus via perl6-users <
perl6-us...@perl.org> wrote:

> put 2.sqrt.comb.grep(*.Int)>>.Int[^10].raku # 10 digits
>

comb takes an argument that can save you a method call:

2.sqrt.comb.grep(*.Int)
  ==>
2.sqrt.comb(/\d/)


Re: A nice touch

2021-10-31 Thread Sean McAfee
On Sat, Oct 30, 2021 at 9:21 PM Wes Peng  wrote:

> What's the "**" operator in perl? I most of the time use R for math, not
> familiar with this operation.
>

It's exponentiation: https://docs.raku.org/language/operators#infix_**

That wasn't a Raku expression I used it in, though, just my attempt to
render a mathematical formula in a plain-text format.  I thought that ** is
probably one of the more widely recognized symbols for exponentiation.


Re: A nice touch

2021-10-31 Thread Sean McAfee
On Sat, Oct 30, 2021 at 9:03 PM Ralph Mellor 
wrote:

> On Sat, Oct 30, 2021 at 8:38 PM Sean McAfee  wrote:
> > Anyway, pretty cool!
>
> I agree it's cool, at least in a golfing sense.
>
> But is your explanation right?
>
> The *range* operator (`..`), if the rhs is less than the left,
> yields an empty list rather than iterating between the endpoints.
>
> In contrast, the *sequence* operator (`...`) iterates.
>

Uh.  Yeah.

I didn't explain why .. works for the zero-arg case and ... doesn't,
because the main point of my message was about the R metaoperator and the
associativity of the operator it creates.  But the difference you mention
is indeed exactly why .. works but ... doesn't.

[*] [\*] 0...1  ==> 0
[*] [\R*] 1..0  ==> 1

To expound even further, the second expression works because 1..0 is an
empty list, reducing that empty list with [\R*] produces another empty
list, and reducing *that* empty list with [*] produces 1, the
multiplicative identity element.


A nice touch

2021-10-30 Thread Sean McAfee
Recently I was golfing the "hyperfactorial," defined for a number 푛 as
푛**푛 × (푛-1)**(푛-1) × (푛-2)**(푛-2) × ... × 1.  I created a quite
concise Raku function:

{ [*] [\*] $_...1 }

The only problem was that this function returns zero for a zero input,
whereas the hyperfactorial of 0 is supposed to be 1.  Of course I could
have just handled zero as a special case, but I hoped to find something
comparably short.  After a bit of thought I tried reversing both the range
and the operator:

{ [*] [\R*] 1..$_ }

It worked!  But I couldn't quite see how.  * is commutative, so isn't it
exactly the same as R*?

It turns out, in Raku it isn't quite the same.  On the operators page, I
found that the R metaoperator produces an operator that reverses the order
of the arguments, but *also* has the opposite associativity.  So, for
example, [\R*] 1..4 reduces from the right, producing the list (4, 12, 24,
24).  Somehow I had formed the idea that Raku operators are left-, right-,
or list-associative, but I was wrong.

Anyway, pretty cool!


Junctions wrapped in singleton lists

2020-11-13 Thread Sean McAfee
I just tried making a sequence of junctions and found that each one ended
up wrapped in a singleton list somehow:

> ({ 1 | -1 } ... *)[^3]
((any(1, -1)) (any(1, -1)) (any(1, -1)))

Strangely, I can set an ending condition that works like I would expect,
but the sequence still produces single lists.

> { (1|-1) * ++$ } ... -3
((any(1, -1)) (any(2, -2)) (any(3, -3)))

This seems to happen for any kind of junction, not just or-junctions.

Is this a bug, or some legitimate rule I'm unaware of?


Re: Sending a string to a subprocess

2020-11-11 Thread Sean McAfee
On Wed, Nov 11, 2020 at 4:44 PM Paul Procacci  wrote:

> So sorry... hit enter way too early.
>
> https://docs.raku.org/type/Proc
>
> my $p = run "ssh", "myhost", "cat - > outfile", :in, :out;
> $p.in.say: "Hello,\nworld!";
>
> Ah, of course.  It's so obvious now.  Thanks!


Sending a string to a subprocess

2020-11-11 Thread Sean McAfee
I posted this question on Stack Overflow a few days ago:
https://stackoverflow.com/questions/64757138/raku-sending-a-string-to-a-subprocesss-standard-input

...but there haven't been any answers, so I'm asking here.

The tl;dr is that I don't see an obvious way to send data to a subprocess's
standard input stream, other than by creating a second subprocess.

For a simple example, suppose I wanted to store a file on a remote host
with ssh:

my $content = 'file contents';
run 'ssh', 'myhost', 'cat > outfile', :in($what-goes-here);

The only solution I've found after a lot of searching is not very appealing.

my $echo = run 'echo', $content, :out;
run 'ssh', 'myhost', 'cat > outfile', :in($echo.out);

Is there any better way?


Re: Constructing a number from digits in an arbitrary base

2020-11-02 Thread Sean McAfee
On Fri, Oct 30, 2020 at 2:19 PM Elizabeth Mattijsen  wrote:

> > On 30 Oct 2020, at 22:11, Sean McAfee  wrote:
> > With polymod, I can get the values of digits even in large bases like
> 101:
> >
> > > 1234567890.polymod(101 xx *)
> > (46 20 26 87 11)
> >
> > Given a list of digit values like that, and the base, I want to
> reconstruct the original number.


So you'd basically need a sub that takes a List, and a base factor, and
> does the necessary arithmetic for you.  I don't think that's in core.  I'd
> be glad if someone proved me wrong  :-)
>

Found it!  The "trick" is to use square braces after the colon and base.
For example, :101[11,87,26,20,46] evaluates to 1234567890.

The digit values have to be supplied most-significant to least-significant,
the opposite of the order returned by polymod, and the base must be known
at compile time, but this is definitely the construction I was trying to
recall originally.  Even nicer for my golfing purposes, the list elements
are coerced to numbers automatically, so for example :2[True, False, True,
False] evaluates to 10.

I can't locate any documentation on this feature, but then I couldn't find
documentation on the dynamic string-parsing version (eg. :2($str)) when I
looked either, only the literal form, like :2<10101>.


Re: Constructing a number from digits in an arbitrary base

2020-10-30 Thread Sean McAfee
On Fri, Oct 30, 2020 at 2:19 PM Elizabeth Mattijsen  wrote:

> > On 30 Oct 2020, at 22:11, Sean McAfee  wrote:
> > > sum <46 20 26 87 11> Z* (1, * * 101 ... *)
> > 123456789
> >
> > ...but I'm hoping there's something more concise, shorter, and/or
> readable.
>
> Ah, so it's not about parsing per se.  Sorry I misunderstood.
>
> So you'd basically need a sub that takes a List, and a base factor, and
> does the necessary arithmetic for you.  I don't think that's in core.  I'd
> be glad if someone proved me wrong  :-)
>

Well, not necessarily even a sub.  Just an expression.

My specific use case at the moment is a golf challenge where I have a list
of objects, some of which are Nil, and I want to create a number from them
where the Nil values are treated as a binary 0 digit and the non-Nil values
as a binary 1 digit, and I'm currently doing it like this:

:2((+«?«@some-are-Nil).join)

As I mentioned, I feel like I've seen a short way to make a number from its
digits, but now I can't remember it.  I could be wrong.  But if it exists
I'm hoping it would let me shave off a few bytes.


Re: Constructing a number from digits in an arbitrary base

2020-10-30 Thread Sean McAfee
Sorry, it seems I wasn't explicit enough.

With polymod, I can get the values of digits even in large bases like 101:

> 1234567890.polymod(101 xx *)
(46 20 26 87 11)

Given a list of digit values like that, and the base, I want to reconstruct
the original number.  One way would be the one I originally suggested:

> sum <46 20 26 87 11> Z* (1, * * 101 ... *)
1234567890

...but I'm hoping there's something more concise, shorter, and/or readable.


Constructing a number from digits in an arbitrary base

2020-10-30 Thread Sean McAfee
I want to construct a number from its digits in some arbitrary base.  That
is, to essentially do the inverse of this kind of polymod call:

my @digits = $number.polymod($base xx *);

I have a nagging feeling that I've seen a very concise way to do this in
Raku before, but now it escapes me, and all my searching has found only
pages describing basic, ordinary base conversion.

Obviously for bases from 2-10 one can just concatenate the digits and pass
them to a conversion construct like :2(...) or :5(...) or whatever, if the
base is fixed at compile time.  For the more general case the best I can
come up with is

my $number = sum @digits Z* (1, * * $base ... *);

Is there a shorter and/or better way?


Re: Brace interpolation in strings creates a new scope?

2020-10-26 Thread Sean McAfee
On Mon, Oct 26, 2020 at 12:04 PM Elizabeth Mattijsen  wrote:

> Personally, I would avoid the use of the anonymous state variable.  I
> think it is an example where Larry would nowadays apply rule #2.
>

Well, I wouldn't use a construction like that in real code.  It just seems
like one of the simpler ways to introduce anonymous state variables.

For the end of my talk, I plan to explore a golfing challenge I worked on a
while ago that calls for zipping two infinite sequences together with the
replication operator xx, where the second sequence is:

1, 1, 2, 2, 3, 3, 4, 4, ...

I wasn't really happy with any of the ways I came up with to generate that
second sequence, like:

{ 1 + $++ div 2 } ... *
map * div 2, 2 .. *

Then I had the sudden inspiration that xx coerces its second argument to
Int, meaning all I really needed was:

1, 1.5 ... *


Brace interpolation in strings creates a new scope?

2020-10-26 Thread Sean McAfee
I'm putting together a Raku presentation for my co-workers and have a
section on state variables.  This is my example:

sub how-many {
state $times;
say "You called me {++$times} times";
}

> how-many
You called me 1 times
> how-many
You called me 2 times
> how-many
You called me 3 times

Then I thought I'd mention anonymous state variables by modifying my
example thusly:

sub how-many {
say "You called me {++$} times";
}

But this gives:

> how-many
You called me 1 times
> how-many
You called me 1 times
> how-many
You called me 1 times

Is this the intended behavior?  The doc page on quoting constructs just
says that values can be interpolated with braces, but (at least to my eyes)
doesn't suggest that this involves creating a new scope, or a new function,
or however it is that this happens.

For my presentation I can just alter some lines to:

say "You called me ", ++$times, " times";

and

say "You called me ", ++$, " times";

...but that seems a bit less elegant than what I had originally.


Re: print particular lines question

2020-08-25 Thread Sean McAfee
On Tue, Aug 25, 2020 at 2:31 PM Andy Bach 
wrote:

> Pretty cool - I didn't know about the bare "$" as a magic state var.
>

They can be pretty great, especially when combined with the magic op=
operators that (in essence) know about identity elements.  I've done a few
challenges on the Code Golf Stackexchange site where I wanted an infinite
sequence like this:

0, 1, -2, 3, -4, 5, -6, ...

It took me a while to realize this can be expressed in Raku simply as:

{ $++ * ($ *= -1) } ... *


Re: regex interpolation of array

2020-06-13 Thread Sean McAfee
On Sat, Jun 13, 2020 at 10:21 AM Brad Gilbert  wrote:

> That was just a dumb example.
> An incredibly dumb example.
>
> So what happens is that `Bool.pick` chooses The Bool values of either
> `True` or `False`.
> It does this at every position in the string.
>
> 'TrueFalse' ~~ / <{ Bool.pick }>
>

I saw this and figured that maybe a state variable could help:

'TrueFalse' ~~ /<{ $ //= Bool.pick }>/

...but it doesn't.  I suppose that means the bracketed code is not compiled
just once, like an anonymous subroutine, but is fully re-evaluated on every
match attempt.  Is that the intended behavior?


Re: Raku -npe command line usage

2020-05-08 Thread Sean McAfee
On Fri, May 8, 2020 at 6:53 AM Brad Gilbert  wrote:

> So together that would be:
>
> raku -ne 'BEGIN my @i; @i.push($_) if /^WARN/; END .say for @i.sort'
>

Or alternately the main body of the loop can be written:

(my @i).push($_) if /^WARN/;

Or even:

push my @i: $_ if /^WARN/;

It's so nice how Raku essentially compiles the body of these file loops
into a little subroutine so that the "my" declaration only occurs once,
unlike how Perl 5 just textually wraps the loop with "while (<>) {" and "}"
which makes the declaration occur on every iteration.

I originally figured this out when I idly worked up a classic
word-frequency-count one-liner:

raku -ne '++(my %freq){$_} for m:g/\w+/; END .say for
%freq.antipairs.sort.reverse' file ...


Re: Lookbehind assertion weirdness

2019-08-23 Thread Sean McAfee
On Thu, Aug 22, 2019 at 6:11 PM yary  wrote:

> Perl 6 is doing the right thing. The dot matches any character. In
> this case, matching the final ':'. The next bit of the regex says the
> cursor has to be after 1:, and indeed, after matching the ':' the
> cursor is after '1:', so the substitution succeeds.
>

My real use case, that I tried to provide a simplified example of, was to
process some pretty-printed JSON.  Less simplified this time, I wanted to
change all "foo": "whatever" strings to "foo": "*".  In Perl 5 I would have
done:

s/(?<="foo": ")[^"]+/*/;

Trying to express this in Perl 6, I thought "lookbehind" would naturally
translate to a "before" assertion:

s/<-["]>+/*/;

...but that didn't work.  Various other attempts led to the simplified
example I originally provided.

Long story short, it seems that a Perl 5 (?<=...) lookbehind translates to
a Perl 6  assertion, and likewise a Perl 5 (?=...) lookahead
translates to a Perl 6  assertion.  The terminology just
confused me due to my prior Perl 5 experience.


Lookbehind assertion weirdness

2019-08-22 Thread Sean McAfee
This seems like a bug, but I thought I'd ask here before reporting it.

$_ = '1:';
s/./x/;
.say;

This prints "1x".  Is that what's supposed to happen somehow?  I would have
thought that '1:' should only match a literal "1:", leaving nothing for the
dot to match.


Subscripting with a list of slices

2019-08-16 Thread Sean McAfee
Today I was surprised and pleased to find that I could apparently subscript
an array with a list of lists of indices, and get a list of slices back:

> my @array = 9 ... 0
[9 8 7 6 5 4 3 2 1 0]
> @array[map { $_, $_ + 1 }, ^9]
((9 8) (8 7) (7 6) (6 5) (5 4) (4 3) (3 2) (2 1) (1 0))

Neat!  But when I tried to clean up my code a bit, it broke.

> my @index = map { $_, $_ + 1 }, ^9
[(0 1) (1 2) (2 3) (3 4) (4 5) (5 6) (6 7) (7 8) (8 9)]
> @array[@index]
(7 7 7 7 7 7 7 7 7)

Weird.  But map returns a Seq, right?  So maybe...

> @array[@index.Seq]
(7 7 7 7 7 7 7 7 7)

Hmm.  How about:

> @array[@index.List]
((9 8) (8 7) (7 6) (6 5) (5 4) (4 3) (3 2) (2 1) (1 0))

That works again.  But why?  Is this the intended behavior?  If so, is it
documented somwhere?


Re: Odd Complex behavior

2019-06-13 Thread Sean McAfee
On Thu, Jun 13, 2019 at 11:12 AM Brad Gilbert  wrote:

> > (-i).reals
> (-0 -1)
>

Ah, so it's nothing particular to Complex:

> bag 0e0, -0e0
bag(-0, 0)

Can't say I'm thrilled to have two distinct zeroes.


Odd Complex behavior

2019-06-13 Thread Sean McAfee
> bag i, 2i - i
bag(0+1i(2))

Well and good.

> bag -i, -2i + i
bag(0-1i, -0-1i)

Huh?  But this works as expected:

> bag Complex.new(0, -1), Complex.new(0, -2) + Complex.new(0, 1)
bag(0-1i(2))

Is this a bug, or is there a sense in which it's correct?


Catching exceptions in expressions

2018-08-03 Thread Sean McAfee
I posted about this subject on Stack Overflow yesterday[1], but I chose a
poor example of something that raises an exception (dividing by zero, which
apparently doesn't necessarily do so) on which the answers have mostly
focused.

I was looking for a way to evaluate an expression, and if the expression
threw an exception, for a default value to be provided instead.  For
example, in Ruby:

quotient = begin; a / b; rescue; -1; end

Or in Lisp:

(setq quotient (condition-case nil (/ a b) (error -1)))

Not having written much exception-related code in Perl 6, I hoped that this
might work:

sub divide($a, $b) { die "Zero denominator" if $b == 0; $a / $b }
my $quotient = do { divide($a, $b); CATCH { default { -1 } } };

It doesn't, though.  As far as I can tell, the value to which a CATCH block
evaluates is ignored; the only useful things one can do in such a block are
things with side effects.  Long story short, I eventually came up with this:

my $quotient = do { my $q; { $q = divide($a, $b); CATCH { default { $q
= -1 } } }; $q };

That's far more verbose than I've come to expect from Perl 6.  Is there
some more concise way of expressing this logic?

The doc page on exceptions mentions try, eg:

my $quotient = try { divide($a, $b) } // -1;

That works in this specific case, but it seems insufficient in general.
The function might validly return an undefined value, and this construction
can't distinguish between that and an exception.  Also, it wouldn't let me
distinguish among various exception cases.  I'd have to do something like:

class EA is Exception { }
class EB is Exception { }
sub divide($a, $b) { (EA, EB).pick.new.throw if $b == 0; $a / $b }

my $quotient = do { my $q; { $q = divide($a, $b); CATCH { when EA { $q
= -1 }; when EB { $q = -2 } } }; $q };


[1]
https://stackoverflow.com/questions/51644197/returning-values-from-exception-handlers-in-perl-6/51670573


Re: Range of Dates

2018-05-05 Thread Sean McAfee
On Wed, May 2, 2018 at 3:44 AM, Elizabeth Mattijsen  wrote:

> Getting back to maybe your original question: if you want the date 7 days
> from now, you can just use integer arithmetic:
>
> $ 6 'say Date.today + 7'
> 2018-05-09
>

Oh, I knew that; that was just an example.

My actual code involved finding the date of the next Tuesday after today,
for which I originally wrote:

my $next-tuesday = (Date.today ... *.day-of-week == 2).tail;

It bugged me a bit stylistically that the parentheses gave prominence to
the entire sequence when all I really wanted was the final element.  So I
played with it a big until I got:

my $next-tuesday = first *.day-of-week == 2, Date.today .. *;

That's when I accidentally left off the third period and found that it
still worked.


Range of Dates

2018-05-01 Thread Sean McAfee
Today I wanted to write an infinite sequence of Dates starting from today,
but I accidentally wrote two dots instead of three as I'd intended.  I was
surprised to find that it seems to work as one might expect, eg:

(Date.today .. *)[7] # one week from today

The online docs say that Ranges are only for numbers and strings, so how is
it that this works?  Is it an accident, or can anything that has a "succ"
method be in a Range, or...?


Junctions now being stringified as one alternative per line?

2018-02-24 Thread Sean McAfee
I recently upgraded to Rakudo 2018.01 and just now encountered some
perplexing behavior.

Junctions, regardless of type, are being stringified one alternative per
line.  1 & 2, 1 | 2, 1 ^ 2, and none(1, 2) are all displayed as a 1, a
newline, and 2.  Previously I would see eg. "all(1, 2)", which now I have
to call .perl on the junction to see.

Was this change intentional?  It's hard to see it as an improvement,
particularly considering how no information about the junction type is
presented.

I discovered the behavior by trying to print the return value of a function
that returned a junction, something like this:

sub f { all @_ }

say "$_ => {f |$_}" for <1 2 3>, <4 5 6>;

This prints:

1 2 3 => 1
1 2 3 => 2
1 2 3 => 3
4 5 6 => 4
4 5 6 => 5
4 5 6 => 6

It looks like the say is being hit six separate times, when it clearly
should be called only twice...which it is, but it's impossible to tell from
the output.


Chained sequence operators

2018-01-26 Thread Sean McAfee
Today I stumbled across the fact that the sequence operator can be chained:

> 1...5...1
(1 2 3 4 5 4 3 2 1)

You can even reduce with it:

> [...] 1, 5, 3, 10, 8
(1 2 3 4 5 4 3 4 5 6 7 8 9 10 9 8)

And even sequences with custom generators can be joined:

> 0,1,*+*...144,*/2...9
(0 1 1 2 3 5 8 13 21 34 55 89 144 72 36 18 9)

Pretty cool!  The online docs for the operator don't seem to offer even a
hint that this is possible, though.

Anyway, I was hoping that someone with more insight into the internals
could describe how this works.  Simple concatenation, or can sequences
lazily dispatch to another sequence once exhausted, or...?


Call a function in a Whatever star

2017-12-13 Thread Sean McAfee
I just tried doing this:

> map *(1), *+1, *+2, *+3

But I get an error: "No such method 'CALL-ME' for invocant of type
'Whatever'".  Fair enough.

This works:

> map { $_(1) }, *+1, *+2, *+3
(2 3 4)

Is there any alternative way to call a function through a whatever-star, as
in my first example?


Re: %% with zero denominator

2017-12-11 Thread Sean McAfee
On Mon, Dec 11, 2017 at 3:01 PM, <zof...@zoffix.com> wrote:

>
> On 2017-12-11 12:22 PM, Sean McAfee wrote:
>
>> Well, not really.  I don't think x %% 0 should return a Failure at all.
>>
>
> Is there a particular problem the current implementation fails to solve?
> In boolean
> context `x %% 0` *is* equivalent to False. The Failure carries additional
> information
> to those who want it. You can discard that information with `so x %% 0` if
> you aren't
> already evaluating in Bool context. Seems returning a Failure is the best
> of both worlds.
>
>
Well, *any* function or operator that returns a boolean *could* return a
Failure instead of (or in addition to) False to provide additional
information to those who want it, but if the condition is not really a
Failure, wouldn't that be misleading?  Like this highly contrived example:

sub is-nonzero($x) { $x.Num / $x.Num }

I feel that %% returning a Failure when given a zero second argument is
similarly misleading/unhelpful.  At least, if the intention of "a %% b" is
simply to return whether a is divisible by b.  If it's explicitly intended
to mean just "a % b == 0" and inherit all of the failure modes of the %
operator, then fine, I suppose.  It seems more clunky to me, though.

1 / 0 is an expression which can evaluate to no sensible value
>
> It can produce a sensible value. In floating point context (that is in Num
> view), that's a perfectly cromulent positive infinity, again per IEEE 754
> standard:
>
>  m: say (1 / 0).Num
>  rakudo-moar fed56be25: OUTPUT: «Inf␤»
>
>
To be perfectly cromulent I'd expect to be able to multiply that Inf by 0
and get my 1 back.


Re: %% with zero denominator

2017-12-11 Thread Sean McAfee
On Mon, Dec 11, 2017 at 12:56 PM, Darren Duncan <dar...@darrenduncan.net>
wrote:

> On 2017-12-11 12:22 PM, Sean McAfee wrote:
>
>> Well, not really.  I don't think x %% 0 should return a Failure at all.
>>
>> 1 / 0 is an expression which can evaluate to no sensible value, so it
>> makes
>> sense to fail there.  By the question "Is one divisible by zero?" has the
>> simple
>> answer "No."
>>
>
> I strongly disagree with you.
>
> First of all, the reason there is no sensible value is that the answer is
> BOTH "yes" and "no" at the same time, so you can't choose one.  Zero DOES
> divide evenly into anything, and typically does so an infinite number of
> times.


I strongly disagree that the answer to "Is 1 divisible by 0?" can be "yes"
in any meaningful, commonly-understood sense.  There is no number which one
can multiply by zero and get one, even an "infinite number," whatever that
means.  The inputs to and output from the remainder operation are natural
numbers, or perhaps integers, and all natural numbers and integers are
finite.


Re: %% with zero denominator

2017-12-11 Thread Sean McAfee
On Mon, Dec 11, 2017 at 1:52 AM, Elizabeth Mattijsen <l...@dijkmat.nl> wrote:

> > On 11 Dec 2017, at 04:42, Sean McAfee <eef...@gmail.com> wrote:
> > The docs say a %% b is True if a % b is 0, so the error is as-designed,
> at least.  But mightn't it make more sense for %% to just return False when
> given a second zero operand?  After all, the answer to "is n divisible by
> zero" is false for any n--there's no need to try to go through with the
> division to ascertain this.
>
> Note that x %% 0 returns a Failure ( https://docs.perl6.org/type/Failure
> ), which will be evaluated to False in a Boolean context.  So it is already
> doing what you want.


Well, not really.  I don't think x %% 0 should return a Failure at all.

1 / 0 is an expression which can evaluate to no sensible value, so it makes
sense to fail there.  By the question "Is one divisible by zero?" has the
simple answer "No."


%% with zero denominator

2017-12-10 Thread Sean McAfee
I think of %% as being Perl 6's is-divisible-by operator, so I was a little
surprised to discover this behavior:

> 1 %% 0
Attempt to divide 1 by zero using infix:<%%>
  in block  at  line 1

The docs say a %% b is True if a % b is 0, so the error is as-designed, at
least.  But mightn't it make more sense for %% to just return False when
given a second zero operand?  After all, the answer to "is n divisible by
zero" is false for any n--there's no need to try to go through with the
division to ascertain this.


Re: Need append help

2017-09-29 Thread Sean McAfee
On Fri, Sep 29, 2017 at 11:27 AM, Brandon Allbery 
wrote:

> On Fri, Sep 29, 2017 at 2:04 PM, ToddAndMargo 
> wrote:
>
>>
>> Question:  Is thee a pretty way like the above to do a prepend?
>>
>
> No, sorry.
>

Actually, there seems to be:

> my $x = "abc"
abc
> $x [R~]= "xyz"
xyzabc
> $x
xyzabc


Re: another one liner

2017-08-05 Thread Sean McAfee
On Fri, Aug 4, 2017 at 10:18 PM, ToddAndMargo  wrote:

> On 08/04/2017 08:43 PM, Bruce Gray wrote:
>
>>
>> P6-ish version:
>> ifconfig | perl6 -e 'say lines.map({ ~$0 if /^(\S+) ": flags="/
>> }).sort[1]'
>>
>
>
Wait a second.  How does map skip input elements like that?

> map { $_ if $_ %% 2 }, 1..10
(2 4 6 8 10)

> 1 if 1 %% 2
()

But:

> map { $_ %% 2 ?? $_ !! () }, 1..10
(() 2 () 4 () 6 () 8 () 10)


Re: flatmap considered harmful?

2017-07-29 Thread Sean McAfee
On Thu, Jul 27, 2017 at 12:43 PM, Will Coleda  wrote:

> I agree, that seems like pointless editorializing.
>
> If you can open a ticket at perl6/doc/issues on github, I'll remove
> that sentence this evening. (or someone can beat me to it.)
>
>
OK, it's done:

https://github.com/perl6/doc/issues/1428

Thanks!


flatmap considered harmful?

2017-07-27 Thread Sean McAfee
While browsing the Perl 6 docs recently, here:

https://docs.perl6.org/type/List#method_flatmap

I noticed this paragraph for the first time:

It is considered *bad practice* to use flatmap. Instead of .flatmap( ),
> please use .map( ).flat as it is clear when the .flat is called and is
> not confusing like .flatmap.
>

To quote a certain president's lawyer:  Says who?

Flat-mapping is awesome; I've written code that does it in several
different programming languages, in none of which is it deprecated in this
way.  Is there really any reason to avoid it in Perl 6 other than
subjective notions of how confusing it is?


Perl 6 ignores SIGPIPE

2017-06-16 Thread Sean McAfee
I see at

http://www.moarvm.com/releases.html

...that as of the 2017.03 release, Perl 6 "ignores SIGPIPE by default."  I
discovered this for myself when I piped a program that generates unlimited
output to the head utility, and the program did not exit when head was
finished.  Simple example:

$ perl6 -e '.say for ^Inf' | head

This will print numbers up to 9, and then continue to use almost 100% of
the CPU printing to a closed pipe.

I haven't been able to turn up any discussion about this change.  Does
anyone have any insight?  It's surprising and, frankly, unwelcome.


Re: Parse a string into a regex?

2017-05-11 Thread Sean McAfee
On Thu, May 11, 2017 at 4:01 PM, Timo Paulssen  wrote:

> The only way that comes to mind is to use EVAL, but that's not
> golf-friendly at all.
>
> Perhaps you can find something sufficiently short based on .contains,
> .index, .starts-with, .ends-with, and friedns?
>

I'm open to suggestions.  A slightly simplified version of the relevant
part of my current code is this:

$str.comb.classify({ first $_ ~~ *, :k, /<[bdfhkl]>/, /<[gpqy]>/, /<[it]>/,
/j/, True })

I was hoping that I could shorten that list of regexes to something like



which I could then turn into character-class regexes on the fly and avoid
the repeated "/<[" and "]>/".


Parse a string into a regex?

2017-05-11 Thread Sean McAfee
I've been searching for how to parse a string into a regex, like qr/$str/
does in Perl 5, but so far without success.

At first I assumed, by analogy with .Str, .List, etc, that I could call
.Regex on a string, but this is not the case.

On IRC's #perl6 I learned about the <$str> construct, which doesn't really
create a new regex, but keeps a reference to the string around, with some
(to me) surprising semantics:

my $str = 'foo';
my $re = rx/<$str>/;
$str = 'bar';
'foo' ~~ $re;  # no match

Still, it's *almost* sufficient for my needs, except that for the purposes
of a golfing challenge I'm working on, I want to parse the argument to a
WhateverCode object into a regex, but this:

map rx/<*>/, ;

...rather predictably doesn't work.

So, is there in fact any way to simply parse a string into a brand-new
Regex object?


Re: Perl 5 list assignment idiom

2017-03-13 Thread Sean McAfee
On Mon, Mar 13, 2017 at 12:37 PM, Will Coleda  wrote:

> Works the same in Perl 6, and you can avoid the parens. Using helper
> subs that return one or two item lists, here's some sample code:
>
> $ perl6
> > sub one-thing { return ("hi",) }
> sub one-thing () { #`(Sub|140454852043936) ... }
> > 1 == my $script = one-thing
> True
> > $script
> (hi)
>
>
But then:

> $script.WHAT
(List)

In the Perl 5 version, $script is assigned the single element of the
returned list.  In your code, it refers to the list itself.

(Also, wait: It looks like "=" has higher precedence than "=="?  Or does
the "my" affect the parsing somehow?)


Perl 5 list assignment idiom

2017-03-13 Thread Sean McAfee
In Perl 5, list assignment in scalar context evaluates to the number of
list elements on the right-hand side.  That enables an idiom that I rather
like:

1 == (my ($script) = $page->find('//script'))
  or die "Other than exactly one script element found";

Can a similar expression that avoids an intermediate array variable be
written in Perl 6?


Design question re: function parameters

2017-03-07 Thread Sean McAfee
Recently this Perl 6 version of the factorial function was mentioned:

  sub postfix:(Int $n) { [*] 2 .. $n }

I experimented a bit with it and found that I couldn't do

  '3'!

as I naively expected from my Perl 5 intuition.  Similarly, I can't pass an 
integer literal to a function that takes a Str.  String/number transparency 
isn't as total as it used to be.

So now there seems to be some tension in code design.  If I want to freely 
accept both numbers and strings in the manner of Perl 5, it looks like I must 
type all of my function arguments as Cool, or omit the types altogether.  But 
doing so removes helpful information from the function signature.  The argument 
to the factorial is conceptually an Int, but I can't advertise that fact in the 
signature if I want to be able to accept a 
string-which-will-be-converted-to-an-Int.

In my tinkering around I've all but come to the conclusion that I should just 
get used to performing conversions manually, eg:

  '1 2 3'.split(/' '/).map((+*)!)

...even though that feels unpleasantly Pythonic (if more concise).  But first I 
wanted to check in here and see if there's some middle way that perhaps I 
haven't been seeing.


Dynamic method generation?

2011-01-08 Thread Sean McAfee
Hello--

I recently wrote some Perl 5 code similar to the following, and I'm
wondering what might be the analogous construction in Perl 6:

package MyMatcher;

my @SIMPLE_FIELDS = qw(FOO BAR BAZ BLETCH QUUX ...);

for my $field (@SIMPLE_FIELDS) {
no strict 'refs';
*{ is_\L$field } = sub { shift-_matches($field) };
}


Re: Dynamic method generation?

2011-01-08 Thread Sean McAfee
On Sat, Jan 8, 2011 at 3:50 PM, Moritz Lenz mor...@faui2k3.org wrote:

 class MyMatcher {
for FOO BAR BAZ BLETCH QUUX - $field {
MyMatcher.^add_method($field, method() {
 self!matches($field);
}
);
}
 }

 The .^  means a method of the metaclass is called, here add_method

 Maybe you'll find
 http://perlgeek.de/en/article/discovering-meta-object-protocolinteresting.


I did, but now I'm wondering how one would do this in the case of an
anonymous class.  Neither the link you provided, nor Apocalypse or Synopsis
12, seem to address that question.  At least, scanning those pages for the
word anonymous didn't land me near anything that appeared to be relevant.