Re: Language Design: 'special casing' of split()? (i.e. .split performs concomitant .join? )

2020-10-10 Thread Tobias Boege
On Sun, 11 Oct 2020, Tobias Boege wrote:
> On Sat, 10 Oct 2020, William Michels via perl6-users wrote:
> > then proceed to process the function call. As it is my understanding that
> > Raku incorporates a lot of different programming paradigms (imperative,
> > object-oriented, functional, etc.), I'm not sure where this behavior falls
> > on the 'paradigm ladder'.
> > 
> 
> If you want to view it as a matter of paradigm, I guess it would be the
> "operator-centric paradigm", except that it is a method and not an operator.
> 
> The Array class inherits methods from Cool and when you call a method from
> Cool on the Array, the Cool part of the array will answer the call. The
> Array is Cool to advertise that it can be evaluated in numeric and string
> "context". In string context, the array becomes joined using spaces as
> delimiters. Put more bluntly: when you treat an array like a string
> (by calling a string-related method of Cool on it), then Raku treats it
> as a string, even if it must convert it to one before. [ This may sound
> magical, but in reality Array just obtains the method .split from Cool
> and its implementation explicitly converts the invocant, whatever it
> may be, to a Stringy on which a sensible split is defined. ]
> 

Oh, it seems like I was far too slow. From all the other answers, I think
Brad put best what I tried to express using many redundant words. And he
avoided the historically charged and probably inaccurate term "context".

Best,
Tobias


Re: Language Design: 'special casing' of split()? (i.e. .split performs concomitant .join? )

2020-10-10 Thread Tobias Boege
On Sat, 10 Oct 2020, William Michels via perl6-users wrote:
> So I guess the first question I have is whether the 'auto-joining' of array
> elements is specc'ed or not.
> 

I did not find anything that explicitly requires @array.split() to force
@array into a string, but there are tests in S02-types/list.t asserting
that stringified lists must use a space as delimiter.

> What you seem to be saying is that when calling a function on an array, the
> first response is for Raku to call something similar to 'cat' on the array,

No, definitely not. At least not "any function". Only functions (or methods
or operators) by which you express the intent to treat the array as a string.

> then proceed to process the function call. As it is my understanding that
> Raku incorporates a lot of different programming paradigms (imperative,
> object-oriented, functional, etc.), I'm not sure where this behavior falls
> on the 'paradigm ladder'.
> 

If you want to view it as a matter of paradigm, I guess it would be the
"operator-centric paradigm", except that it is a method and not an operator.

The Array class inherits methods from Cool and when you call a method from
Cool on the Array, the Cool part of the array will answer the call. The
Array is Cool to advertise that it can be evaluated in numeric and string
"context". In string context, the array becomes joined using spaces as
delimiters. Put more bluntly: when you treat an array like a string
(by calling a string-related method of Cool on it), then Raku treats it
as a string, even if it must convert it to one before. [ This may sound
magical, but in reality Array just obtains the method .split from Cool
and its implementation explicitly converts the invocant, whatever it
may be, to a Stringy on which a sensible split is defined. ]

The same principle makes code like `"2" ** 5` or `2.map: * ** 5` work,
where in the first case a string 2 is treated as, and hence converted to,
a number, and in the second case an integer is treated like a list and
indeed Raku will arrange for that to happen on the fly.

In those two cases it is exponentiation that forces the invocant to become
a numberic and it is mapping that forces the invocant to become a listy
thing transparently. In the same way splitting something forces it to
become a string first. [ Again, it is not the language that somehow picks
up *syntactical* clues from your code about what to convert to what, but
it is the core implementation of, e.g., Any.map which is inherited by Int,
in the above example, and converts whatever its invocant is to something
that is iterable, because iteration is what you wanted to happen by calling
.map on it. ]

