How does Current function work?

Asked

Viewed 955 times

19

For some time I always use the function current() in PHP, to get the first element of array (which is actually not its functionality, as it returns the current pointer on which the array is) and I’ve been noticing something that has left me a little confused compared to the features of next(), prev() and reset().

And I’ll explain why.

In the PHP manual and even in Notepad++, we see that the argument of current() is a reference passage of an element of the type array, in the same way as next() and prev(). In fact, the job declaration is this:

mixed current ( array &$array )

However, if you use it in a array function returned or even a array temporary (in this case, declared directly as argument of current()) it works normally (the argument being a variable passed by reference).

current([1, 2, 3]);// 1
current(explode(',', '1, 2, 3')); //1
$array = [1, 2, 3];
current($array); //1

Now, what makes my confusion even bigger is that if I pass one array directly in functions such as next() and prev(), this generates a fatal error:

next([1, 2, 3]);
//Fatal error: Only variables can be passed by reference
echo next(explode(',', '1, 2, 3')); 
//Strict Standards: Only variables should be passed by reference

The question is: If the PHP manual specifies in the function statement that current() works with arrays passed by reference (like many other functions used for arrays), because she’s the only one who works with arrays passed directly as argument (as in the first example)?

Note: The PHP Handbook is very emphatic: mixed current ( array &$array )

  • I just discovered something important: using the PHP Sandbox, I noticed that the Current function started to behave like this from version 5.1 of PHP. Previously to this above version, when a parameter was passed that was not a variable in current() (because of the reference passage), this generated a fatal error. We can deduce that in the manual, mixed current ( array &$array ) is a reference to the way this function behaved in the old days.

  • 2

    php is not reporting the use of current() correctly. The code current(1) generates Current() expects Parameter 1 to be array, integer Given, but if you do current(new stdClass), it generates no warning. If expera array, why accepts object?

4 answers

12

Because there is no need to pass it by reference, the only thing this function does, is to return the contents of the current pointer of the array, and this will not modify the array, it is not necessary to pass it by reference.

Other examples of current() and other functions of the same segment:

$transport = array('foot', 'bike', 'car', 'plane');
$mode = current($transport); // $mode = 'foot';
$mode = next($transport);    // $mode = 'bike';
$mode = current($transport); // $mode = 'bike';
$mode = prev($transport);    // $mode = 'foot';
$mode = end($transport);     // $mode = 'plane';
$mode = current($transport); // $mode = 'plane';

$arr = array();
var_dump(current($arr)); // bool(false)

$arr = array(array());
var_dump(current($arr)); // array(0) { }

Note that all functions simply return and modify the pointer.

About the error you generated when trying to apply next() in the array statement, it is because these functions were made to work with the array pointer.

But if you try to declare the array within the function, the pointer does not exist, and so generates the error you posted in the question.

Pointer is directly linked to the creation of the variable of type array, is the index of the variable, which only exists from the moment you declare it.

The manual states that the array is passed by reference:

mixed current ( array &$array )

This is because when we use functions of this "group", such as next(), it changes the position of the pointer, ie it is not necessary to pass by reference, as the function itself does this by changing the position of the pointer ex.:

$var = array(1,2,3);
echo current($var);//1
echo next($var);//2  <- Alterou o ponteiro de $var
echo current($var);//2 
$a = $var; // <- Copiou o array
echo current($a); //2 <- Ponteiro na mesma posição de $var.

Reference passage: http://www.php.net/manual/en/language.references.pass.php

Function current(): http://www.php.net/manual/en/function.current.php

  • next() does not modify the array, just as Current() does not; and next() accepts passage by reference only. I would like to understand the sense that the manual has made the syntax explicit mixed current ( array &$array ), when it doesn’t work that way.

  • No, you can do the test this way:;$var = array(1,2,3);&#xA; echo current($var);&#xA; echo next($var); There is no reference passage in this, and it works.

  • I’d like you to observe the syntax that the Manual put there. That’s the question. It’s like this: array &$array. If you look at next(), it’s the same thing. http://www.php.net/manual/en/function.next.php

  • The Current() function works with non-referenced arrays (and even with objects), and this is indisputable (because it works, right). The statement of the function (in the manual) is what leads us to think that it should be an element passed by reference. Sort(), ksort() and other functions have this same statement, but Current() was the only one I saw that was, say, "wrong"

  • Understood, it is because in these functions, as the next(), the position of the pointer is modified, but does not need to pass by reference, the function itself does it.

  • I will post an example in the answer.

  • I think that when I said "pass by reference" I had the argument that Current must be a variable with an array. I think I may have confused your answer, but speaking of "passing by reference", I refer to when you point out in the argument of a function with the operator &, indicating that there should be a mandatory variable in the parameter (which will be used by reference). I believe that is why it is called "passage". It is different from the reference by the attribution of =&.

  • Yes, that $var1 =& func(); is linked by reference.

  • In essence I think very much like you: how current does not modify the array (does not move the pointer), it does not generate the error. However, I think this does not occur because the function ceases to receive the argument by reference. For me it always receives. The others fail because the argument is not a variable, and it would make no sense to advance the pointer in these cases (see my answer for more details).

Show 5 more comments

11

Observing the behavior described by you makes it clear that this must be an error in the php manual. My suspicion is that as php uses the technique of Copy-On-Write, it only generates error when the pointer (referencia) of the array is modified.
In the case of the function current php is not changing the value of the pointer, just returning its position.

I think it’s interesting to open a bug-report in php and ask them to add a note to the manual, to make it clearer how the function works.

  • 1

    I think the manual gambit is here: "Every array has an internal pointer to the element". But the guys left it there mixed current(array &$array). There is no note that in versions higher than php 5.1 it behaves differently

  • we will follow https://bugs.php.net/bug.php?id=68995

7

I don’t think the manual is wrong, just incomplete. I’m not familiar enough with the PHP source code to be able to trace the problem to the point where the error message is sent, but I believe I have understood what happens.

The problem is not terms or not a reference; as the function is defined with &$array as a parameter, the argument it receives is always a reference to the array passed. I believe you’re emphasizing the wrong part of the error message:

Only variables can be passed by Ference

The key here is only variables, and not passed by Ference. In next([1, 2, 3]);, you do not pass a variable, pass a literal array. There is no reference to it outside the scope of the function next; once it returns, the reference count of the structure representing the array will be 0, and the memory is collected by the "garbage man".

It makes no sense for the functions that move the array pointer to want to change the state of an object that will cease to exist once it returns. Moving the pointer is an expendable operation, and they have a guard against it somewhere (I’m not sure where, but if you look at the source code they differ in one or two lines - examples: next and current). There are even tests to ensure that this use generates an error (example).

Note that the error does not occur if the array is assigned to a variable, and the variable is passed to the function:

next($var = [1, 2, 3]);

In that case, $var exists in the scope where the function was called, ie remains available after the call and cannot be claimed by Garbage Collector.

When you take the current value with current, this does not modify the array state; in this case, PHP sees no problems and lets it pass. Within my knowledge limitations regarding the implementation details of PHP, this is the evaluation I was able to do. Maybe I’m wrong, if anyone has evidence of that please let me know.

1


After a long time and even forgetting that question, I found the PHP staff response.

If I don’t quite understand the answer, help by editing it.

According to a certain [email protected]:

Non-iterator Objects are iterable like arrays, Mostly for BC reasons. This is expected behaviour, but I don’t think we should change the manual page to note that - effectively, it’ll be treated like an array regardless, and it’s confusing.

What translating is (google translator):

Non-interacting objects are rotating as matrices, mainly for reasons of reverse compatibility. This behavior is expected, but I don’t think we we should change the manual page. Note that it will be treated as a matrix anyway, and this is confusing.

  • Translators, make yourselves at home!

  • 4

    Confused is the answer he gave you :D

  • 1

    The answer is so confusing when the :D function

  • 3

    After reading it 10 times, I think I get it. It’s clear to you what he meant?

  • Explains what happens to current (correct), but it does not explain the question of the reference operator being there in the manual. That is, its explanation makes it clear that the manual is wrong

Browser other questions tagged

You are not signed in. Login or sign up in order to post.