Re: Raku -npe command line usage

2020-05-08 Thread Fernando Santagata
On Fri, May 8, 2020 at 6:10 PM Fernando Santagata 
wrote:

> raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> reduce({$^a ~ "\n" ~
> $^b}) ==> say()' sample.log
>

and the reduce call can be written more compactly: reduce({"$^a\n$^b"})

-- 
Fernando Santagata


Re: Raku -npe command line usage

2020-05-08 Thread William Michels via perl6-users
Maybe?

perl6 -e 'lines() ==> grep /^WARN/ ==> sort() ==> join("\n") ==> say();'

HTH, Bill.


On Fri, May 8, 2020 at 9:10 AM Fernando Santagata
 wrote:
>
> raku -e'.say for lines() ==> grep(/^WARN/) ==> sort' sample.log
>
> is not very satisfying because for the "for" which breaks the flow.
> OTOH this
>
> raku -e'lines().grep(/^WARN/).sort».say' sample.log
>
> doesn't use the feed operator and this
>
> raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> say()' sample.log
>
> outputs a list on one line, not each line on its own. This one works, but it 
> feels awkward:
>
> raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> reduce({$^a ~ "\n" ~ $^b}) 
> ==> say()' sample.log
>
> On Fri, May 8, 2020 at 5:49 PM yary  wrote:
>>
>> All good ideas so far, in the "more than one way to do it" spirit, can use 
>> "state" instead of "my", since state only initializes 1st time it's hit.
>>
>> raku -ne 'state @i;@i.push($_) if .starts-with(q[WARN]); END .say for 
>> @i.sort' sample.log
>>
>> Or adapting Brad's answer with the feed operator for fun
>>
>> raku -e 'for lines() ==> grep /^WARN/ ==> sort() {.say}' sample.log
>>
>> Now, I didn't want to use 'map' in there, because of a habit of only using 
>> 'map' when I want the return values. When looping for side-effects only, 
>> like saying each value in a list, I want to use 'for'. UnFORtunately though 
>> I cannot find anything as clean looking as
>>
>> raku -e 'lines() ==> grep /^WARN/ ==> sort() ==> map *.say' sample.log
>>
>> reading entirely L-to-R which does NOT use map... ideas?
>>
>> -y
>>
>>
>> On Fri, May 8, 2020 at 10:10 AM William Michels via perl6-users 
>>  wrote:
>> >
>> > On Fri, May 8, 2020 at 5:16 AM WFB  wrote:
>> > >
>> > > Hi,
>> > >
>> > > I am trying to write an one-liner to go through all lines in a logfile 
>> > > and look for an certain key word, store the line and sort them before 
>> > > printing them out.
>> > >
>> > > My approach was:
>> > > raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END { 
>> > > @i.sort.say }"
>> > > That does not work because @i does not exist in the if clause. I tried 
>> > > our @i as well with no luck.
>> > >
>> > > How can I store data that can be accessed in the END phaser? Or is there 
>> > > another way to archive it? TIMTOWTDI^^
>> > >
>> > > One hint I found was the variable $ and @ respectively. But those 
>> > > variables are created for each line new...
>> > >
>> > >
>> > > I did not found a help or examples for -npe except raku -h. Is there 
>> > > more helpful stuff somewhere in doc.raku.org? If so I could'nt find it.
>> > >
>> > > Thanks,
>> > > Wolfgang
>> >
>> > Hi Wolfgang,
>> >
>> > This is a first attempt at doing what you want: I'm sure it can be
>> > shortened. Since one of your requirements is doing a sort on filtered
>> > values stored in an array, I abandoned use of the "-ne" one-liner
>> > flag, using "-e"  and "for lines()" instead. I also used grep instead
>> > of smart-matching:
>> >
>> > perl6 -e 'my @i; for lines() {if .grep(/^WARN/) -> ($s)
>> > {@i.push($s)};}; .say for @i.sort;'
>> >
>> > Note: the "-> ($s)" section where I store grepped matches comes from a
>> > Jonathan Worthington answer found here (thanks Jonathan!):
>> >
>> > stackoverflow.com/questions/58982745/raku-one-line-expression-to-capture-group-from-string
>> >
>> > I certainly would be interested to learn if there's a phaser solution
>> > to this problem (and I also have a sneaking suspicion that Supply
>> > might be useful  here... ).
>> >
>> > HTH, Bill.
>
>
>
> --
> Fernando Santagata


