Ленивое Функциональное Определение в PHP - действительно ли это возможно?

Удалить элементы с использованием массива индексов:

  1. Массив строк и индексов
    let animals = ["cats", "dogs", "chimps", "moose", "squarrel", "cow"]
    let indexAnimals = [0, 3, 4]
    let arrayRemainingAnimals = animals
        .enumerated()
        .filter { !indexAnimals.contains($0.offset) }
        .map { $0.element }
    
    print(arrayRemainingAnimals)
    
    //result - ["dogs", "chimps", "cow"]
    
  2. Массив целых чисел и индексов
    var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
    let indexesToRemove = [3, 5, 8, 12]
    
    numbers = numbers
        .enumerated()
        .filter { !indexesToRemove.contains($0.offset) }
        .map { $0.element }
    
    print(numbers)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    

Удалить элементы, используя значение элемента другого массива

  1. Массивы целых чисел
    let arrayResult = numbers.filter { element in
        return !indexesToRemove.contains(element)
    }
    print(arrayResult)
    
    //result - [0, 1, 2, 4, 6, 7, 9, 10, 11]
    
  2. Массивы строк
    let arrayLetters = ["a", "b", "c", "d", "e", "f", "g", "h", "i"]
    let arrayRemoveLetters = ["a", "e", "g", "h"]
    let arrayRemainingLetters = arrayLetters.filter {
        !arrayRemoveLetters.contains($0)
    }
    
    print(arrayRemainingLetters)
    
    //result - ["b", "c", "d", "f", "i"]
    
5
задан scunliffe 23 September 2008 в 01:49
поделиться

8 ответов

Используйте локальный статический var:

function foo() {
    static $called = false;
    if ($called == false) {
        $called = true;
        expensive_stuff();
    }
}

Избегайте использования глобального для этого. Это создает помехи глобальному пространству имен и делает функцию менее инкапсулированной. Если другие места помимо внутренностей функциональной потребности знать, назвали ли это, то это стоило бы того для помещения этой функции в классе как Alan Storm, указали.

13
ответ дан 18 December 2019 в 06:36
поделиться

можно сделать условное функциональное определение.

if( !function_exists('baz') )
{ 
    function baz( $args ){ 
        echo $args; 
    }
}

Но в настоящее время, функция становится кирпичом при определении.

Можно использовать create_function, но я предложил бы, чтобы Вы не ДЕЛАЛИ, потому что это медленно, использует большую память, не освобождается () 'd недо php выходы и является дырой в системе безопасности, столь же большой как оценка ().

Ожидайте до PHP5.3, где у нас есть "закрытия" http://wiki.php.net/rfc/closures

Затем Вам разрешат сделать

if( !isset( $baz ) ) 
 { 
    $baz = function( $args )
    { 
        echo $args;
    }
}

$baz('hello');

$baz = function( $args )
{ 
       echo $args + "world"; 
}
$baz('hello');

На дополнительные материалы для чтения это - эффект, который Вы хотите.

$fname = 'f_first'; 
function f_first( $even ) 
{ 
    global $fname; 
    doExpensiveStuff(); 
    $fname = 'f_others';
    $fname( $even );
    /* code */ 
}
function f_others( $odd ) 
{
     print "<b>".$odd."</b>";
}

foreach( $blah as $i=>$v ) 
{
   $fname($v);
}

Это сделает то, что Вы хотите, но вызов мог бы быть немного более дорогим, чем нормальный вызов функции.

В PHP5.3 Это должно быть допустимо также:

$func = function( $x ) use ( $func ) 
{ 
     doexpensive(); 
     $func = function( $y )
     { 
          print "<b>".$y."</b>";
     }
     $func($x);
}
foreach( range(1..200) as $i=>$v ) 
{ 
    $func( $v ); 
}

(Лично, я думаю, конечно, что все эти аккуратные приемы будут невероятно медленнее, чем Ваше более раннее сравнение 2 положительных битов.;))

Если Вы действительно обеспокоены получением лучшей скорости везде

$data = // some array structure
doslowthing(); 
foreach( $data as $i => $v ) 
{
   // code here 
}

Вы не можете делать это однако, но Вы не дали достаточно объема для разъяснения. Если можно сделать это однако, то хорошо, простые ответы являются часто лучшими :)

4
ответ дан 18 December 2019 в 06:36
поделиться

Вы на самом деле представили этот код? Я сомнителен, что дополнительный булев тест собирается оказать любое измеримое влияние на время рендеринга страницы.

6
ответ дан 18 December 2019 в 06:36
поделиться

Не используйте include() или include_once(), если Вы не заботитесь если include() сбои. Если Вы включаете код, то Вы заботитесь. Всегда используйте require_once().

1
ответ дан 18 December 2019 в 06:36
поделиться

При доведении открытия, что дополнительный булев тест будет слишком дорогим, можно установить переменную на название функции и назвать его:

$func = "foo";    

function foo()
{
    global $func;
    $func = "bar";
    echo "expensive stuff";
};


function bar()
{
    echo "do nothing, i guess";
};

for($i=0; $i<5; $i++)
{
    $func();
}

Дайте этому выстрел

0
ответ дан 18 December 2019 в 06:36
поделиться

PHP не имеет лексического контекста, таким образом, Вы не можете сделать то, что Вы хотите с функцией. Однако PHP имеет классы, который концептуально работает точно таким же образом с этой целью.

В JavaScript Вы сделали бы:

var cache = null;
function doStuff() {
  if (cache == null) {
    cache = doExpensiveStuff();
  }
  return cache;
}

С классами (В PHP), Вы сделали бы:

class StuffDoer {
  function doStuff() {
    if ($this->cache == null) {
      $this->cache = $this->doExpensiveStuff();
    }
    return $this->cache;
  }
}

Да, основанное на классах ООП является более подробным, чем функциональное программирование, но мудрым производительностью, они должны быть о подобном.

Все, что в стороне, PHP 5.3, вероятно, получит лексический контекст / поддержка закрытия, поэтому когда это выйдет, можно записать в более быстром стиле функционального программирования. Посмотрите rfc-wiki PHP для подробного описания этой функции.

0
ответ дан 18 December 2019 в 06:36
поделиться

Как насчет того, чтобы использовать локальные статические переменные?

function doStuff($param1) {
    static $called = false;
    if (!$called) {
        doExpensiveStuff($param1);
        $called = true;
    }
    // do the rest
}

Если необходимо сделать дорогой материал только однажды для данного значения параметра, Вы могли бы использовать буфер массива:

function doStuff($param1) {
    static $buffer = array();
    if (!array_key_exists($param1, $buffer)) {
        doExpensiveStuff($param1);
        $buffer[$param1] = true;
    }
    // do the rest
}

Локальные статические переменные являются персистентными через вызовы функции. Они помнят значение после возврата.

0
ответ дан 18 December 2019 в 06:36
поделиться

Какая-либо причина Вы преданы функциональному шаблону стиля? Несмотря на наличие анонимных функций и планов относительно закрытия, PHP действительно не является функциональным языком. Это походит на класс, и объект был бы лучшим решением здесь.

Class SomeClass{
    protected $whatever_called;
    function __construct(){
        $this->called = false;
    }
    public function whatever(){
        if(!$this->whatever_called){
            //expensive stuff
            $this->whatever_called = true;
        }
        //rest of the function
    }
} 

Если бы Вы хотели стать необычными, то Вы могли бы использовать волшебные методы, чтобы избежать необходимости предопределять названные булевские переменные. Если Вы не хотите инстанцировать объекта, пойдите статичные.

0
ответ дан 18 December 2019 в 06:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: