Sidef

 view release on metacpan or  search on metacpan

lib/Sidef/Types/Block/Block.pm  view on Meta::CPAN

        while (1) {
            $self->run;
        }

        $self;
    }

    sub if {
        my ($self, $bool) = @_;
        $bool ? $self->run : $bool;
    }

    sub __fdump {
        my ($self, $obj) = @_;

        my $ref = ref($obj);

        if ($ref eq 'Sidef::Types::Number::Number') {
            my ($type, $str) = $obj->_dump();

            if ($type eq 'int') {
                return scalar {dump => ($ref . "::_set_int('${str}')")};
            }

            return scalar {dump => ($ref . "::_set_str('${type}', '${str}')")};
        }

        if ($ref eq 'Sidef::Module::OO' or $ref eq 'Sidef::Module::Func') {

            my $module = (
                          ref($obj->{module})
                          ? Data::Dump::Filtered::dump_filtered($obj->{module}, __SUB__)
                          : qq{"$obj->{module}"}
                         );

            my $module_name = ref($obj->{module}) || $obj->{module};

            my $code = {
                dump => qq{
                    do {
                        use $ref;
                        eval "require $module_name";
                        bless({ module => $module }, "$ref");
                    }
                }
            };

            return $code;
        }

        if ($ref eq 'Sidef::Types::Block::Block') {
            die "[ERROR] Blocks cannot be serialized!";
        }

        return;
    }

    sub ffork {
        my ($self, @args) = @_;

        state $x = require Data::Dump::Filtered;
        open(my $fh, '+>', undef);    # an anonymous temporary file
        my $fork = Sidef::Types::Block::Fork->new(fh => $fh);

        # Try to fork
        my $pid = fork() // die "[ERROR] Cannot fork";

        if ($pid == 0) {
            srand();
            my @objs = ($self->call(@args));
            print $fh scalar Data::Dump::Filtered::dump_filtered(@objs, \&__fdump);
            exit 0;
        }

        $fork->{pid} = $pid;
        $fork;
    }

    *start = \&ffork;

    sub fork {
        my ($self, @args) = @_;

        my $fork = Sidef::Types::Block::Fork->new();

        my $pid = CORE::fork() // die "[ERROR] Cannot fork: $!";
        if ($pid == 0) {
            srand();
            $self->call(@args);
            exit 0;
        }

        $fork->{pid} = $pid;
        $fork;
    }

    sub thread {
        my ($self, @args) = @_;
        state $x = do {
            eval { require forks; } // require threads;
            *threads::get  = \&threads::join;
            *threads::wait = \&threads::join;
            1;
        };
        Sidef::Module::OO->__NEW__(
                                   threads->create(
                                                   {
                                                    'context' => 'list',
                                                    'exit'    => 'thread_only'
                                                   },
                                                   sub { $self->call(@args) }
                                                  )
                                  );
    }

    *thr = \&thread;

    sub _iterate {
        my ($callback, @objs) = @_;

        foreach my $obj (@objs) {

lib/Sidef/Types/Block/Block.pm  view on Meta::CPAN

        my $max = CORE::int($n // 1);

        _iterate(
            sub {
                if ($self->run(@_)) {
                    push @array, @_;
                    last if (@array >= $max);
                }
            },
            $range
        );

        defined($n)
          ? Sidef::Types::Array::Array->new(\@array)
          : $array[0];
    }

    sub nth {
        my ($self, $n, $range) = @_;

        state $inf_range = Sidef::Types::Number::Number->inf->range;

        $range //= $inf_range;

        my $k   = 0;
        my $nth = undef;

        $n = CORE::int($n);
        $n > 0 || return undef;

        _iterate(
            sub {
                if ($self->run(@_) and ++$k == $n) {
                    $nth = $_[0];
                    last;
                }
            },
            $range
        );

        return $nth;
    }

    sub sum {
        my ($self, $range) = @_;
        $range->sum_by($self);
    }

    *Σ = \∑

    sub prod {
        my ($self, $range) = @_;
        $range->prod_by($self);
    }

    *Π = \∏

    sub cache {
        my ($self) = @_;
        $self->{is_cached} && return $self;
        state $x = require Memoize;
        $self->{code}      = Memoize::memoize($self->{code});
        $self->{is_cached} = 1;
        $self;
    }

    sub uncache {
        my ($self) = @_;
        $self->{is_cached} || return $self;
        state $x = require Memoize;
        if (defined(my $uncached = eval { Memoize::unmemoize($self->{code}) })) {
            $self->{code}      = $uncached;
            $self->{is_cached} = 0;
        }
        $self;
    }

    sub flush_cache {
        my ($self) = @_;
        $self->{is_cached} || return $self;
        state $x = require Memoize;
        eval { Memoize::flush_cache($self->{code}) };
        $self;
    }

    sub dump {
        Sidef::Types::String::String->new("$_[0]");
    }

    *to_s   = \&dump;
    *to_str = \&dump;

    {
        no strict 'refs';

        foreach my $name (qw(bsearch bsearch_le bsearch_ge bsearch_inverse)) {

            *{__PACKAGE__ . '::' . $name} = sub {
                my ($self, $x, $y) = @_;

                my $from = $x // Sidef::Types::Number::Number::ZERO;
                my $upto = $y // $from->inc->mul(Sidef::Types::Number::Number::TWO);

                while (1) {
                    my $k = $from->$name($upto, $self);

                    if (defined($k) and $k->is_between($from, $upto)) {
                        return $k;
                    }

                    $from = $upto->inc;
                    $upto = $from->add($from);
                }

                return Sidef::Types::Number::Number::MONE;
            };
        }

        *{__PACKAGE__ . '::' . '*'}  = \&repeat;
        *{__PACKAGE__ . '::' . '<<'} = \&for;
        *{__PACKAGE__ . '::' . '>>'} = \&map;
        *{__PACKAGE__ . '::' . '&'}  = \&grep;
        *{__PACKAGE__ . '::' . '∘'}  = \&compose;
    }
}

1;



( run in 0.436 second using v1.01-cache-2.11-cpan-39bf76dae61 )