Re: Raku -npe command line usage

2020-05-08 Thread yary
Ooops forgot the sort... let's golf with the hyper-operator again...

raku -ne'push my @i: $_ if .starts-with: q[WARN]; END @i.sort>>.say'
sample.log

-y


On Fri, May 8, 2020 at 1:10 PM yary  wrote:

> ooh neat! I didn't know. Indeed this works. Thanks Sean!
>
> raku -ne'push my @i: $_ if .starts-with: q[WARN]; END .say for @i'
> sample.log
>
> -y
>
>
> On Fri, May 8, 2020 at 1:04 PM Sean McAfee  wrote:
>
>> 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: Raku -npe command line usage

2020-05-08 Thread yary
ooh neat! I didn't know. Indeed this works. Thanks Sean!

raku -ne'push my @i: $_ if .starts-with: q[WARN]; END .say for @i'
sample.log

-y


On Fri, May 8, 2020 at 1:04 PM Sean McAfee  wrote:

> 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: 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: Raku -npe command line usage

2020-05-08 Thread yary
I like this formulation Fernando posted (removed a set of parens not needed
with method calls)

raku -e'lines.grep(/^WARN/).sort».say' sample.log

It is clean, all left-to-right, and doesn't use "map" for its side-effects
only.
Putting the feed operator back in where it would work–have to keep the
hyper-operator–

raku -e'(lines() ==> grep(/^WARN/) ==> sort)».say' sample.log

-y


On Fri, May 8, 2020 at 12:10 PM Fernando Santagata <
nando.santag...@gmail.com> wrote:

> raku -e'.say for lines() ==> grep(/^WARN/) ==> sort' sample.log
>
> is not very satisfying because for the "for" which breaks the flow.
> OTOH this
>
> raku -e'lines().grep(/^WARN/).sort».say' sample.log
>
> doesn't use the feed operator and this
>
> raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> say()' sample.log
>
> outputs a list on one line, not each line on its own. This one works, but
> it feels awkward:
>
> raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> reduce({$^a ~ "\n" ~
> $^b}) ==> say()' sample.log
>
> On Fri, May 8, 2020 at 5:49 PM yary  wrote:
>
>> All good ideas so far, in the "more than one way to do it" spirit, can
>> use "state" instead of "my", since state only initializes 1st time it's hit.
>>
>> raku -ne 'state @i;@i.push($_) if .starts-with(q[WARN]); END .say
>> for @i.sort' sample.log
>>
>> Or adapting Brad's answer with the feed operator for fun
>>
>> raku -e 'for lines() ==> grep /^WARN/ ==> sort() {.say}' sample.log
>>
>> Now, I didn't want to use 'map' in there, because of a habit of only
>> using 'map' when I want the return values. When looping for side-effects
>> only, like saying each value in a list, I want to use 'for'. UnFORtunately
>> though I cannot find anything as clean looking as
>>
>> raku -e 'lines() ==> grep /^WARN/ ==> sort() ==> map *.say' sample.log
>>
>> reading entirely L-to-R which does NOT use map... ideas?
>>
>> -y
>>
>>
>> On Fri, May 8, 2020 at 10:10 AM William Michels via perl6-users <
>> perl6-users@perl.org> wrote:
>> >
>> > On Fri, May 8, 2020 at 5:16 AM WFB  wrote:
>> > >
>> > > Hi,
>> > >
>> > > I am trying to write an one-liner to go through all lines in a
>> logfile and look for an certain key word, store the line and sort them
>> before printing them out.
>> > >
>> > > My approach was:
>> > > raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END {
>> @i.sort.say }"
>> > > That does not work because @i does not exist in the if clause. I
>> tried our @i as well with no luck.
>> > >
>> > > How can I store data that can be accessed in the END phaser? Or is
>> there another way to archive it? TIMTOWTDI^^
>> > >
>> > > One hint I found was the variable $ and @ respectively. But those
>> variables are created for each line new...
>> > >
>> > >
>> > > I did not found a help or examples for -npe except raku -h. Is there
>> more helpful stuff somewhere in doc.raku.org? If so I could'nt find it.
>> > >
>> > > Thanks,
>> > > Wolfgang
>> >
>> > Hi Wolfgang,
>> >
>> > This is a first attempt at doing what you want: I'm sure it can be
>> > shortened. Since one of your requirements is doing a sort on filtered
>> > values stored in an array, I abandoned use of the "-ne" one-liner
>> > flag, using "-e"  and "for lines()" instead. I also used grep instead
>> > of smart-matching:
>> >
>> > perl6 -e 'my @i; for lines() {if .grep(/^WARN/) -> ($s)
>> > {@i.push($s)};}; .say for @i.sort;'
>> >
>> > Note: the "-> ($s)" section where I store grepped matches comes from a
>> > Jonathan Worthington answer found here (thanks Jonathan!):
>> >
>> >
>> stackoverflow.com/questions/58982745/raku-one-line-expression-to-capture-group-from-string
>> >
>> > I certainly would be interested to learn if there's a phaser solution
>> > to this problem (and I also have a sneaking suspicion that Supply
>> > might be useful  here... ).
>> >
>> > HTH, Bill.
>>
>
>
> --
> Fernando Santagata
>


