Giter Site home page Giter Site logo

Comments (6)

damianwadley avatar damianwadley commented on May 29, 2024

This is a "feature" of PHP that has been deprecated in 8.3 and will be removed (become an error) in 9.0.

https://www.php.net/manual/en/language.operators.increment.php#language.operators.increment.string
https://wiki.php.net/rfc/saner-inc-dec-operators

from php-src.

6562680 avatar 6562680 commented on May 29, 2024

Ok, just put it here:

<?php

/**
 * _itertools_range(0,2) -> 0 1 2
 * _itertools_range(2,0,-1) -> 2 1 0
 *
 * @param int      $start
 * @param int|null $end
 * @param int|null $step
 *
 * @return \Generator
 */
function _itertools_range($start, $end, $step = null) : \Generator
{
    $step = $step ?? 1;

    if (! (($isStringStart = is_string($start)) || is_int($start) || is_float($start))) {
        throw new \LogicException('The `start` should be int|float|string');
    }

    if (! (($isStringEnd = is_string($end)) || is_int($end) || is_float($end))) {
        throw new \LogicException('The `end` should be int|float|string');
    }

    if (! (($isFloatStep = is_float($step)) || is_int($step))) {
        throw new \LogicException('The `step` should be int|float');
    }

    $_step = $step;

    $intStep = (int) $step;
    $floatStep = (float) $step;

    if ($floatStep === (float) $intStep) {
        $_step = $intStep;

        $isFloatStep = false;
    }

    if (! $_step) {
        return;
    }

    $isModeString = ($isStringStart || $isStringEnd);

    if ($isModeString && $isFloatStep) {
        throw new \LogicException('The `step` should be int if `start` or `end` are strings');
    }

    $_start = $start;
    $_end = $end;

    if ($isModeString) {
        if (! $isStringStart) {
            $_start = (string) $_start;
        }

        if (! $isStringEnd) {
            $_end = (string) $_end;
        }

    } else {
        $intStart = (int) $start;
        $intEnd = (int) $end;

        $floatStart = (float) $start;
        $floatEnd = (float) $end;

        if ($floatStart === (float) $intStart) {
            $_start = $intStart;

        } else {
            $_start = $floatStart;
        }

        if ($floatEnd === (float) $intEnd) {
            $_end = $intEnd;

        } else {
            $_end = $floatEnd;
        }
    }

    $isReverse = $_step < 0;

    $i = $_start;

    while (
        false
        || ($isReverse && ($i >= $_end))
        || ($i <= $_end)
    ) {
        yield $i;

        if ($isModeString) {
            if (false
                || ($isReverse && ($i === $_start))
                || ($i === $_end)
            ) {
                break;
            }

            for ( $ii = 0; $ii < $_step; $ii++ ) {
                if ($isReverse) {
                  $i--;
                } else {
                  $i++;
                }
            }

        } else {
            $i += $_step;
        }
    }
}


foreach (_itertools_range('aa', 'zz') as $v) {
  var_dump($v);
}

Output:

string(2) "aa"
string(2) "ab"
string(2) "ac"
string(2) "ad"
string(2) "ae"
string(2) "af"
string(2) "ag"
string(2) "ah"
string(2) "ai"
string(2) "aj"
...
string(2) "zz"

Common use case - product, product_repeat, combinations_unique, combinations_all, permutations

Most common practical IRL use case: you want to get decbin() for all cases until int $n -> '00', '01', '10', '11'
It is _product_repeat(2, range(0, 1)) or for cycle with base_convert...
_product_repeat internally use _product that is internally use _range

We had just get in generators era getting AI bots, that is done with generators. Skipping generator based stuff in next PHP could be a mistake...

from php-src.

6562680 avatar 6562680 commented on May 29, 2024

Few days ago i've received comment in some of PHP chats... "Your speaking about generators show us that you're a coder that had 1 year of experience, because EVERYBODY knows that they're useless and the one-time toy".

It exactly explains that people didn't even understand that any ASYNC/PARALLEL operations could be realized with generators (yield callable and arguments) and event-loop (process manager).

Just

  • implement pipeline that expects [ callable, args ] as yield. Pipeline is depth-first tree walker.
  • implement promise that also expects [ callable, args ] as yield. Promise is width-first tree walker.
  • extracting values from already running generator outside primary iterating loop could be helpful, currently - impossible, so you need to create new generator from existing queue of planned calls if you want to implement middleware stuff.

Both promise and pipeline is callables too. Actually - it has method call() that is loop with call_user_func(), and callAsync() that is Generator yields [ callable, args ] and awaiting back the [ result ]. But, it means you can create promise of pipelines or create pipeline of promises.

Await() function iterates over generator in current process (preventing yield to the above loop) delegating call to the ProcessorInterface, that is in simpliest case just call call_user_func_array().

Async() function returns yield of the passed callable and given arguments instead of doing call_user_func(). Actually is a function that return generator that takes function name and given args, yields it and awaits result to $gen->send();

Loop() function iterates over generator and run process for each yielded callable. In that process it delegates call to the ProcessorInterface like await() function. As in any daemon-like application tickrate is needed like usleep(1) giving time to processor to handle CPU health. Also it limites the count of processes to N using simple array with N cells and stores process PIDs. Our process manager is wait until cell process is finish, free the cell, then start new task. Exactly because promise-pipeline stuff parallel things goes parallel, serial things goes serial, and our loop should dont care about it. Main point is - HOLDING DATA INSIDE our "callable", state-managment, self-contain callable...

Lambda/closure functions could be serialized as passed uses and code file/line pointer, inside one loop code (war?) never changes.

Async timer is just checking microtime() > timerExpiredAt in infinite loop... So its "very fast" action instead of "blocking action". Any function could be "non-blocking" if you return its name and arguments to later call via process manager instead of call it immediate inside current process.

Its possible in any OS... And could be extended with pcntl_fork in linux to be more faster.

from php-src.

6562680 avatar 6562680 commented on May 29, 2024

@damianwadley up

from php-src.

damianwadley avatar damianwadley commented on May 29, 2024

I don't understand what your commentary has to do with the reported issue: 'z'++ increments to 'aa' which is still <= 'z' and thus the loop does not end there, and this ability to increment letter strings will be removed in the future.

from php-src.

6562680 avatar 6562680 commented on May 29, 2024

Thank you, Mario. You're always right. Just read the recipe and notify your product manager, if you prefer direct speaking instead of thinking deep.

My reply is about "do not remove iterators "features" because in next 10 years iterarors could replace any task you want to design.

from php-src.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.