Home > Back-end >  Closure in JavaScript vs PHP
Closure in JavaScript vs PHP

Time:02-24

I am trying to implement a very simple closure related task in PHP which is not going well. I have this solution in JavaScript. How do i implement this in PHP?

const data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

const getChunksOfTwo = () => {
  let pos = 0
  
  return () => {
     const start = pos
     const finish = start   2
     const chunk = data.slice(start, finish)
     pos  
     return chunk
  }
}

// To initiate the closure
const closureFun = getChunksOfTwo()

// Call the closureFun
closureFun() // Gives [1, 2]
closureFun() // Gives [2, 3]
closureFun() // Gives [3, 4]

But in PHP the same apparently does not work. I am trying this:

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $pos = 0;

   return function() {
     $start = $pos;
     $finish = $start   2;
     $chunk = array_slice($data, $start, $finish);
     $pos  ;
     return $chunk;
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
$closureFun(); // Does not give [1, 2]
$closureFun(); // Does not give [2, 3]

CodePudding user response:

There are two issues in your php codes.

First is a closure in PHP encapsulates its scope, meaning that it has no access to the scope in which it is defined or executed. It is, however, possible to inherit variables from the parent scope (where the closure is defined) into the closure with the use keyword. This inherits the variables by-value, a copy is made available inside the closure using its original name.

As you want to keep the value of $pos for each function call, you need to pass it by reference with &$pos.

Second, the implementation of array_slice in php is different from slice in js. So, you need to change your input in the php.

<?php
$data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];

function getChunksOfTwo($data) {
    $pos = 0;

    return function () use ($data, &$pos) {
        $chunk = array_slice($data, $pos, 2);
        $pos  ;
        return $chunk;
    };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun());
print_r($closureFun());
print_r($closureFun());

CodePudding user response:

I propose an alternative why not use array_chunk?

$data = [1,2, 3, 4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];
$chunk = array_chunk($data, 2);
$pos = 0;
print_r($chunk[$pos]);
$pos  ;
print_r($chunk[$pos]);
$pos  ;
print_r($chunk[$pos]);

Output:

Array
(
    [0] => 1
    [1] => 2
)
Array
(
    [0] => 3
    [1] => 4
)
Array
(
    [0] => 5
    [1] => 6
)

Reference:

CodePudding user response:

You can try this

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $pos = 0;
   
   return function() use(&$pos, $data) {
     $start = $pos;
     $finish = 2;
     $chunk = array_slice($data, $start, $finish);
     $pos =2;
     return $chunk;
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun()); // gives [1, 2]
print_r($closureFun()); // gives [2, 3]

Or

$data = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20];

function getChunksOfTwo($data) {
   $chunks = array_chunk($data, 2);
   $pos = 0;
   
   return function() use(&$pos, $data, $chunks) {
     return $chunks[$pos  ];
   };
};

// To initiate the closure
$closureFun = getChunksOfTwo($data);

// Call the closureFun
print_r($closureFun()); // gives [1, 2]
print_r($closureFun()); // gives [2, 3]

& with var means passing by reference source

It has to be passed by reference to mutate that variable otherwise it copies the original and every new call will have the same value.

Outupt

Array
(
    [0] => 1
    [1] => 2
)
Array
(
    [0] => 3
    [1] => 4
)

  • Related