Re: NativeCall questions

2020-05-08 Thread David Santiago
Thanks for the information!

Have a great weekend!

Best regards,
David Santiago

Tobias Boege  escreveu no dia sexta, 8/05/2020 à(s) 15:52:
>
> 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: Raku -npe command line usage

2020-05-08 Thread Fernando Santagata
raku -e'.say for lines() ==> grep(/^WARN/) ==> sort' sample.log

is not very satisfying because for the "for" which breaks the flow.
OTOH this

raku -e'lines().grep(/^WARN/).sort».say' sample.log

doesn't use the feed operator and this

raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> say()' sample.log

outputs a list on one line, not each line on its own. This one works, but
it feels awkward:

raku -e'lines() ==> grep(/^WARN/) ==> sort() ==> reduce({$^a ~ "\n" ~ $^b})
==> say()' sample.log

On Fri, May 8, 2020 at 5:49 PM yary  wrote:

> All good ideas so far, in the "more than one way to do it" spirit, can use
> "state" instead of "my", since state only initializes 1st time it's hit.
>
> raku -ne 'state @i;@i.push($_) if .starts-with(q[WARN]); END .say for
> @i.sort' sample.log
>
> Or adapting Brad's answer with the feed operator for fun
>
> raku -e 'for lines() ==> grep /^WARN/ ==> sort() {.say}' sample.log
>
> Now, I didn't want to use 'map' in there, because of a habit of only using
> 'map' when I want the return values. When looping for side-effects only,
> like saying each value in a list, I want to use 'for'. UnFORtunately though
> I cannot find anything as clean looking as
>
> raku -e 'lines() ==> grep /^WARN/ ==> sort() ==> map *.say' sample.log
>
> reading entirely L-to-R which does NOT use map... ideas?
>
> -y
>
>
> On Fri, May 8, 2020 at 10:10 AM William Michels via perl6-users <
> perl6-users@perl.org> wrote:
> >
> > On Fri, May 8, 2020 at 5:16 AM WFB  wrote:
> > >
> > > Hi,
> > >
> > > I am trying to write an one-liner to go through all lines in a logfile
> and look for an certain key word, store the line and sort them before
> printing them out.
> > >
> > > My approach was:
> > > raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END {
> @i.sort.say }"
> > > That does not work because @i does not exist in the if clause. I tried
> our @i as well with no luck.
> > >
> > > How can I store data that can be accessed in the END phaser? Or is
> there another way to archive it? TIMTOWTDI^^
> > >
> > > One hint I found was the variable $ and @ respectively. But those
> variables are created for each line new...
> > >
> > >
> > > I did not found a help or examples for -npe except raku -h. Is there
> more helpful stuff somewhere in doc.raku.org? If so I could'nt find it.
> > >
> > > Thanks,
> > > Wolfgang
> >
> > Hi Wolfgang,
> >
> > This is a first attempt at doing what you want: I'm sure it can be
> > shortened. Since one of your requirements is doing a sort on filtered
> > values stored in an array, I abandoned use of the "-ne" one-liner
> > flag, using "-e"  and "for lines()" instead. I also used grep instead
> > of smart-matching:
> >
> > perl6 -e 'my @i; for lines() {if .grep(/^WARN/) -> ($s)
> > {@i.push($s)};}; .say for @i.sort;'
> >
> > Note: the "-> ($s)" section where I store grepped matches comes from a
> > Jonathan Worthington answer found here (thanks Jonathan!):
> >
> >
> stackoverflow.com/questions/58982745/raku-one-line-expression-to-capture-group-from-string
> >
> > I certainly would be interested to learn if there's a phaser solution
> > to this problem (and I also have a sneaking suspicion that Supply
> > might be useful  here... ).
> >
> > HTH, Bill.
>


