Can I capture the returned value of a routine used in RUN-MAIN?
Asked Answered
V

3

7

I want a script to run a subroutine exported from a module, with the exported sub to be run as MAIN in the script. The subroutine does all that I want, except that it returns the result instead of printing it.

RUN-MAIN seems to achieve most of what I'm aiming for, but I'm not sure how to grab the returned value of the routine.

Is there a way I can capture the output of the routine given to RUN-MAIN to be printed? Is RUN-MAIN the right approach for this sort of thing?

Votaw answered 19/11, 2019 at 18:55 Comment(0)
V
2

Redispatch can be used within a wrapped routine to call the original. say can then be used on the result of the redispatch within the wrap. This will also generate usage from the original routine.

sub foo (
  $input #= The data we want
) {
  return $input;
}

&foo.wrap( sub (|) { callsame.say } );

RUN-MAIN &foo, Nil;

$ raku filename.raku

Usage:
  filename.raku <input>
  
    <input>    The data we want
Votaw answered 18/11, 2020 at 11:58 Comment(0)
C
5

You could use the function composition operator infix:<∘> or infix:<o>

sub foo ($name, Int $n=1) { 
    "Hello $name\n" xx $n 
}; 
RUN-MAIN &say o &foo, Nil; #or &foo Ro &say

but unfortunately, it is changing the signature

sub foo ($name, Int $n=1) { 
    "Hello $name\n" xx $n 
};

say &foo.signature;
say (&foo Ro &say).signature;

so default USAGE message does not work.

Cyanotype answered 20/11, 2019 at 15:54 Comment(2)
The lack of USAGE is indeed unfortunate, but infix:<∘> is a nice idea! I'll have a play around with it.Votaw
I'm playing around with the following which seems to doing what I want so far: our &MAIN = &say ∘ &foo; RUN-MAIN( &foo, Nil );Votaw
V
2

The following seems to accomplish what I intended (where foo is the target sub).

RUN-MAIN( &foo, Nil );

sub MAIN ( |c --> Nil ) {
  foo(|c).say;
}

EDIT: Unfortunately this solution is not ideal, as it runs &foo twice.

Votaw answered 19/11, 2019 at 23:56 Comment(2)
It is not a typo. The first |c is a Capture parameter, and the additional prepended | is to make it a Slip. This didn't quite work as I'd expected, although I'll need to remind myself why, and if it was exactly this or something else that caused my issue (IIRC I was running MAIN twice somehow, once with and once without say). After playing around a bit this was the final result I came up with: github.com/manwar/perlweeklychallenge-club/blob/master/…Votaw
It seems I misunderstood the documentation, so yes the extra pipe is in fact a typo :)Votaw
V
2

Redispatch can be used within a wrapped routine to call the original. say can then be used on the result of the redispatch within the wrap. This will also generate usage from the original routine.

sub foo (
  $input #= The data we want
) {
  return $input;
}

&foo.wrap( sub (|) { callsame.say } );

RUN-MAIN &foo, Nil;

$ raku filename.raku

Usage:
  filename.raku <input>
  
    <input>    The data we want
Votaw answered 18/11, 2020 at 11:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.