> I can point to the (functional) R-programming language to show what happens
> there. When manipulating "array-like" (i.e. vector) objects in R, you can
> do nested function calls, or sequential (piped) function calls, and still
> get the same data structure out at the end. So a 10-element input gives a
> 10-element output. In the R-GUI (i.e. REPL):
> 
> > 0:9
>  [1] 0 1 2 3 4 5 6 7 8 9
> > x <- 0:9
> > is.vector(x)
> [1] TRUE
> > length(x)
> [1] 10
> > # using base-R:
> > sqrt(tan(cos(sin(x
>  [1] 1.2479614276 0.8867679488 0.8398446968 1.2344525173 0.9431819962
> 0.8044843661 1.1966884594
>  [8] 1.0064589934 0.7823305851 1.1415611482

Yes, so it seems that R prefers to vectorize function calls over arrays.
In Raku, if you want to apply a method or sub or operator to every element
of a list instead of the list object itself (which may have its own over-
load or inherited version of that method causing it to behave strangely,
which is the topic of this thread), you ought to use `map` or a hyper
operator.

In Raku, if you call sin on an array, that puts the array in a numeric
context which makes the array collapse to the closest numeric thing
that Raku makes the convention to associate with it: the number of its
elements. Behold:

  my @x = 0..9;
  say @x.sin; #= -0.5440211108893698 = sin(10)

This is an excellent example you chose, because .sin and .split both
become methods of Array because Array inherits Cool. They both do not
apply element-wise but cause the entire invocant array to adapt to
context -- they become a number or a string depending on how you want
to treat it.

Best,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Language Design: 'special casing' of split()? (i.e. .split performs concomitant .join? )

2020-10-06 Thread Tobias Boege
On Tue, 06 Oct 2020, William Michels via perl6-users wrote:
> [...]
>
> So my question regards "special-casing" of split/join in Raku. Is the first
> result on comma-delimited data the default, i.e. joining disparate elements
> of an array together head-to-tail? Or is the second result on
> whitespace-delimited data the default (i.e. no joining of disparate
> elements together head-to-tail)? Which one is special-cased? If the second
> one is special-cased, is that why Raku returns 5 elements and not 4
> elements as in lines C/D (implied join)?
> 

My answer is going to be that there is *no* special-casing. You have an
array of strings @a and you call the `split` and `join` methods on it.
These two methods are not alike. `join` is a proper method of List and
it joins stringifications of the elements of that list.

Crucially, the `split` method comes from somewhere else: Array inherits
it from the Cool class. When you call Array.split, what happens is that
your entire array gets stringified first (joining stringifications of
its elements with spaces) and then Cool.split is called on that string
representation of your array. This is even mentioned in the introductory
paragraph about Cool [1].

This is the strangely consistent explanation of the effects you observed.
You see, the only "special" thing is that Array.split being a Cool method
causes the array to be joined with *spaces* before the splitting starts,
but this always happens, independently of the join/split arguments.

Array.split does in particular *not* "pass on" the split call to the
elements of the array. For that you would use @a».split, although this
would cause (itemized) Seqs for each element of @a to end up in the
returned list, so what you actually thought you were doing may be
written as

  @a».&{ .split(",").Slip }

I am sure there are ways to write it more alphabetically.

Best,
Tobias

[1] https://docs.raku.org/type/Cool

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: liens and :chomp question

2020-08-30 Thread Tobias Boege
On Sun, 30 Aug 2020, ToddAndMargo via perl6-users wrote:
> >- You are calling .lines on the value of .IO.open which is an
> >  IO::Handle. IO::Handle.lines does not take a named argument
> >  :chomp, so passing one is useless.
> 
> That explains it.
> 
> Bu:
>  https://docs.raku.org/type/IO::Path#method_lines
> 
>  (IO::Path) method lines
>  Defined as:
> 
>  method lines(IO::Path:D: :$chomp = True, :$enc = 'utf8', :$nl-in =
> ["\x0A", "\r\n"], |c --> Seq:D)
> 
>  Opens the invocant and returns its lines.
> 
>  The behavior is equivalent to opening the file specified
>  by the invocant, forwarding the :$chomp, :$enc, and
>  :$nl-in arguments to IO::Handle.open, then calling
>  IO::Handle.lines on that handle, forwarding any of
>  the remaining arguments to that method, and returning
>  the resultant Seq.
> 
> The "signature" line (cryptogram) clearly stated that
> ":$chomp" is a parameter of the method.
> 
> Now you are obviously correct that :chomp is ignored.
> If I am not mistaken, I have just tripped over another
> error in the documentation.  Your take?
> 

You confuse two methods that have the same name "lines". One of them,
which exists in the IO::Path class, has a :chomp argument. The other,
on IO::Handle does not.

  "path".IO.lines()   <-- calls lines on an IO::Path (supports :chomp)
  "path".IO.open.lines()  <-- calls lines on an IO::Handle (does not support 
:chomp)

In the second case, if you want chomping to happen you have to pass
the :chomp to the *open* call, as you do below:

> $ p6 'dd "Lines.txt".IO.open(:chomp).lines()[3,2];'
> ("Line 3", "Line 2")
> 
> $ p6 'dd "Lines.txt".IO.open(:!chomp).lines()[3,2];'
> ("Line 3\n", "Line 2\n")
> 
> $ p6 'say "Lines.txt".IO.open(:!chomp).lines()[3,2];'
> (Line 3
>  Line 2<-- why the space?
> )
> 

The better question is "whose space". You print again the List of lines
you obtain by indexing the return value of .lines, so expect output in
the form of "(item1 item2 ...)". This is where your space comes from.
Lists print that way. They insert spaces between their elements.

In this case, you had :chomp disabled, so the "Line 3" item printed
"Line 3\n", including the newline that was not chomped, then the space
and then the next item, "Line2\n" with its newline, then the closing
parenthesis which is also part of printing a List.

This serves to better illustrate where one element of the List ends
and where the next begins. The space separate them:

  $ rakudo -e 'say "Lines.txt".IO.open(:!chomp).lines()[3,2].map({ "«$_»" });'
  («Line 3
  » «Line 2
  »)

Best,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: liens and :chomp question

2020-08-29 Thread Tobias Boege
On Sat, 29 Aug 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> I am trying to figure out how to use line with :$chomp.
> Now what am I doing wrong?
> 
> 
> $ alias p6
> alias p6='perl6 -e'
> 
> $ p6 'say "Lines.txt".IO.open.lines(:chomp)[3,2];'
> (Line 3 Line 2)
> 
> $ p6 'say "Lines.txt".IO.open.lines(:!chomp)[3,2];'
> (Line 3 Line 2)
> 
> I am looking for
> 
> Line 3
> Line 2
> 

Then I would suggest

  say $_ for "Lines.txt".IO.lines[3,2]

> Now what am I doing wrong?

  - You are calling .lines on the value of .IO.open which is an
IO::Handle. IO::Handle.lines does not take a named argument
:chomp, so passing one is useless. The .lines method on an
IO::Path, however, which I call in my snippet, supports
such an argument. You could call .IO.lines(:chomp) or
.IO.open(:chomp).lines.

  - You should use :chomp and not :!chomp because :chomp removes
the trailing newline from every line read for you. When you
use `say`, a trailing newline is added automatically, so in
order to get only one newline in the output per item, you
have to :chomp. The :chomp argument does not appear in my
snippet because it is the default, but you could have done

  say $_ for "Lines.txt".IO.lines(:!chomp)[3,2]

to see the effect of not chomping.

  - What you `say` is the return value of indexing the Seq that
is returned by .lines. This is an object of type List and
will always print in the format "(item1 item2 ...)" and not
in the format you desire. In the snippet above I iterate
over that List with `for` and print every item in a new line.

Best,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: lines :$nl-in question

2020-08-28 Thread Tobias Boege
On Fri, 28 Aug 2020, ToddAndMargo via perl6-users wrote:
>https://docs.raku.org/type/IO::Path#method_lines
> 
>(IO::Path) method lines
> 
>Defined as:
> 
>method lines(IO::Path:D: :$chomp = True, :$enc = 'utf8', :$nl-in = 
> ["\x0A", "\r\n"], |c --> Seq:D)
> 
>Opens the invocant and returns its lines.
> 
>The behavior is equivalent to opening the file specified
>by the invocant, forwarding the :$chomp, :$enc,
>and :$nl-in arguments to IO::Handle.open, then calling
>IO::Handle.lines on that handle, forwarding any of the
>remaining arguments to that method, and returning the
>resultant Seq.
> 
> And if I am not pushing it, what is `|c`?
> 
> [...]
> I do not understand

The description of this method says that it shall do two things:

  - open the invocant path (IIRC you like to use the phrase
"what is fed into it" instead of "invocant") which returns
an IO::Handle,

  - then call the lines method on this IO::Handle, resulting
in a sequence of lines (Seq in Raku), and it should return
this same Seq value.

The lines method on an IO::Path does the same as the lines method on an
IO::Handle, except that it has to open the path before to get a handle.

The arguments to the IO::Path.lines method therefore split into two groups:

  - :$chomp, :$enc, :$nl-in which are passed on to the open call
in the first bullet point above,

  - all the remaining arguments, whatever they are, are *captured*
by the syntax |c and will be forwarded to the IO::Handle.lines
call in the second bullet point above.

The |c is a so-called capture parameter [1]. It is used in a signature
(what you stubbornly call "cryptogram") when a method wants to inspect
some (or none) of the arguments it got but keep all the others in a
black box, named c here. The capture black box allows forwarding these
extra arguments to some other call. The point is that the IO::Path.lines
method does not need to know which arguments the target IO::Handle.lines
method accepts. It only needs to take everything in and pass it on.

It follows that you read about the meaning of the individual arguments or
which arguments it makes sense to pass to IO::Path.lines in the documentation
pages for the IO::Handle.open and IO::Handle.lines methods, which are linked
to in the text. Really, everything that IO::Path.lines does is redistribute
its arguments to two other method calls.

The documentation of lines does not tell you that |c is a capture parameter,
but it described what it is used for with the slide-in

  [...] forwarding any of the remaining arguments to that method [...]

in the paragraph you quoted. The connection of that slide-in with the
"|c thing" is a matter of text comprehension.

Best,
Tobias

[1] https://docs.raku.org/type/Signature#Capture_parameters

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Raku User's Survey 2020 out now....

2020-08-27 Thread Tobias Boege
On Thu, 27 Aug 2020, ToddAndMargo via perl6-users wrote:
> To pick out particular lines:
>$ cat Lines.txt | raku -e '.say for lines()[3,2,5]'
>Line 3
>Line 2
>Line 5
> 
> If it is, it is buried somewhere.
> 
> And what goes inside the ()?  That may seem like a dumb
> remark (especially since I live and die in Top Down and
> know very well what the () does) but it is a common mistake
> I make with lines is forgetting the () when using the [].
> 

How does that mistake manifest? I cannot see a way in which omitting
the sub call parentheses in code like that could possibly lead to some
different behavior.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Seq whitespace sensitivity? (was Re: print particular lines question)

2020-08-26 Thread Tobias Boege
On Wed, 26 Aug 2020, Tobias Boege wrote:
> Observe:
> 
>   > 1 ...^ 20
>   (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
> 
>   > 1 ... ^20  # actually C«1 ... (0..19)»
>   (1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)
> 
> The documentation [1] states that the C«...» infix is list-associative
> and while I have never seen an example of that (including in that docs
> page), it would explain why it happily takes in your list (1) and then
> your list (0 .. 19) and concatenates them into a sequence, without
> applying any of the usual sequence operator magic.

And I must correct myself. The associativity has nothing to do with this.
I don't know where my mind was when I wrote that. From the documtation,
I would blame the slurpy argument **@ for that behavior of just taking in
lists and effectively iterating them into a new Seq, and in Rakudo it is
apparently this special candidate:

  # https://github.com/rakudo/rakudo/blob/e2855aa/src/core.c/operators.pm6#L129
  multi sub infix:<...>(\a, Mu \b) {
  Seq.new(SEQUENCE(a, b))
  }

Best,
Tobias


Re: Seq whitespace sensitivity? (was Re: print particular lines question)

2020-08-26 Thread Tobias Boege
On Wed, 26 Aug 2020, William Michels via perl6-users wrote:
> > 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) } ... *
> >
> 
> Hi Sean, that's a neat solution! I seem to have found an oddity though
> (whitespace sensitivity). In the REPL:
> 
> > say { $++ * ($ *= -1) } ...21
> (0 1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 17 -18 19 -20 21)
> > say { $++ * ($ *= -1) } ...^21
> (0 1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 17 -18 19 -20)
> > say { $++ * ($ *= -1) } ... 21
> (0 1 -2 3 -4 5 -6 7 -8 9 -10 11 -12 13 -14 15 -16 17 -18 19 -20 21)
> > say { $++ * ($ *= -1) } ... ^21
> (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
> 
> I would have expected the last line of code (whitespace between "..."
> and "^21") to give the same answer as the first three. Any ideas?
> 

The difference is likely to come from the fact that "^20" as a term is
a shorthand for the range "0..^20", while "...^" is the sequence operator
with exclusive endpoint. Placement of whitespace will dictate where the
little hat attaches to and thus change the meaning of the statement.

Observe:

  > 1 ...^ 20
  (1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

  > 1 ... ^20  # actually C«1 ... (0..19)»
  (1 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19)

The documentation [1] states that the C«...» infix is list-associative
and while I have never seen an example of that (including in that docs
page), it would explain why it happily takes in your list (1) and then
your list (0 .. 19) and concatenates them into a sequence, without
applying any of the usual sequence operator magic.

When you write "1 ...^20" I suppose that longest-token matching prefers
the former interpretation as it makes the infix token longer.

Best,
Tobias

[1] https://docs.raku.org/language/operators#index-entry-..._operators

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Combining multiple "is..." traits into one?

2020-08-11 Thread Tobias Boege
On Wed, 12 Aug 2020, Stuart Hungerford wrote:
> Hi,
> 
> I'm working with roles where the mixing-in classes and roles need to
> have some mixin-specific notion of equality. So I have an Equality
> role that can also be
> mixed in as needed:
> 
> role Equality {
>   method equal(Equality:D) of Bool:D {...}
> }
> 
> To make using the role easier I've created an infix operator "=/=". To
> give the infix operator predcitable semantics I need to specify the
> precedence and the associativity with traits:
> 
> sub infix:<=/=>(Equality:D \x, Equality:D \y) of Bool:D is
> equiv(&infix:<==>) is assoc is export {
>   x.equal(y)
> }
> 
> Is there some way to combine traits to a more succinct trait?  Something like:
> 
> subset Equivalence of Routine where {magic}...;
> 
> sub infix:<=/=>(Equality:D \x, Equality:D \y) of Bool:D is equivalence
> is export;
> 
> Would a custom version of the trait_mod: routine do the trick?

Yes:

  multi trait_mod: (Routine $r, :$equivalence!) {
  trait_mod:($r, :equiv(&infix:<==>));
  trait_mod:($r, :assoc);
  }

At the same time you can mix in a role if you need to, by adding
`$r does Equivalence`. If you want to query this information of a
predefined operator to make a subset, check for instance

  dd &infix:<+>.prec
  # Hash element = {:assoc("left"), :prec("t=")}

at least on Rakudo. I have no idea if this attribute or the format
for the 'prec' key in particular are standardized.

Best,
Tobias


Re: subs and the type system

2020-07-20 Thread Tobias Boege
On Mon, 20 Jul 2020, Gianni Ceccarelli wrote:
> Aside:
> 
> ``(sub (Int $ --> Int) {}) ~~ Walkable`` is false, because
> ``:(Int $ --> Int) ~~ :(Numeric $ --> Numeric)`` is false, which is
> correct because function subtypes should be contravariant in the parameter
> types and covariant in the return type (i.e. if the caller passes a
> Numeric, the callback should accept a Numeric or a *more general*
> type, and if the caller expects a Numeric back, the callback should
> return a Numeric or a *more specific* type).
> 
> But then ``:(Numeric $ --> Int) ~~ :(Numeric $ --> Numeric)`` is also
> false, and I feel like it should be true. Opinions?
> 

My _opinion_ is that you are right, be it only because there exist words
reminiscent of category theory that describe your desired behavior :-)

But the source code of a Signature smartmatching another Signature [1]
explicitly uses smartmatching for the parameter types and uses the
unforgiving container identity operator to compare the return types:

  91  return False unless self.returns =:= $topic.returns;

The `eqv` implementation for two Signatures uses `=:=` as well, so this
restriction seems deliberate. Changing the `=:=` to a `.does` call makes
your code snippet work:

  $ ./rakudo-m -e 'say :(Numeric $ --> Int) ~~ :(Numeric $ --> Numeric)'
  True

but it creates problems with roast that appear to spread multiple parts
of the language. Failing tests are:

  t/spec/S10-packages/precompilation.rakudo.moar  (Wstat: 65280 
Tests: 32 Failed: 0)
  t/spec/S02-types/compact.rakudo.moar(Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S02-types/native.rakudo.moar (Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S06-currying/positional.t(Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S06-signature/closure-parameters.rakudo.moar (Wstat: 256 
Tests: 21 Failed: 1)
  t/spec/S09-typed-arrays/native-int.rakudo.moar  (Wstat: 65280 
Tests: 169 Failed: 0)
  t/spec/S09-typed-arrays/native-num.rakudo.moar  (Wstat: 65280 
Tests: 157 Failed: 0)
  t/spec/S09-typed-arrays/native.t(Wstat: 65280 
Tests: 3 Failed: 0)
  t/spec/S17-lowlevel/cas-int.t   (Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S17-promise/nonblocking-await.t  (Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S32-array/splice.rakudo.moar (Wstat: 256 
Tests: 0 Failed: 0)
  t/spec/S32-basics/xxPOS-native.t(Wstat: 65280 
Tests: 15 Failed: 0)
  t/spec/S32-list/iterator.t  (Wstat: 65280 
Tests: 48 Failed: 0)
  t/spec/integration/precompiled.t(Wstat: 256 
Tests: 9 Failed: 1)

Some failures are very dubious like this error, resulting in the test
not even starting (there are multiple of this sort, as you can see):

  $ ./rakudo-m -Ilib t/spec/S06-currying/positional.t
  ===SORRY!===
  No appropriate parametric role variant available for 'array::intarray'

Maybe my small changes (patch attached) create inconsistencies with these
other parts of the language (oftentimes related to native types?), or maybe
the test suite relies on (hence specifies) non-covariance. I don't know.

Best,
Tobias

[1] 
https://github.com/rakudo/rakudo/blob/master/src/core.c/Signature.pm6#L34-L93

PS: I want to note that my first attempt naïvely replaced the `=:=` with
`~~` but this set roast even more on fire which I think is related to `~~`
autothreading on junctions, as opposed to `=:=` and `.does`.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk
diff --git a/src/core.c/Signature.pm6 b/src/core.c/Signature.pm6
index ea2b5cabe..72eff7bdd 100644
--- a/src/core.c/Signature.pm6
+++ b/src/core.c/Signature.pm6
@@ -88,7 +88,7 @@ my class Signature { # declared in BOOTSTRAP
 return False unless $hasslurpy;
 }
 }
-return False unless self.returns =:= $topic.returns;
+return False unless $topic.returns.does(self.returns);
 True;
 }
 
@@ -160,7 +160,7 @@ multi sub infix:(Signature:D \a, Signature:D \b) {
 return False unless a.WHAT =:= b.WHAT;
 
 # different return
-return False unless a.returns =:= b.returns;
+return False unless a.returns.does(b.returns);
 
 # arity or count mismatch
 return False if a.arity != b.arity || a.count != b.count;


Re: subs and the type system

2020-07-20 Thread Tobias Boege
On Mon, 20 Jul 2020, Theo van den Heuvel wrote:
> Hi gurus,
> 
> after looking at the documentation on Sub, Signature and the raku type
> system I find myself unable to constrain the types of functions in the way I
> think I need.
> 
> The situation: I have a function, let's call in 'walker', whose first
> parameter is a callback.
> I wish to express that only callbacks with a certain Signature and return
> type are acceptable.
> Let's say the callback should follow :(Numeric $n --> Numeric). My callback
> is going to be more complicated, but for simplicity sake.
> 
> I was hoping to be able to use a named type of function with this signature.
> I know I can say
> 
> my $sig =  :(Numeric $n --> Numeric);
> 
> but my attempts to use $sig fail. I found no example of an application
> beyond smartmatching.
> 
> [...]
>
> but I was hoping for an explicit type, maybe using class, or subset or
> roles.
> I hope to say soemething like
> 
> sub walker(Walkable &callback, ...)
> 
> What am I missing here?
> 

You said that you know how to check signatures via smartmatching.
Smartmatching is great, there isn't much to know beyond it. The way
to shoehorn smartmatching into the type system is `subset`:

  subset Walkable of Callable where {
  .signature ~~ :(Numeric --> Numeric)
  };

If your callback signature is more complicated, all the more reason to
give it a name via subset. You can use it now almost like you wanted:

  sub walker (Walkable $w) {
  say $w($_) for 1..10
  }

  walker(-> Numeric $x --> Numeric { $x.sqrt });  # WORKS
  walker(-> $x { $x.sqrt });  # DOESN'T

You cannot write `Walkable &w` in the signature of &walker because the
combination of a type and the &-sigil apparently means that `&w` should
be Callable and return a Walkable. That's why I use the $-sigil. [*]

Note that if you constrain the signature of a Callable, then you have
to provide the appropriate signature statically, as demonstrated.

Best,
Tobias

[*] N.B. I failed to find a reference for this in the documentation.
I discovered it by writing `sub walker (Int &w)` and provoking a type
checking error which told me that it was expecting `Callable[Int]`.
(That was also my gut feeling.) According to source code, Callable is
a parametric role in Rakudo whose first parameter indeed is the return
type. This is all somewhat nebulous to me (how does the Callable-
parametric way to specify return type compare with smartmatching
against .signature, for example? They don't seem equivalent!), so
I stick with the $-sigil.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: root cubic

2020-07-09 Thread Tobias Boege
On Thu, 09 Jul 2020, Tobias Boege wrote:
> Now, there are effective ways to represent algebraic numbers like 9 ** (1/3)
> in such a way that you can do arithmetic with them, but I'm not aware of any
> implementation of that available to Raku. For someone with enough tuits,
> I think this [1] can serve as a sort of high-level manual for creating such
> a module. In terms of ready-made non-Raku packages, I only know of CGAL [2],
> which provides a clean and even (template-)parametric interface to real
> algebraic numbers. In fact, I might have a try at NativeCall'ing it this
> evening.
> 

Here is a super spartan version of this:

  https://github.com/taboege/raku-Real-Algebraic

The module is:

  - not the most straightforward to build (but given all dependencies,
zef should do everything required automatically, and it should
warn about missing dependencies),
  - not well integrated with the rest of Raku,
  - untested.

But it accomplishes the following:

  my \η = - (8ra).kth-root(4);

Turn the literal 8 into a Real::Algebraic number so that methods and
operator overloads work, then take its real, positive 4th root and negate
that number for good measure. η is now an instance of Real::Algebraic.

  say η ** -4 == (1/8)ra;  # OUTPUT: «True»

As expected, raising it to the -4th power produces another Real::Algebraic
number (in some hidden internal representation) that can be successfully
compared for equality against 1/8.

Note that the Num version of this, `8.sqrt.sqrt ** -4 == 1/8`, yields
False, just like `0.1 + 0.2 == 0.3` is false in languages that don't
use rationals for decimal literals.

And finally, there is a FatRat coercer that gives you arbitrarily close
rational approximations, here accurate to within at least 200 decimals
(compare with WolframAlpha, for instance):

  say η.FatRat(1e-200).nude;
  
(-2319046107914249546164017690226327191927995914167183915057429614886355365218221502899659586060964349175885087790712999436533151194306883153880674634813417790513862919501362233566580543228616216472448597249046963887795
 
1378913065775496824682182051857728448902028277271278088224317349054049721856053955032165000485952146958446223387833982704161766047792183079895777875237766653530662154044294980748355504146827894396365898183024673030144)

But this is as far as my interest in this goes at the moment. Hope it
is interesting to some.

Best,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: root cubic

2020-07-09 Thread Tobias Boege
On Thu, 09 Jul 2020, Aureliano Guedes wrote:
> Hi all,
> 
> A quick question.
> 
> This is expected?
> 
> raku -e 'say 9 ** (1/3)'
> 2.080083823051904
> 
> 
> Why do I'm asking this?
> I know about the computational floating problem and I also know that the
> Raku deal with rational whenever it is possible and store numbers as
> expressions (actually I don't know if there are more details). That's why
> 0.2 + 0.1 == 0.3 in Raku returns True whilst in other languages like
> Python, Perl5, and Ruby return False.
> 
> Then, I was just playing around and I'd like to check if it is expected.
> 

I for one expected it. The equation 0.1 + 0.2 == 0.3 uses the Rat type in
Raku, which stores rational numbers as exact fractions of numerator and
denominator, avoiding the floating point inaccuracies you mention, and
hence making equality comparisons trustworthy.

The number 9 ** (1/3) is not rational and in general exponentiation with a
fractional power might not produce a rational number, so exact representation
via Rat is out of the question. Therefore Rakudo does the computation with
Num, which are inexact floating point values again.

Now, there are effective ways to represent algebraic numbers like 9 ** (1/3)
in such a way that you can do arithmetic with them, but I'm not aware of any
implementation of that available to Raku. For someone with enough tuits,
I think this [1] can serve as a sort of high-level manual for creating such
a module. In terms of ready-made non-Raku packages, I only know of CGAL [2],
which provides a clean and even (template-)parametric interface to real
algebraic numbers. In fact, I might have a try at NativeCall'ing it this
evening.

Best,
Tobias

[1] https://math.stackexchange.com/a/3144516
[2] https://www.cgal.org/

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: why so different

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> Thank you for the clarification.
> 
> There is a method to set Rat precision at the scope of the program to apply
> to all *.Rat() cases?
> 

I don't know, based on a quick search in the documentation, of any global
setting. The hacky solution would be to wrap the method like this:

  say pi.Rat.nude;  # OUTPUT: (355 113)

  Num.^find_method('Rat').wrap: -> |c {
  # Make the default argument 1e-20
  callwith |(|c, 1e-20 if c.elems ≤ 1)
  };

  say pi.Rat.nude;  # OUTPUT: (245850922 78256779)

This program has three parts. First, we print pi.Rat.nude for comparison.
The nude method returns numerator and denominator of a Rat as a list.
The last part is just looking at pi.Rat.nude again to confirm that the
change in the middle has worked and increased the default precision.

You said you are relatively new to Raku, so let me explain the middle part.
Raku has a special syntax for calling metamethods (i.e. doing introspection)
on an object or type, which is the .^ operator. I use it to access an object
representation of the Rat method on the Num type. I can wrap some code of
my liking around this method via its wrap method.

The `-> |c { … }` syntax creates an anonymous code block that wraps around
the Num.Rat method and it accepts all arguments that may be passed as a
Capture [1] in the variable c. If that Capture does not have a first
parameter, i.e. the precision is not specified, I sneak in my 1e-20.
Afterwards, the `callwith |(…)` part unpacks the (modified) captured
arguments and calls the original method that I am wrapping [2].

Effectively, I pass a precision of 1e-20 whenever the caller did not pass
a precision. You can see that the wrapping takes effect immediately in
the last line of the above program.

Ideally, this could be turned into a module that hides the questionable
means behind a dynamic $*RAT-PRECISION variable or so. That is, unless
someone comes up with an even better solution.

Best,
Tobias

[1] https://docs.raku.org/type/Capture
[2] https://docs.raku.org/routine/wrap

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: why so different

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Aureliano Guedes wrote:
> Hi all,
> 
> First, I'm naive in Raku. Then let's go to my question.
> 
> I'm trying to figure out why we got so different results here:
> 
> > e.Rat()**(pi.Rat()*i)
> -0.9902-1.3942922582021257e-07i
> > e**(pi*i)
> -1+1.2246467991473532e-16i
> > e.Rat()**(pi.Rat()*i) == e**(pi*i)
> False
> 
> I understand the Num actually have the traditional behavior which leads
> this:
> 0.1.Num() + 0.2.Num() != 0.3.Num()
> 
> And Rat is awesome cos deal nice to the real world.
> 
> Anyway, I do not expect so different results between Rat and Num.
> 

First, e and π are not rational numbers, so Num (IEEE 754 double)
and Rat (pair of bigint numerator and denominator) both will be only
approximations.

The literals e and pi in Raku are typed as Num and when you call the
Rat method on them, you get a Rat back with the *default* precision
of 1e-6 [1]. That is a lot less precise than the Nums you started
with, hence the difference. Try supplying a large enough precision:

  > e.Rat(1e-200)**(pi.Rat(1e-200)*i)
  -1+1.2246467991473532e-16i

This is better than a default .Rat() but notice that you cannot get
past the limited precision in the source Nums, which is ca. 1e-16.

Best,
Tobias

[1] https://docs.raku.org/routine/Rat

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: junctions and parenthesis

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Elizabeth Mattijsen wrote:
> BEGIN trait_mod:(&any, :tighter(&infix:<*>));
> 
> comes to mind, but that doesn't seem to do the trick.
> 

My guess: tighter and looser are only consulted by the parser
in contexts where 'any' was recognized as an *operator*.


Re: junctions and parenthesis

2020-06-22 Thread Tobias Boege
On Mon, 22 Jun 2020, Joseph Brenner wrote:
> Patrick R. Michaud  wrote:
> 
> > The "any" function is just like any other function taking an arbitrary list
> > of arguments (including user-defined functions).  As such it parses with
> > lower precedence than comparison operators -- so "eq" binds more tightly
> > than "any".
> 
> Thanks, makes sense.
> 
> > I'm not exactly sure what sort of warning should go here, or how it'd be
> > detected.
> 
> Yes, exactly.  From one point of view it's working as designed-- to me
> it felt pretty weird, though.
> 
> Speculating wildly:  could there be a need for a different type of
> function with different precedence?
> 

You can achieve this today by redefining &any to be a prefix operator
and provide it with tight enough precedence. In this example, I pick
infix multiplication as the argument stopper, which is in particular
tighter than the relevant eq operator; your mileage may vary:

  sub old-any (|c) { CORE::{'&any'}.(|c) }

  multi prefix: (|c) is tighter(&infix:<*>) {
  old-any |c
  }

  say so any  eq any ;# True (fixed)
  say so old-any() eq old-any();  # True
  say so old-any   eq old-any ;   # False

Now I'd be interested to see how someone would turn this into a
frugal-sub declarator or an `is frugal` trait.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: I need help sorting a list

2020-05-24 Thread Tobias Boege
On Sun, 24 May 2020, Elizabeth Mattijsen wrote:
> Hmmm... it appears we need to numerify the match to get numeric comparison 
> semantics, so we put a "+" before the match:
> 
> $ raku -e 'my @x=.sort: { +m/ \d+ $/ }; for @x { say $_; 
> }'
> a1
> a2
> a5
> a123
> a133
> 

So I think this would be a more general "version sort" then, where the number
doesn't have to be at the end only:

  @things.sort: {
  .comb(/ \d+ | \D+ /)
  .map({ .Int // .self })
  }

It does not conform to all the rules about natural sort on Rosetta Code [1]
but I like how

  - longest-token matching,
  - .sort behavior on (differently-sized) tuples, and
  - .Int returning an (undefined) Failure

work together here.

Regards,
Tobias

[1] https://rosettacode.org/wiki/Natural_sorting

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: I need help sorting a list

2020-05-24 Thread Tobias Boege
On Sun, 24 May 2020, ToddAndMargo via perl6-users wrote:
> On 2020-05-24 02:24, Elizabeth Mattijsen wrote:
> > dd .sort: { m/ \d+ $/ }
> >
> 
> Hi Elizabeth,
> 
> This seems to work:
> 
>$ raku -e 'dd .sort: { m/ \d+ $/ };'
>("a5", "a6", "a33", "a111").Seq
> 
> 
> But I can't figure out how to get it into an array:
> 
>$ raku -e 'my @x=.sort: { m/ \d+ $/ }; for @x { say
> $_; }'
>a5
>a2
>a123
>a133
>a1
> 

I think getting it into an array is not the problem, you did the
right thing by assigning the Seq into @x. The sort characteristic
that Liz used, { m/ \d+ $/ }, doesn't do the right thing (at least
for me). I cannot tell you why it is an apparent no-op, though.

Converting the extracted Match to an Int does work:

  $ raku -e 'my @x = .sort: { +m/ \d+ $/ }; dd @x'
  Array @x = ["a1", "a2", "a5", "a22", "a123", "a133"]

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: sqrt and Buf question

2020-05-14 Thread Tobias Boege
On Thu, 14 May 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> 1) how do I get 40 or more digits out of sqrt?
> 

Meaningful digits? Not possible as sqrt uses limited precision. I think
the IEEE 754 doubles that I would suspect to be used internally are capped
way below 40 significant decimal digits.

> 2) how to I assist those bytes to a 40 (or more)
> byte long Buf?
> 
> This obviously does not work:
> 
> my Num $x = 3.sqrt; my Buf $y = Buf.new($x)
> 
> Type check failed in initializing element #0 to Buf; expected uint8 but got
> Num (1.7320508075688772e0)
>   in block  at  line 1
> 

You can convert the Num to a string and put that string into a Buf:

  Buf.new(3.sqrt.Str.encode)

That's what I'd do without any clue at all about who is supposed to use
this Buf. At least the buffer is about as long as the number is decimal
digits, which seems to be what you wanted?

Regards,
Tobias


Re: NativeCall questions

2020-05-08 Thread Tobias Boege
On Fri, 08 May 2020, David Santiago wrote:
> I also noticed that although my data string is defined as
> CArray[uint8], when i loop through the array, the values are signed
> ints:
> 
> say $_ for $ed.data[0..10];
> 
> output:
> 
> -98

There is an old open bug report about this: 
https://github.com/Raku/old-issue-tracker/issues/5859

Best,
Tobias


Re: subst :g and captures in the replacement

2020-04-19 Thread Tobias Boege
On Sun, 19 Apr 2020, yary wrote:
> How would one do s/(.+),(.+)/$1,$0/ using .subst ?
> -y

You can pass a code block as the second argument which assembles the
replacement text. The block is evaluated anew for every substitution
and it has access to the latest captures:

  say .subst(/(.*) ',' (.*)/, { "$1,$0" }) for «a,z 10,12 l,25»
  # z,a
  # 12,10
  # 25,l

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: subst :g and captures in the replacement

2020-04-19 Thread Tobias Boege
On Sun, 19 Apr 2020, yary wrote:
> Question from today's Raku meetup. This works in a way I expect
> 
> > 'fosdffgg'.subst(/f+/,"( "~ * ~" )", :g);
> ( f )osd( ff )gg
> 
> This one, $0 gets the single f each time
> 
> > 'fosdffgg'.subst(/(f+)/,"( $0 )", :g);
> ( f )osd( f )gg
> 
> Bug or misunderstanding on my part?
> 

Not a bug. You are calling the subst method on a string. Naturally, in order
to perform the call, all the arguments you pass have to be evaluated first.
This includes interpolating $0 into the string "( $0 )". You take whatever
$0 contains, put it into a string and pass that into subst. In your case $0
seemed to confusingly stringify to "f". Consider this instead:

  "oops" ~~ /^(..)/ andthen say 'fosdffgg'.subst(/(f+)/,"( $0 )", :g)
  # OUTPUT: «( oo )osd( oo )gg»

where I deliberately set $0 beforehand.

Your first variant works because you pass a Callable into subst and when you
do that subst will repeatedly evaluate the Callable. Not so when you pass a
string value.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: tip: Windows, Git, and those nice Linux utilities

2020-04-09 Thread Tobias Boege
On Thu, 09 Apr 2020, ToddAndMargo via perl6-users wrote:
> On 2020-04-09 09:39, Richard Hainsworth wrote:
> > Am I missing something here?
> > 
> > It would seem obvious to me that Git and Raku are not linked in any way,
> > except of course for developers who only use Git with Raku, or who only
> > have a dependency on Git through zef.
> > 
> > It would therefore seem to me that a Raku / Zef distribution should NOT
> > bundle Git. Consequently, 'Git' is not "forgotten" and that is *should*
> > be installed independently.
> 
> Git is required for Zef to operate.  So Git is a dependency
> of Zef.  Therefor Zef should either include Git or warn
> the user that he needs to download it himself

That's an exaggeration. git is a dependency of the p6c ecosystem that zef
is preconfigured to support. But zef currently supports CPAN as well which
does not need git. If you don't have git installed, you get access to CPAN
(and of course modules you install from your own local filesystem) but not
p6c. Whether that is enough is your call.

AFAICS, git is not a dependency of the zef packge in Fedora either. I just
started a fresh VM, installed Rakudo and zef and then via zef a module and
its dependencies -- all without git.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: regex objects as hash keys

2020-04-05 Thread Tobias Boege
On Sun, 05 Apr 2020, Joseph Brenner wrote:
> I find in Raku that (as expected) I can use an object as a hash key:
> 
> class Rutabaga { method color { say "purple (and white)"; } }
> 
> my $obj = Rutabaga.new
> my %vegeout;
> %vegeout{ $obj } = "this works";
> 
> And for something I was doing I wanted to save up
> data about matches for various different regexs,
> so I thought I could just use a hash for this, like so:
> 
> my (%match_locs, $loc);
> 
> my $godzilla_rx  = rx:i{ << godzilla >> };
> if $text ~~ m/$godzilla_rx/ {
> $loc = $/.from;
> say "Godzilla: Found at $loc!";
> %match_locs{ $godzilla_rx } = $loc;
> }
> 
> But using a regex object as a hash key evidently doesn't work,
> it gives you the warning message:
> 
>#  Regex object coerced to string (please use .gist or .perl to do that)
> 
> And what's worse is it coerces to an *empty list* which means *every*
> regex is treated as the same key.
> 
> If you I follow the advice to use the *.perl, then that works, of course:
> 
> %match_locs{ $godzilla_rx.perl } = $loc;
> 
> But you wouldn't be able to use the keys of the hash as a regex
> object later, which seems sub-optimal, though not a concern for
> my present purposes.

The same thing happened with your Rutabaga object. It had a default
Str method that was called when you used it as a hash key. It didn't
really store the object in the key but just its .Str:

  %vegeout.keys.any ~~ Rutabaga;  # OUTPUT: «False»
  %vegeout.keys.all ~~ Str;   # OUTPUT: «True»
  %vegeout.keys[0] === $obj;  # OUTPUT: «False»

This is because Hash objects, by default, have Str(Any) keys, meaning
Str and coercing when required. If you want a Hash which allows any
kind of object as key, you have to declare it such:

  my $obj = Rutabaga.new;
  my %vegeout{Any};  # <-- see: 
https://docs.raku.org/language/hashmap#Non-string_keys_(object_hash)
  %vegeout{$obj} = "this works";
  %vegeout.keys.all ~~ Rutabaga;  # OUTPUT: «True»
  %vegeout.keys[0] === $obj;  # OUTPUT: «True»

This will also work with Regex objects.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: What is operand 152 and 160?

2020-03-31 Thread Tobias Boege
On Tue, 31 Mar 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> Windows 10-1909 Pro
> 
> raku -v
> This is Rakudo version 2020.01 built on MoarVM version
> 2020.01.1 implementing Perl 6.d.
> 
> Running my program I get this at a call to
> a sub in a module:
> 
>  operand type 160 does not match register type
>  152 for op decont_u in frame WinCreateKey
> 
> What is operand 152 and 160?
> 

A cursory look around the MoarVM and nqp sources leads me to believe
that they're bitmasks describing conditions of operands somewhere in
the bytecode. 152 would be uint32 and 160 an uint64, without any extra
flags set for them.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: irrational nubmer?

2020-02-26 Thread Tobias Boege
On Wed, 26 Feb 2020, ToddAndMargo via perl6-users wrote:
> > > $ p6 'say (99/70).base-repeating();'
> > > (1.4 142857)
> > > 
> > > means that 142857 also repeats (it does not), but
> > > that it is best it can figure out with the precision
> > > it has?
> > > 
> > 
> > What are you talking about? It does repeat. I suggest you take a piece
> > of paper and compute the decimal digits of 99/70 by hand until you are
> > convinced that it is 1.4 and then an endless stream of 142857 repeating.
> 
> I used gnome calculator to 20 digits:
> 665857/470832
> 1.41421356237468991063
> Sorry.  Not seeing any repeating patterns.
> 

Todd, you were asking about 99/70, so I answered you about 99/70.
I even quoted it. Now you come with 665857/470832. For that number,
you will see the repetition after about 580 decimal digits.

> Here is NAS doing it to 1 million digits (they have too
> much time on their hands):
> https://apod.nasa.gov/htmltest/gifcity/sqrt2.1mil
> No repeats.
> 
> So why does base-repeating tell me there is a repeating
> pattern when there is not?
> 

Sigh. We already settled that Rat and Num in Raku are rational numbers
and that √2 is an irrational number. So what can you definitely not apply
the base-repeating method to in Raku? -- The honest value of √2.

NASA apparently computed the first million digits of √2 and you see no
repeated digits. Good. In fact a real number is irrational if and only
if its decimal expansion has no repeating pattern. You can view this as
a reason for why they are not super easy to deal with on a computer.

But that has nothing to do with the numbers we looked at above. Those were
obviously rational numbers. They were obviously different from √2 because
that number is not rational -- and we were looking at rational numbers.
We were looking at rational numbers close to √2. What makes you think that
NASA computing digits of the number √2 has any bearing on the correctness
of `(99/70).base-repeating`? Because √2 and 99/70 are obviously not the
same number.

We are not working out the decimal expansion of √2. We are working out
decimal expansions of rational numbers close to, but different from, √2.
Even though they are close, structural properties of the expansions,
like the existence of a repeating pattern, are radically different.

> Ah ha, 99/70 does have a repeat:
> 1.4142857 142857 142857 1
> 
> Maybe 665857/470832 I just do not go out enough digits to
> see a repeat.
> 
> √2 does not repeat though, but I am thinking that
> I am stretching the poor machines abilities a bit too far
> and that is where the repeat comes from
> 
> $ p6 'say sqrt(2).Rat.base-repeating();'
> >> (1.4 
> >> 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)
> 
> So, with the technology on hand, the approximation of √2
> does have a repeating pattern of
> 
> 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076
> 
> (And in engineering terms, is meaningless)
> 

Yes, √2 has no repeating decimal pattern and the repetition returned to
you is the one of the rational approximation to √2 that Raku computed
when you asked for `sqrt(2).Rat`.

(Somehow it seems like you understood halfway through writing your
response but decided to keep the first half anyway. I don't know why.)

> > > And what are the unboxing rules for (665857/470832)?
> > > 
> > 
> > No idea what you mean.
> 
> When is <665857/470832> unboxed to a Real number to
> operate on it?  Or is it never unboxed?
> 

I'm no boxing expert, but I know that Rat has high-level arithmetic
defined for it and there is no native rational type to unbox to.
That would have to go through Num, I suppose. So I see neither a need
nor a target for unboxing a Rat. But I still have no idea what kind
of operations you have in mind. That said, Rat is not a NativeCall-
related type.

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: irrational nubmer?

2020-02-26 Thread Tobias Boege
On Wed, 26 Feb 2020, Todd Chester via perl6-users wrote:
> Hi Tobias,
> 
> I am confused as to as to what you mean by numerator and
> denominator.
> 

Rational numbers can always be written as the ratio of two integers:
a/b with b non-zero. One calls a the numerator and b the denominator.

In Raku the types Int, Rat, FatRat and Num are all rational numbers,
as they all can be written as the ratio of two integers (up to Infs
and NaNs).

> When I say:
> $ p6 'say (99/70).base-repeating();'
> (1.4 142857)
> 
> $ p6 'say (665857/470832).base-repeating();'
> (1.4142 
> 135623746899106262955788901349101165596221157440445849050192000543718353892683589900431576443402317599483467563801950589594590002378767798280490705814388146939885139497740170591633533829476331260407109117477146837937948142861997485302613246338396710503958949264281102388962517415978523125021238998198932952730485608454820403031229822951711013694906038671967920617120331668195874536989839263261630475413735684915213919189859652699901451048356951099330546776769633329935093621504060896455635980562068848336561661059571142148367145818466034594080266421993407414959051211472457267)
> 
> $ p6 'say sqrt(2).Rat.base-repeating();'
> (1.4 
> 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)
> 
> How does Raku know √2 is approximated by 99/70 or 665857/470832?
> Does not Raku just throw a binary algorithm at any number you
> feed sqrt?
> 

The floating point unit in your computer receives the 2 and returns
a floating point approximation of √2. Raku then uses the algorithm
I linked to in my last email to give you the 99/70.

> also, what exactly am I look at with (1.4 142857)?   Is
> this a way of saying that 1.4 is the rational part and
> 142857 the irrational part?
> 

No, Raku doesn't know anything about irrational numbers. As soon as
you obtain the return value of `sqrt(2)` in Raku, you got a rational
approximation to √2 and no part of the program knows that you wanted
to compute an irrational number. The irrationality is gone, it was
all in your head. You are dealing with this rational number that is
"close" to √2.

> What is also confusing is when a number does not repeat,
> what is .base-repeating() trying to tell me?  Is does not repeat?
> 
> 2/3 is 0.666.
> $ p6 'say (2/3).Rat.base-repeating();'
> (0. 6)
> 
> Does that mean that the 6 repeats?
> 

Yes.

> and
> 
> $ p6 'say (99/70).base-repeating();'
> (1.4 142857)
> 
> means that 142857 also repeats (it does not), but
> that it is best it can figure out with the precision
> it has?
> 

What are you talking about? It does repeat. I suggest you take a piece
of paper and compute the decimal digits of 99/70 by hand until you are
convinced that it is 1.4 and then an endless stream of 142857 repeating.

If afterwards you trust Raku again, try `(99/70).base(10, 1000)` to get
the first thousand decimal digits of that fraction printed.

> And it it can not find a repeat, why does it not say so?
> 

If you did the pen and paper exercise above, you know how the algorithm
goes and that it is very easy to see when you've found the repeat and
when you haven't. Above, there was a repeat that was easily found.
The documentation says that if the repeat cannot be found within a
thousand digits, the repeating part in the return value of &base-repeating
will be "???".

I've found this to be false. The source code of the method does not have
such precautions and the limit is certainly not 1000 decimals. Try for
example 1/1019 which has a group of 1018 repeating decimals. [ Maybe
the number-theoretically inclined subscribers here will figure out how
I found this example. ]

Curiously, the old design docs [1] mandate a buffer of 100_000 to look
for repeating digits. Pre-christmas versions of Rakudo apparently did
have this check but "sanity", as a comment in the Rakudo sources called
it, was removed in March 2015 [2] :-)

As it currently stands [3], Rakudo will exhaust all memory to try to
find the repeating group if it has to. (Note that all rational numbers
have this repeating group -- you know this if you did the exercise --
so the search is never in vain, but it *is* attack surface for a DoS.)

> And why am I getting zero back from
> $ p6 'say sqrt(2).Rat.base-repeating() - (665857/470832).base-repeating();'
> 0
> 

The return value of &base-repeating is a list. You are subtracting
two lists which actually gets you the difference of their lengths.
Since both lists have two elements (all lists returned by that
function do) you get zero:

  > sqrt(2).Rat.base-repeating - sqrt(1000).Rat.base-repeating
  0

> Also, what is the algebraic precedence of the operation?  In
> (665857/470832).base-repeating()
> 
> is (665857/470832) solved first or is (665857/470832) a special
> number (Rat) that is fed to .base-repeating?
> 

What happens here is that the expression `665857/470832` is a
Rat literal. You take this literal Rat object and call a method
on it. It is not conv

Re: irrational nubmer?

2020-02-20 Thread Tobias Boege
On Thu, 20 Feb 2020, ToddAndMargo via perl6-users wrote:
> > > On Fri, 21 Feb 2020 at 13:31, ToddAndMargo via perl6-users
> > > mailto:perl6-users@perl.org>> wrote:
> > > 
> > > $ perl6 -e 'say sqrt(2).base-repeating();'
> > > No such method 'base-repeating' for invocant of type 'Num'
> > > in block  at -e line 1
> > > 
> 
> On 2020-02-20 19:07, Norman Gaywood wrote:
> > 
> > perl6 -e 'say sqrt(2).Rat.base-repeating();'
> > (1.4 
> > 14213197969543147208121827411167512690355329949238578680203045685279187817258883248730964467005076)
> 
> Hi Norman,
> 
> Much better!
> 
> Question: Rat:
> https://docs.raku.org/type/Rat
> 
>   Rat objects store rational numbers as a pair
>   of a numerator and denominator. Number literals
>   with a dot but without exponent produce Rats.
> 
> What does Rat do to sqrt(2) to give it a numerator
> and a denominator?
> 

I'm not sure if you have digested what others have said, so I'll repeat it:
sqrt(2) already has a numerator and denominator. sqrt(2) takes the integer
2 and computes its square root as a floating point number using magic IEEE
powder. If you look up the IEEE 754 float representations, you'll notice
that every (non-NaN, non-Inf) float is a rational number. So sqrt(2) is
already a rational number approximating the positive real number whose
square is 2.

That said, just taking the obvious numerator and denominator from the float
might give you unnecessarily large numbers, and the Rat conversion on Num
has to support a user-supplied tolerance as well. Reading the documentation,
it seems that Raku does not require IEEE 754 to be in effect at all.

So what Rakudo does (I recommend reading the source code [1]) is a variant
of finding a continued fraction for the Num [2], except that it computes
the Rat instead and stops when it reached the requested accuracy. It starts
from scratch and iteratively approximates the Num, which has the advantage
that you can stop when you don't have to continue and that it only relies
on arithmetic on the Num working, not that it is represented according to
some standard internally.

Note also that Num.Rat supports a :fat argument to give you a FatRat back,
but you cannot actually increase the precision of your rational approximation
of √2 beyond the source you put in, which is a double precision float:

  > sqrt(2).Rat.nude # precision 1e-6, the default
  (1393 985)
  > sqrt(2).Rat(1e-8).nude   # a bit better requested, request granted
  (19601 13860)
  > sqrt(2).Rat(1e-16).nude  # still better but 1e-16 is ca. the limit
  (131836323 93222358)

  > sqrt(2).Rat(1e-20).nude  # no improvement
  (131836323 93222358)
  > sqrt(2).Rat(1e-100, :fat).nude  # fatter but not better, because
  (131836323 93222358)  # the source sqrt(2) is too lossy

Regards,
Tobias

[1] https://github.com/rakudo/rakudo/blob/cdbd60c1/src/core.c/Num.pm6#L46
[2] 
https://en.wikipedia.org/wiki/Continued_fraction#Calculating_continued_fraction_representations

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: irrational nubmer?

2020-02-20 Thread Tobias Boege
On Wed, 19 Feb 2020, Paul Procacci wrote:
>  >> Is there a test to see if a number is irrational
> There is no such thing as an irrational number in computing.
> 
> Surely there are "close approximations", but that's the best any computer
> language can currently do.
> 

It all depends on representation.  Of course there are ways to write
algebraic numbers as their minimal polynomials over the rationals.
You may not call that a "number", but you can do effective arithmetic
with such a representation, so for many purposes it's as good as a
"chunk of bits" number and it is an exact symbolic representation of
a (possibly irrational) number from which you can extract rational
approximations of any wanted precision.  And in that representation,
a number is irrational if and only if the minimal polynomial has
degree at least two, very easy to check.  (Note, however, that you
do not get all irrationals in this way. π and e are still out of
reach, for example.)

Granted, Todd would not have anticipated this answer if he calls
arbitrary length integers "magic powder" and the question "I have
computed this Int/Num/Rat in Raku, is it rational?" does indeed
not make any sense.  But there are computer languages that can do
better.  Given FatRats, such modules can be written for Raku today.

There seems to be a slogan of some sort that, if you search IRC logs
or the documentation, pops up a number of times: "Perl 6 (Raku) is not
a computer algebra system" ("RINACAS"?).  I don't know what happened
in the history of Perl 6 development, but it seems that irrationals
were sought in core at some point and it was Larry who stopped that
motion [1].

Regards,
Tobias

[1] https://github.com/Raku/problem-solving/issues/4#issuecomment-474892811

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: bytes are used in an UInt/Int?

2020-02-03 Thread Tobias Boege
On Mon, 03 Feb 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> Did Larry put a sneaky way to tell how many bytes
> a UInt/Int is using?
> 

The number of bits required to store an Int is, for positive numbers,
the same as the index of their most significant bit, which is available
via Int.msb. From the bits, you can calculate the bytes.

How much memory the implementation actually allocates is "none of your
business" I suppose. And you get to decide how you want to treat zero and
negative integers (the latter probably by taking their absolute value).
Maybe you always want to add an imaginary sign bit as well.

Also please note that UInt is not a datatype and there is no storage
associated with it. UInt is the name of a property that a pre-existing
Int object can satisfy or not, namely being greater than or equal to
zero. There are no objects of type UInt. There are only Int objects
that smartmatch UInt or variables with a UInt constraint.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Hash Constraints w/in subset's

2020-02-01 Thread Tobias Boege
On Sat, 01 Feb 2020, Paul Procacci wrote:
> Hey ladies/gents,
> 
> How would one go about defining a subset of a Hash who's key's and values
> are both constrained by something 
> 
> I've read https://docs.perl6.org/type/Hash and it does make mention of
> constraining keys and values, but not within the context of a subset.
> Before I go ripping my hair out, I want to make sure I'm doing things right.
> 
> For instance, what if I want to define a subset that uses a Hash as it's
> base class, in which I want to add the constraint that it's keys must be
> strings yet it's values are constrained to only accept Int's?
> 

You would make a subset of Hash if you are getting Hashes and you want
to give some common code that checks the validity of the Hash a name.
If you want a new type that you can actually create objects from, the
solution is subclassing, not subsetting, but works similarly to below.
(Just to make sure you're not surprised when you can't call .new on
your subset later.)

With a subset you could do:

subset PhoneBook of Hash[Int, Str];

my Int %pb{Str};
%pb   = +49_123_4567_6789;  # good
try %pb = "unknown";  # fails

dd %pb  #= Hash[Int,Str] %pb = (my Int %{Str} = :tobias(4912345676789))
say %pb ~~ PhoneBook  #= True

to the same effect.

Note that if you subset PhoneBook of Hash[Int, Str], then your hashes
really must be typed. An ordinary Hash that just happens to always map
strings to integers is not sufficient and will fail the type check.
You could make a looser subset of Hash with a where clause that checks
compatibility of all keys with Str and of all values with Int as well,
but that would be more expensive.

To answer your question: Hash does the Associative role which is
parameterized by the key and value type, but *in reverse order*.
Hash[Int, Str] is the type that maps Int <-- Str, just like in the
neat `my Int %pb{Str}` declaration.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: stolen uint's

2020-01-29 Thread Tobias Boege
On Tue, 28 Jan 2020, ToddAndMargo via perl6-users wrote:
> This all came up when I tried to match
> 
>   RegSetValueExW(
>   _In_ HKEY hKey,
>   _In_opt_ LPCWSTR lpValueName,
>   _Reserved_ DWORD Reserved,
>   _In_ DWORD dwType,
>   _In_reads_bytes_opt_(cbData) CONST BYTE * lpData,
>   _In_ DWORD cbData
> 
> where CbData can either be a UTF little endian C string,
> terminated by a nul or a four byte little endian
> unsigned integer (no two's complement allowed) depending
> on the value of lpValueName (REG_SZ, REG_DWORD, etc.)
> 
> I wound up doing this:
> 
> subset StrOrDword where Str | UInt;
> sub WinRegSetValue( WinRegHives $Hive, Str $SubKey, Str $KeyName, ValueNames
> $ValueType, StrOrDword $ValueData, Bool $Debug = False )
> returns DWORD is export( :WinRegSetValue ) {

Are you really 100% sure that you interpreted this API correctly? I see how
a DWORD cbData can be a four-byte unsigned integer: it gives the length of
lpData in bytes, as documented [1].

But then a DWORD is 4 bytes long. Reusing these 4 bytes for an alternative
interface where you may pass a UTF-whatever string that is at most 4 bytes
encoded, including the NUL terminator... seems too insane. And there is no
mention of that in the documentation page [1]. I do not think that cbData
is ever used for anything but to indicate the length of the buffer lpData.
It is lpData which can have a multitude of types (and serialization formats),
the intended one to be taken from the dwType argument (not lpValueName).

My advice is still the same I gave in my very first reply to this thread:
make your function a multi and write a candidate for each dwType. You have
to write different code for serializing an integer vs. a string to pass as
lpData anyway and the compiler can detect native types in multi dispatch
for you:

  # REG_DWORD
  multi WinRegSetValue(…, uint32 $data) {
  use experimental :pack;
  RegSetValueExW(…, REG_DWORD, pack("L", $data), 4)
  }

  # REG_SZ
  multi WinRegSetValue(…, Str $data) {
  my $blob = "$data\0".encode
  RegSetValueExW(…, REG_SZ, $blob, $blob.bytes)
  }

  # REG_BINARY
  multi WinRegSetValue(…, blob8 $data) {
  RegSetValueExW(…, REG_BINARY, $data, $data.bytes)
  }

Regards,
Tobias

[1] 
https://docs.microsoft.com/en-us/windows/win32/api/winreg/nf-winreg-regsetvalueexw

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Range on Subsets

2020-01-28 Thread Tobias Boege
On Tue, 28 Jan 2020, Simon Proctor wrote:
> So some recent conversations covered the Range method on numeric types like
> Int
> 
> So Int.Range gives the range of valid values -Inf^..^Inf which is neat.
> 
> Then I thought I'd try UInt.Range and got 0..^Inf
> 
> Ah Ha! Thinks I. I have a plan. What if I try this?
> 
> my subset OneToTen of Int where { not .defined or 1 <= $_ <= 10 };
> say OneToTen.Range;
> 
> And it gives ...
> 
> -Inf^..^Inf
> 
> And now I'm a bit confused. The Docs say the UInt is just a subset
> https://docs.raku.org/type/UInt
> 
> So how does it have it's own Range?
> 

It's simply special-cased in the Int.Range implementation:

  
https://github.com/rakudo/rakudo/blob/d8e859d000fa658766266a45f99e58661dec7b0e/src/core.c/Int.pm6#L239

As a consequence of the implementation checking the .^name, you can
make Rakudo appear very confused:

  subset UInt of Int where 1000 .. 1002;
  say UInt.Range;  #= 0..^Inf

Arguably, the subset declarator could probably make the case where the
matcher is an explicit Range as above DWIM, but as soon as arbitrary code
is involved, as in your OneToTen, there is no hope to make a sensible
Range method.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: stolen uint's

2020-01-25 Thread Tobias Boege
On Sat, 25 Jan 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> Anyone have a workaround to my stolen uint's?
> 
> > constant DWORD := uint32;
> (uint32)
> 
> > subset StrOrDword where Str | DWORD;
> (StrOrDword)
> 
> > sub x( StrOrDword $item ) {
> *   say "$item is a " ~ $item.^name;
> *   }
> &x
> 
> > x( "abc" );
> abc is a Str
> 
> > x( 3 );
> Constraint type check failed in binding to parameter '$item'; expected
> StrOrDword but got Int (3)
>   in sub x at  line 1
>   in block  at  line 1
> 
> > x( 3.UInt );
> Constraint type check failed in binding to parameter '$item'; expected
> StrOrDword but got Int (3)
>   in sub x at  line 1
>   in block  at  line 1
> 

Raku allows you to use native datatypes and to constrain variables to
refuse anything but some kind of native data. But an uint32 is just
32 bits, no class and no methods attached.

If nevertheless you call methods on native values, they will be boxed
into objects that actually support methods to be called on themselves.
Native integers, signed or not, are boxed into Int.

With that in mind, re-read the documentation section about native
dispatch [1]. Your sub x has no candidate that statically accepts
a native integer. Since you use a subset type, the typecheck is
deferred until runtime, but StrOrDword.ACCEPTS has no native integer
candidate either, and at that point you lost already, as

  x(my uint32 $ = 3)

would result in the 3 being auto-boxed to be able to check it against
`Str | uint32` and because of the boxing, its type is now Int and the
check fails. Consider:

  sub x(uint32 $item) { say "$item is a " ~ $item.^name }

  x(3);# works, `only` subs auto-unbox the Int literal
  x(my uint32 $ = 3);  # works, a native integer is provided

In both cases, "3 is a Int" will be printed, because the class name
is obtained by calling a (meta-)method on $x, which triggers boxing
to Int. There is no room for a class name in a 32 bits native integer.

Now, if you change the signature to something subsetty/dynamic like

  sub x($item where uint32)

both calls fail to dispatch, as explained above. On the other hand,
this works because there is an explicit native integer candidate for
the dynamic typecheck, so you don't get boxed:

  sub x($item where -> uint32 { True })

By the way, this has nothing to do with unsigned or signed integers,
your signs are not stolen, your values are boxed. The uint32 type is
simply not suitable to be typechecked against, as this quintessentially
paradoxical line of code tells you:

  say (my uint32 $ = 3) ~~ uint32;  # False

Native data is second-class data in a language where everything
is an object.

If you want a workaround, eschew the subset and provide two candidates
for your sub x: one for Str and one for uint32. How do you expect to
handle something that may either be a Raku string object or a native
integer in a single candidate anyway? Or drop the native integer
altogether and use Int until you really need the native thing.

Regards,
Tobias

[1] https://docs.raku.org/language/numerics#Native_dispatch

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: troubles with with base(2)

2020-01-20 Thread Tobias Boege
On Mon, 20 Jan 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> Now what am I doing wrong?
> 
> my $v = 0b00101101 ^ 0b1001; say $v.base(2);
> one(101101, 1001)
> 
> It should be
> 100100
> 

Please examine the output you get. Does the spurious "one" in there not
make you raise an eyebrow and head over to the documentation?

^ is a junction constructor, specifically it creates a one() junction.
If you want bitwise XOR use the... bitwise XOR operator +^.

In general, the "bare" operators &, |, ^ in Raku are used for declarative
purposes: in normal Raku they are junction constructors and in regexes
they denote longest-token matching.

Many other languages use these operators for (signed or unsigned) bitwise
operations, but in Raku these "numeric" bitwise operations are put under
the "+" umbrella to show that they are numeric: +&, +| and +^. Corresponding
operators also exist for buffers as ~&, ~| and ~^, for booleans as ?&, ?|
and ?^ and for sets as (&), (|), (^).

This is a truly beautiful and thoughtful thing about Raku.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: my first two doc issues

2020-01-19 Thread Tobias Boege
On Sun, 19 Jan 2020, ToddAndMargo via perl6-users wrote:
> RFE: Please add the following examples to routine +^
> https://github.com/Raku/doc/issues/3177
> 
> Now I wait and see what kind of reception I get.  It
> will be nice to contribute to the docs, rather than
> just always griping about them
> 

Oh well, I just responded with what my gut told me when this arrived
in my inbox. Didn't know that I would be part of a public experiment.

Anyway, godspeed!

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Ping JJ: string literals

2020-01-19 Thread Tobias Boege
On Sat, 18 Jan 2020, ToddAndMargo via perl6-users wrote:
> 
> > Would you be so kind to post this as an issue in the documentation, so
> > we can pick up on it?
> > 
> > Thanks!
> > 
> > JJ
> 
> Would you mind posting back the link to it, so I can
> get on the following list?

https://github.com/Raku/doc/issues/3169

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: problems with xor

2020-01-18 Thread Tobias Boege
On Fri, 17 Jan 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
> https://docs.raku.org/routine/+$CIRCUMFLEX_ACCENT
> 
> (Operators) infix +^§
> 
> multi sub infix:<+^>($a, $b --> Int:D)
> 
> Integer bitwise XOR operator: Coerces both arguments to Int and does a
> bitwise XOR (exclusive OR) operation.
> 
> 
> $ p6 'my uint8 $x=0b0101_0111; my uint8 $y = 0b_; my uint8 $z =
> +^($x, $y ); say "0", $x.base(2); say "", $y.base(2); say $z.base(2);'
> 
> 01010111
> 
> 1101
> 
> 
> XOR
> A  B   A xor B
> 0  0  0
> 1  0  1
> 0  1  1
> 1  1  0
> 
> That s not what I am seeing above.
> 
> What am I doing wrong this time?
> 
> And who set the high bit making $z negative?
> 

As was already mentioned, if you want to use the &infix:<+^> operator,
you have to either call it by its full name as a sub:

  &infix:<+^>($x, $y)

or you have to use it according to its syntax category, as an infix:

  $x +^ $y

When you write +^($x,$y), its cousin &prefix:<+^> is called instead,
because now you use +^ as a prefix operator. That one performs bitwise
negation on its argument coerced to Int, and since you pass it a list
of length two, you actually evaluate +^2. And that's how you get the
high bit and a value of -3.

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: Ping JJ: string literals

2020-01-18 Thread Tobias Boege
On Sat, 18 Jan 2020, JJ Merelo wrote:
> The example works perfectly, and it does because it's a string literal
> which is already 0 terminated. Let's use this code instead of the one that
> I used in my other mail about this (which you probably didn't read anyway):
> 
> 8< 8< 8<
> 
> What does this mean? It means that NativeCall does the right call
> (badum-t) and converts a Raku string literal into a C string literal,
> inserting the null termination even if we didn't. I actually don't care if
> it was the NativeCall API or the encode method. It just works. It gets
> allocated the right amount of memory, it gets passed correctly into the C
> realm. Just works. Since @array.elems has 3 elements, well, it might be
> rather the C part the one that does that. But I really don't care, and it
> does not really matter, and thus the example is correct, no need to add
> anything else to the documentation. Except maybe "get your C right"
> 

What you say seems to be correct: if you have a string literal in your
Raku code, this works for me, too. (Sometimes, see below.)

BUT the terminating NUL character is not inserted by NativeCall and it
isn't inserted by &encode. If you run this program which uses a much
longer string that is not a literal on the face of it:

use NativeCall;
sub c-printf(CArray[uint8]) is native is symbol { * };

my $string = "X" x 1994;
my $array = CArray[uint8].new($string.encode.list);
c-printf $array;

through valgrind, it will warn you about a one-character invalid read,
that is a byte accessed by printf() which is at offset 0 after a properly
allocated block of size 1994:

$ perl6-valgrind-m -MNativeCall -e 'sub c-printf(CArray[uint8]) is native 
is symbol { * }; my $string = "X" x 1994; my $array = 
CArray[uint8].new($string.encode.list); c-printf $array' >/dev/null

==325957== Invalid read of size 1
==325957==at 0x48401FC: strchrnul (vg_replace_strmem.c:1395)
==325957==by 0x50CD334: __vfprintf_internal (in /usr/lib/libc-2.30.so)
==325957==by 0x50BA26E: printf (in /usr/lib/libc-2.30.so)
==325957==by 0x4B58048: ??? (in $rakudo/install/lib/libmoar.so)
==325957==by 0x1FFEFFFB5F: ???
==325957==by 0x4B57F81: dc_callvm_call_x64 (in 
$rakudo/install/lib/libmoar.so)
==325957==by 0x50BA1BF: ??? (in /usr/lib/libc-2.30.so)
==325957==by 0xA275E3F: ???
==325957==by 0x990153F: ???
==325957==by 0xA275E3F: ???
==325957==by 0x1FFEFFFB7F: ???
==325957==by 0x4B578D1: dcCallVoid (in $rakudo/install/lib/libmoar.so)
==325957==  Address 0xb5ebf1a is 0 bytes after a block of size 1,994 alloc'd
==325957==at 0x483AD7B: realloc (vg_replace_malloc.c:836)
==325957==by 0x4A9DFDF: expand.isra.3 (in 
$rakudo/install/lib/libmoar.so)
==325957==by 0x4A9E6F4: bind_pos (in $rakudo/install/lib/libmoar.so)
==325957==by 0x4A2C9AF: MVM_interp_run (in 
$rakudo/install/lib/libmoar.so)
==325957==by 0x4B2CC24: MVM_vm_run_file (in 
$rakudo/install/lib/libmoar.so)
==325957==by 0x109500: main (in $rakudo/install/bin/perl6-m)

This is the NUL byte that happens to be there and terminate our string
correctly, but nothing in the moarvm process has allocated it, because
knowing what is allocated and what isn't is valgrind's job. And if it's
not allocated, then either moarvm routinely writes NULs to memory it
doesn't own or it simply does not automatically insert a NUL after the
storage of every CArray[uint8]. And why would it? I for one would not
expect CArray[uint8] to have special precautions built in for when it's
used to hold a C string.

Why does it work with a string literal in the Raku code? I don't know,
but consider the following variations of the code, with my oldish Rakudo:

  - with $string = "X" x 1994: valgrind sad
  - with $string = "X" x 4:valgrind sad
  - with $string = "X" x 3:valgrind happy
  - with $string = "X" x 2:valgrind happy
  - with $string a short literal
like "FOO":valgrind happy
  - with $string a literal of
sufficient length like "FOOO": valgrind sad
  - with $string = "FOO" x 2:  valgrind happy
  - with $string = "FOO" x 200:valgrind sad

My guess is that if it's sufficiently small and easy, then it is computed
at compile-time and stored somewhere in the bytecode, for which some
serialization routine ensures a trailing NUL byte inside an allocated
region of memory for the process.

That is only a barely informed guesses, but independently of what causes
it to work on short string literals, I strongly believe that this is an
implementation detail and hence I would call the example in the docs
misleading. Appending the ", 0" when constructing the CArray[uint8]
seems like a really neat fix.

Anyway, the most important message of this mail should actually be:
_Normally_, the way you pass a Raku string to a native function is by
using the `is encoded` trait. It's such a nice

Re: Cardinals

2020-01-02 Thread Tobias Boege
On Thu, 02 Jan 2020, ToddAndMargo via perl6-users wrote:
> Hi All,
> 
>  “He who asks is a fool for five minutes, but he who
>  does not ask remains a fool forever.”
>  ― Mark Twain
> 
> This would be my five minutes.  I will live.
> 
> How do I do a 32 bit unsigned integer (cardinal)?  I
> have a situation where I need to be able to have the
> first bit be a one and not have Raku think it is
> a negative number.
> 

It's called uint32: 
https://docs.perl6.org/language/nativetypes#index-entry-uint32

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: play with raku and autobiographical numbers

2019-12-31 Thread Tobias Boege
On Tue, 31 Dec 2019, Marc Chantreux wrote:
> hello,
> 
> 2020 describes itself as it is composed by
> 
> 2 0
> 0 1
> 2 2
> 0 3
> 
> perfect golf excuse! I have :
> 
> sub is_autobiographic (\x) {
> my \s = x.Str;
> my @r = s.comb;
> my %appearance_of;
> %appearance_of{$_}++ for @r;
> x ~~ join '', (%appearance_of{$_}//0 for 0..^@r);
> }
> 
> (^∞
> ).race( :1batch,:10degree
> ).grep( &is_autobiographic
> ).head(10).map(*.say)
> 
> anyone with something simpler?
> 

Here is my entry, having a Bag count the occurences of letters,
instead of the loop over @r you used. It also doesn't assemble
a string out of the bag to compare the input to, but consults
the bag directly for each digit:

  sub is-autobiographic (\x) {
  my \bag = x.comb.Bag;
  [and] x.comb.kv.map: {
  bag{~$^i} == $^v
  }
  }

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: square root question

2019-12-15 Thread Tobias Boege
On Sat, 14 Dec 2019, ToddAndMargo wrote:
> What am I doing wrong here?
> 
> > multi prefix:<√> (Cool:D $x) { $x.sqrt }
> &prefix:<√>
> 
> > say √2
> ===SORRY!===
> Argument to "say" seems to be malformed
> --> say⏏ √2
> Bogus postfix

If this is inside the REPL, it's not your fault. It's a known issue:
https://github.com/rakudo/rakudo/issues/2245

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: about 'use v6.d'

2019-12-13 Thread Tobias Boege
On Fri, 13 Dec 2019, Brad Gilbert wrote:
> There should probably be a way to require a minimum version of the compiler.
> 
> use rakudo v2019.07;
> 

As I understand it, this would do something quite different from `use v6`,
which is probably your point(?).  A single Raku compiler would strive to
support `use v6.x` for many x, which Rakudo does by keeping around a setting
for each language version.  The `v6` pragmas can be changed per compunit
under the same compiler, so different parts of the same process can run
under different Raku versions.  (You probably know that more accurately
than me, so please correct me if I'm wrong.)

What Rakudo doesn't do is include a setting for every release, so the effect
of a `use rakudo v2019.07` would be closer to a *dependency* rather than a
pragma: it doesn't change the way your code is executed, it will abort it
altogether if your compiler is not recent enough or not Rakudo.  My under-
standing is that META6.json would be the natural place to declare dependencies,
although I couldn't tell how to properly declare a compiler dependency there,
as the compiler is not a module (right?).

Otherwise such a rakudo pragma is probably as easy to implement as

  --8<-- rakudo.pm6 
  sub EXPORT (Version:D $ver) {
  given $*PERL.compiler {
  die "This compiler is not Rakudo"unless .name eq 'rakudo';
  die "Rakudo version ≥ $ver required" unless .version ≥ $ver;
  }
  %( )
  }
  --8<--

Regards,
Tobias

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk


Re: My keeper on "contains"

2019-12-09 Thread Tobias Boege
On Mon, 09 Dec 2019, perl6-users-h...@perl.org wrote:
> Date: Sun, 8 Dec 2019 17:45:22 -0800
> From: ToddAndMargo via perl6-users 
> To: perl6-users 
> Subject: My keeper on "contains"
> 
> 8< ...
>
> Case insensitive contains:
> $ p6 'if "2018 Jul 7".fc.contains( "jul".fc ) {say "Yes";}'
> Yes
> 
> $ p6 'if "2018 xJul 7".fc.contains( "jul".fc ) {say "Yes";}'
> Yes
> 
> p6 'if "2018 xul 7".fc.contains( "jul".fc ) {say "Yes";}'
> 
> 
> $ p6 'my $x="strong>2018.2.0; Coming Soon"; say so 
> $x.fc.contains("strong" & not "coming soon");'
> False
> 

Careful about the last example, it is misleading. The `not` in
`"strong" & not "coming soon"` is not a junction constructor but
is evaluated eagerly, resulting in this junction:

  $ rk 'dd "strong" & not "coming soon"'
  all("strong", Bool::False)

because not("coming soon") is False at the moment where the &
operator assembles the all-junction. The result of passing this
to .contains will always be False, e.g.

  $ rk 'say so "strong".contains("strong" & not "weak")'
  False

What you meant was

  $ rk 'say so "strong".contains("strong" & none "weak")'
  True

which sadly doesn't sound as natural in English.

Regards,
Tobias

PS: Sorry for not replying in-thread. I just registered and didn't have
a proper copy of the mail at hand. (When I read about the "get" command
of the mailing list manager, I got my hopes up too high apparently as I
just received the mail canned in a digest, not suitable for replying.)

-- 
"There's an old saying: Don't change anything... ever!" -- Mr. Monk