-- 
Fernando Santagata


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: NativeCall questions

2020-05-08 Thread David Santiago
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
-110
-109
-99
74
-109
-99
74
-105
-93
74

Is it possible to not "sign" them?

Regards,
David Santiago

Curt Tilmes  escreveu no dia sexta, 8/05/2020 à(s) 12:56:
>
> On Fri, May 8, 2020 at 8:49 AM David Santiago  wrote:
>
> > EncodedData* ed = malloc(sizeof(EncodedData));
> > ed->data = encbuffer;
> > ed->crc32 = crc32;
> > return ed;
>
> You're returning a pointer to encbuffer -- make sure the storage for
> that is kept around
> somewhere.  If it is passed in from Raku, you'll be fine as long as
> you hold on to the
> object on that side.  Otherwise you might need to allocate/copy it to make 
> sure.
>
> > class EncodedData is repr('CStruct') {
> > has CArray[uint8] $.data;
> > has uint32 $.crc32;
> > }
>
> That's fine, but CArray[uint8] is just a pointer -- it doesn't know
> how long the array
> it is pointing to is.  It either needs a sentinel at the end (like the
> Nul at the end of a
> C string), or a separate field with a size to figure that out.
>
> > Don't know how many elements a C array returned from a library
>
> yep
>
> Curt


Re: Raku -npe command line usage

2020-05-08 Thread William Michels via perl6-users
On Fri, May 8, 2020 at 5:16 AM WFB  wrote:
>
> Hi,
>
> I am trying to write an one-liner to go through all lines in a logfile and 
> look for an certain key word, store the line and sort them before printing 
> them out.
>
> My approach was:
> raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END { @i.sort.say }"
> That does not work because @i does not exist in the if clause. I tried our @i 
> as well with no luck.
>
> How can I store data that can be accessed in the END phaser? Or is there 
> another way to archive it? TIMTOWTDI^^
>
> One hint I found was the variable $ and @ respectively. But those variables 
> are created for each line new...
>
>
> I did not found a help or examples for -npe except raku -h. Is there more 
> helpful stuff somewhere in doc.raku.org? If so I could'nt find it.
>
> Thanks,
> Wolfgang

Hi Wolfgang,

This is a first attempt at doing what you want: I'm sure it can be
shortened. Since one of your requirements is doing a sort on filtered
values stored in an array, I abandoned use of the "-ne" one-liner
flag, using "-e"  and "for lines()" instead. I also used grep instead
of smart-matching:

perl6 -e 'my @i; for lines() {if .grep(/^WARN/) -> ($s)
{@i.push($s)};}; .say for @i.sort;'

Note: the "-> ($s)" section where I store grepped matches comes from a
Jonathan Worthington answer found here (thanks Jonathan!):

stackoverflow.com/questions/58982745/raku-one-line-expression-to-capture-group-from-string

I certainly would be interested to learn if there's a phaser solution
to this problem (and I also have a sneaking suspicion that Supply
might be useful  here... ).

HTH, Bill.


Re: Raku -npe command line usage

2020-05-08 Thread Brad Gilbert
The 「@i」 is defined within the 「BEGIN」 block, so it is scoped to the
「BEGIN」 block.

If you didn't want that, don't use a *block* with 「BEGIN」.

BEGIN my @i;

Also you wrote the 「if」 wrong.
There shouldn't be a 「;」 before the 「if」.
You also don't need to use 「$_ ~~ 」 with 「/^WARN/」 as that would
automatically happen.

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

You probably also want the lines to be written each to to their own lines.
So you probably want one of the following.

@i.sort.map( *.say )
.say for @i.sort

Again you don't need to use a block with 「END」 either.

So together that would be:

raku -ne 'BEGIN my @i; @i.push($_) if /^WARN/; END .say for @i.sort'

---

That said, I wouldn't use -n in this case.

raku -e 'lines.grep( /^WARN/ ).sort.map( *.say )'

Currently regexes are a bit slow. You can use 「.starts-with」 instead to
make it faster.

raku -e 'lines.grep( *.starts-with(q[WARN]) ).sort.map( *.say )'

(Note that 「 'abc' 」 is short for 「 q'abc' 」 which can also be written as 「
q[abc] 」.
The latter is useful on the command line so that it doesn't interfere with
the command processor quoting rules.)

On Fri, May 8, 2020 at 7:16 AM WFB  wrote:

> Hi,
>
> I am trying to write an one-liner to go through all lines in a logfile and
> look for an certain key word, store the line and sort them before printing
> them out.
>
> My approach was:
> raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END { @i.sort.say
> }"
> That does not work because @i does not exist in the if clause. I tried our
> @i as well with no luck.
>
> How can I store data that can be accessed in the END phaser? Or is there
> another way to archive it? TIMTOWTDI^^
>
> One hint I found was the variable $ and @ respectively. But those
> variables are created for each line new...
>
>
> I did not found a help or examples for -npe except raku -h. Is there more
> helpful stuff somewhere in doc.raku.org? If so I could'nt find it.
>
> Thanks,
> Wolfgang
>


Re: NativeCall questions

2020-05-08 Thread Curt Tilmes
On Fri, May 8, 2020 at 8:49 AM David Santiago  wrote:

> EncodedData* ed = malloc(sizeof(EncodedData));
> ed->data = encbuffer;
> ed->crc32 = crc32;
> return ed;

You're returning a pointer to encbuffer -- make sure the storage for
that is kept around
somewhere.  If it is passed in from Raku, you'll be fine as long as
you hold on to the
object on that side.  Otherwise you might need to allocate/copy it to make sure.

> class EncodedData is repr('CStruct') {
> has CArray[uint8] $.data;
> has uint32 $.crc32;
> }

That's fine, but CArray[uint8] is just a pointer -- it doesn't know
how long the array
it is pointing to is.  It either needs a sentinel at the end (like the
Nul at the end of a
C string), or a separate field with a size to figure that out.

> Don't know how many elements a C array returned from a library

yep

Curt


Re: NativeCall questions

2020-05-08 Thread David Santiago
Thanks for the help.


> EncodedData *encode(unsigned char* data, size_t data_size)
> and return 
> Also your struct and CStruct are defining the contents in the reverse
> order.  They must
> match up exactly.
>

I did those two changes:
"""
EncodedData* ed = malloc(sizeof(EncodedData));
ed->data = encbuffer;
ed->crc32 = crc32;
return ed;
"""

And i also changed the CStruct [1] to:

class EncodedData is repr('CStruct') {
has CArray[uint8] $.data;
has uint32 $.crc32;
}

I'm not getting a SIGSEGV anymore, however i'm now getting the
following error when trying to "say $_ for $ed.data.list":

