1

I would like to try mix of AnyEvent and Coro.
Is there a way to make the three lines between BEGIN and END more elegant/condensed?

use AnyEvent::HTTP;
use Coro;

async {
  _
  # BEGIN
  my $READY = AnyEvent->condvar;
  my $guard = http_request( GET => $url, $READY );
  my ($data, $hHeaders ) = $READY->recv;
  # END
  …
}

WARNING: man AnyEvent suggest slightly different way for Coro integration but the general idea stays the same (comment added after accepted reply).

AnyEvent::HTTP::http_get "url", Coro::rouse_cb;
my ($body, $hdr) = Coro::rouse_wait;
AnFi
  • 10,493
  • 3
  • 23
  • 47
  • Subs. This is what subs are for. – ikegami Feb 24 '23 at 13:39
  • Wrappers "sub per sub" are the trivial way for **a few** http_request like calls. I think about some custom preprocessor (e.g. Filter::cpp) for hundredths different http_request like calls [with callback/condvar as the last parameter). Maybe you suggest something more than my *simple* interpretation. – AnFi Feb 24 '23 at 13:58
  • Subs take parameters, you know. – ikegami Feb 24 '23 at 14:20

2 Answers2

3

Subs. This is what subs are for.

sub sync {
   my $sub = shift;
   $sub = \&$sub;   # Make `strict refs` happy.
   my $done = AnyEvent->condvar;
   my $guard = $sub->( @_, $done );
   return $done->recv;
}

my ( $data, $headers ) = sync \&http_request, GET => $url;
  # -or-
my ( $data, $headers ) = sync http_request => GET => $url;

or

use Sub::Name qw( sub_name );

sub build_sync(_) {
   my $wrapped_sub_name = shift;
   my $wrapped_sub = \&$wrapped_sub_name;

   my $sub_name = $wrapped_sub_name . '_sync';
   my $sub = sub_name $sub_name => sub {
      my $done = AnyEvent->condvar;
      my $guard = $wrapped_sub->( @_, $done );
      return $done->recv;
   };

   no strict qw( refs );
   *$sub_name = $sub;
}

build_sync for qw( http_request ... );

my ( $data, $headers ) = http_request_sync( GET => $url );
ikegami
  • 367,544
  • 15
  • 269
  • 518
  • The `build_sync` proposal seems to be the best for small/medium scripts IMHO. I'm going to wait a few days for other suggestion and accept it without anything better. My another idea is new `sync` module with AUTOLOAD and syntax `my ( $data, $headers ) = sync::http_request( GET => $url );` – AnFi Feb 24 '23 at 18:42
  • It may be sub AUTOLOAD in the script and itself and sync_ prefix in function name. (sync_http_request) Anyway I want to try mix of Coro and AnyEvent for more intuitive scripts. – AnFi Feb 24 '23 at 19:24
  • Basically, you want an async system that returns C# Tasks instead of using callbacks, so that you could do `await f();` – ikegami Feb 24 '23 at 21:32
  • Much better would be version where `recv` is called when scripts tries to **access** the values - "lazy recv" v. "eager recv". "Eager recv" is simpler/trivial to implement. "Lazy recv" is better for background processing. – AnFi Feb 27 '23 at 15:42
2

We can use the following:

sub SYNC (\&@) {
  my $sub = shift @_;
  my $READY =  AnyEvent->condvar;
  my $guard = &$sub( @_, $READY);
  return $READY->recv;
}

my ($data, $hHeaders ) = SYNC &http_request, GET => $url;
ikegami
  • 367,544
  • 15
  • 269
  • 518
AnFi
  • 10,493
  • 3
  • 23
  • 47