Don't know how many elements a C array returned from a library
  in method elems at
/usr/share/perl6/core/sources/8660F65A7B3492675BB3B2058DB30E411A4C4E54
(NativeCall::Types) line 223
  in method list at
/usr/share/perl6/core/sources/8660F65A7B3492675BB3B2058DB30E411A4C4E54
(NativeCall::Types) line 226
  in sub MAIN at bin/uints.p6 line 15
  in block  at bin/uints.p6 line 3


I can access without problems $ed.crc32



[1] - if i change the data type to str i get the error: "String
corruption detected: bad storage type"


Best regards,
David Santiago


Raku -npe command line usage

2020-05-08 Thread WFB
Hi,

I am trying to write an one-liner to go through all lines in a logfile and
look for an certain key word, store the line and sort them before printing
them out.

My approach was:
raku -ne "BEGIN {my @i }; @i.push($_); if $_ ~~ /^WARN/; END { @i.sort.say
}"
That does not work because @i does not exist in the if clause. I tried our
@i as well with no luck.

How can I store data that can be accessed in the END phaser? Or is there
another way to archive it? TIMTOWTDI^^

One hint I found was the variable $ and @ respectively. But those variables
are created for each line new...


I did not found a help or examples for -npe except raku -h. Is there more
helpful stuff somewhere in doc.raku.org? If so I could'nt find it.

Thanks,
Wolfgang


Re: NativeCall questions

2020-05-08 Thread Curt Tilmes
On Fri, May 8, 2020 at 6:44 AM David Santiago  wrote:
>
> I'm porting some personal perl5 scripts to Raku, and  one of those
> scripts  is using Inline::C.
> [...]
> Why? How do i fix it?

I haven't tried all of this, but the first thing that leaps out is
that repr('CStruct') is
not a struct -- it is a pointer to a struct.

Your 'return ed' will return the struct by value, not by reference/pointer.

To return that, you need a signature like this:
EncodedData *encode(unsigned char* data, size_t data_size)
and return 

Also your struct and CStruct are defining the contents in the reverse
order.  They must
match up exactly.

> Also the read method from the IO::Handle returns a Buf. I would like
> to pass it directly to my C function. Is there any change in the
> C/raku code i should do?
> The data field from class EncodedData is type "str". Should it be
> CArray[uint8] instead?

Str is good for things that are Nul-terminated and can be safely
parsed as unicode strings.
(I generally use Str instead of str even for NativeCall stuff.)

Here you are passing in the size, though.  You have to be careful
using '.chars' to get
the size in bytes.  They might not be the same in all cases.

I would recommend just passing it in as a 'Blob'.
sub encode(Blob $data, size_t $size --> EncodedData) is
native('lib/MyLib/libmylib.so') {*};
my $buf = "my string".encode;
my $encoded = encode($buf, $buf.bytes);

Using str in your CStruct for the return should be fine if the
returned string is Nul-terminated
and can be safely parsed.  Otherwise define it as CArray[uint8].


Curt


Re: NativeCall questions

2020-05-08 Thread Timo Paulssen
Hi David,

the first thing that catches my eye is that your struct and the class
have the members switched around, so you're already almost guaranteed to
read a bogus pointer when trying to get the data.

Also, please note that returning structs directly, or passing structs
directly, as arguments is hairy business, you'll probably want to work
with pointers instead, which either means your function has to malloc
the EncodedData struct, or take a pointer to an already created one as
an argument - you would then create the EncodedData on the raku side
with a .new

Whenever you declare a struct to be passed as argument or received as
return value in NativeCall, you will get "TheStruct *" on the C side.

Not sure if that's all it takes to fix this. Feel free to write back to
the list.

Hope to Help
  - Timo

On 08/05/2020 12:44, David Santiago wrote:
> Hello,
>
> I'm porting some personal perl5 scripts to Raku, and  one of those
> scripts  is using Inline::C.
>
> The inline::c code would contain a function with the signature:
>
> AV* encode(unsigned char* data, size_t data_size)
>
> Description of the parameters on the original perl script:
> data -> binary string (the value comes from read $FH)
> data_size -> size in bytes of binary_string (the value comes from the
> return of the read function)
>
> And it would return an array with two values (a binary string and its crc32):
>
> """
> SV* enc_string = newSVpv(buffer, 0);
> SV* ret = sv_2mortal(newAV());
> av_push(ret, enc_string);
> SV* hex_string = newSVpv(hex_number, 0);
> av_push(ret, hex_string);
> free(hex_number);
> return ret;
> """
>
>
> Now for using it in raku, i'm changing  the return value to a struct:
> typedef struct{
>   unsigned char* data;
>   uint32_t crc32;
> } EncodedData;
>
> So i changed the signature to:
> EncodedData encode(unsigned char* data, size_t data_size)
>
> And i'm returning the struct:
> """
> EncodedData ed;
> ed.crc32 = crc32;
> ed.data = encbuffer;
>
> return ed;
> """
>
> Create a shared lib gcc -shared -olibmylib.so mylib.c
>
> Now on my raku script i did:
> """
> class EncodedData is repr('CStruct') {
> has uint32 $.crc32;
> has str $.data;
> }
>
> sub MAIN() {
> sub encode(str $data, size_t $size --> EncodedData) is
> native('lib/MyLib/libmylib.so') {*};
> my EncodedData $ed = encode("this is my string that will be
> encoded", "this is my string that will be encoded".chars );
> say $ed.crc32.base(16);
> say $ed.data;
> }
> """
> However this isn't working. Everytime i access "$ed.data" I'm getting
> the following error:
> "fish: 'raku bin/uints.p6' terminated by signal SIGSEGV (Address
> boundary error)"
>
> Why? How do i fix it?
>
> Also the read method from the IO::Handle returns a Buf. I would like
> to pass it directly to my C function. Is there any change in the
> C/raku code i should do?
> The data field from class EncodedData is type "str". Should it be
> CArray[uint8] instead?
>
> Best regards,
> David Santiago


NativeCall questions

2020-05-08 Thread David Santiago
Hello,

I'm porting some personal perl5 scripts to Raku, and  one of those
scripts  is using Inline::C.

The inline::c code would contain a function with the signature:

AV* encode(unsigned char* data, size_t data_size)

Description of the parameters on the original perl script:
data -> binary string (the value comes from read $FH)
data_size -> size in bytes of binary_string (the value comes from the
return of the read function)

And it would return an array with two values (a binary string and its crc32):

"""
SV* enc_string = newSVpv(buffer, 0);
SV* ret = sv_2mortal(newAV());
av_push(ret, enc_string);
SV* hex_string = newSVpv(hex_number, 0);
av_push(ret, hex_string);
free(hex_number);
return ret;
"""


Now for using it in raku, i'm changing  the return value to a struct:
typedef struct{
  unsigned char* data;
  uint32_t crc32;
} EncodedData;

So i changed the signature to:
EncodedData encode(unsigned char* data, size_t data_size)

And i'm returning the struct:
"""
EncodedData ed;
ed.crc32 = crc32;
ed.data = encbuffer;

return ed;
"""

Create a shared lib gcc -shared -olibmylib.so mylib.c

Now on my raku script i did:
"""
class EncodedData is repr('CStruct') {
has uint32 $.crc32;
has str $.data;
}

sub MAIN() {
sub encode(str $data, size_t $size --> EncodedData) is
native('lib/MyLib/libmylib.so') {*};
my EncodedData $ed = encode("this is my string that will be
encoded", "this is my string that will be encoded".chars );
say $ed.crc32.base(16);
say $ed.data;
}
"""
However this isn't working. Everytime i access "$ed.data" I'm getting
the following error:
"fish: 'raku bin/uints.p6' terminated by signal SIGSEGV (Address
boundary error)"

Why? How do i fix it?

Also the read method from the IO::Handle returns a Buf. I would like
to pass it directly to my C function. Is there any change in the
C/raku code i should do?
The data field from class EncodedData is type "str". Should it be
CArray[uint8] instead?

Best regards,
David Santiago