За последние 24 часа нас посетили 15344 программиста и 1434 робота. Сейчас ищут 865 программистов ...

Передача по ссылке в функцию обратного вызова. Почему первый вариант работает а второй нет?

Тема в разделе "PHP для новичков", создана пользователем cycymora, 12 сен 2024.

  1. cycymora

    cycymora Активный пользователь

    С нами с:
    31 май 2021
    Сообщения:
    8
    Симпатии:
    0
    Чем ссылка в первом варианте лучше ссылки во втором и существует ли подобный первому способ передачи ссылки в функцию обратного вызова, но "более общепринятый, стандарнтый, понятный и т.п."?

    PHP:
    1. <?php
    2. $extLang = [
    3.     'rb' => 'Ruby',
    4.     '*.py' => 'Python',
    5.     '*.php' => 'PHP',
    6.     'js' => 'JavaScript',
    7. ];
    8.  
    9. array_walk($extLang, 'counter', [&$extLang]);
    10. function counter($item, $key, $arr): void
    11. {
    12.     if (is_string($item)) {
    13.         if (isset($arr[0][0]['maxItemLen'])) {
    14.             $len = strlen($item);
    15.             if ($len > $arr[0][0]['maxItemLen']) {
    16.                 $arr[0][0]['maxItemLen'] = $len;
    17.             }
    18.         } else {
    19.             $arr[0][0]['maxItemLen'] = strlen($item);
    20.         }
    21.     }
    22. }
    23.  
    24.  
    25. array_walk($extLang, 'counter2', $linkExtLang = &$extLang);
    26. function counter2($item, $key, $arr): void
    27. {
    28.     if (is_string($item)) {
    29.         if (isset($arr[0]['maxItemLen'])) {
    30.             $len = strlen($item);
    31.             if ($len > $arr[0]['maxItemLen']) {
    32.                 $arr[0]['maxItemLen'] = $len;
    33.             }
    34.         } else {
    35.             $arr[0]['maxItemLen'] = strlen($item);
    36.         }
    37.     }
    38. }
    39. var_export($extLang);
     
  2. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    485
    Симпатии:
    94
    Адрес:
    Бавария, Германия
    Добрый день!
    Вариант 1 лучше чем 2 потому, что 2 вариант не работает.
    Вашу функцию counter немного переделал.
    PHP:
    1. <?php
    2. echo "<pre>";
    3. $extLang = [
    4.     'rb' => 'Ruby',
    5.     '*.py' => 'Python',
    6.     '*.php' => 'PHP',
    7.     'js' => 'JavaScript',
    8. ];
    9.  
    10. array_walk($extLang, 'counter', [&$extLang]);
    11. /*
    12. function counter($item, $key, $arr): void
    13. {
    14.     if (is_string($item)) {
    15.         if (isset($arr[0][0]['maxItemLen'])) {
    16.             $len = strlen($item);
    17.             if ($len > $arr[0][0]['maxItemLen']) {
    18.                 $arr[0][0]['maxItemLen'] = $len;
    19.             }
    20.         } else {
    21.             $arr[0][0]['maxItemLen'] = strlen($item);
    22.         }
    23.     }
    24. }
    25. */
    26. function counter($item, $key, $arr): void
    27. {
    28.    arr[0][0]['maxItemLen'] = max( $arr[0][0]['maxItemLen'], strlen($item) );
    29. }
    30.  
    31. echo "1. Вариант<br>\$extLang ";
    32. print_r($extLang);
    33. $extLang = [
    34.     'rb' => 'Ruby',
    35.     '*.py' => 'Python',
    36.     '*.php' => 'PHP',
    37.     'js' => 'JavaScript',
    38. ];
    39.  
    40. array_walk($extLang, 'counter2', $linkExtLang = &$extLang);
    41. function counter2($item, $key, $arr): void
    42. {
    43.     if (is_string($item)) {
    44.         if (isset($arr[0]['maxItemLen'])) {
    45.             $len = strlen($item);
    46.             if ($len > $arr[0]['maxItemLen']) {
    47.                 $arr[0]['maxItemLen'] = $len;
    48.             }
    49.         } else {
    50.             $arr[0]['maxItemLen'] = strlen($item);
    51.         }
    52.     }
    53. }
    54. echo "2. Вариант<br>\$extLang ";
    55. print_r($extLang);
    56.  
    57. /*
    58. 1. Вариант
    59. $extLang Array
    60. (
    61.     [rb] => Ruby
    62.     [*.py] => Python
    63.     [*.php] => PHP
    64.     [js] => JavaScript
    65.     [0] => Array
    66.         (
    67.             [maxItemLen] => 10
    68.         )
    69.  
    70. )
    71.  
    72. 2. Вариант
    73. $extLang Array
    74. (
    75.     [rb] => Ruby
    76.     [*.py] => Python
    77.     [*.php] => PHP
    78.     [js] => JavaScript
    79. )
    80. */
    Удачи!
     
  3. cycymora

    cycymora Активный пользователь

    С нами с:
    31 май 2021
    Сообщения:
    8
    Симпатии:
    0
    У Вас отменное чувство юмора, однако :D. Я вот полтора часа потратил, чтобы понять почему не работает, но так и не понял...:(

    Чтож, опыт не пропьешь!

    И Вам удачи! Спасибо за ответ!
     
  4. cycymora

    cycymora Активный пользователь

    С нами с:
    31 май 2021
    Сообщения:
    8
    Симпатии:
    0
    Всеравно, к одной строчке не получится свести - т.к. в начале maxItemLen не существует, а в конце в strlen попадет массив:
    PHP:
    1. function counter($item, $key, $arr): void
    2. {
    3.     if (is_string($item)) {
    4.         if (!isset($arr[0][0]['maxItemLen'])) {
    5.             $arr[0][0]['maxItemLen'] = 0;
    6.         }
    7.         $arr[0][0]['maxItemLen'] = max($arr[0][0]['maxItemLen'], strlen($item));
    8.     }
    9. }
     
    #4 cycymora, 12 сен 2024
    Последнее редактирование: 12 сен 2024
  5. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    485
    Симпатии:
    94
    Адрес:
    Бавария, Германия
    Однако и одна строчка работает. Поставьте ради интереса error_reporting(E_ALL). Предупреждения не выдаются.
    Если и добавлять в функции проверку то достаточно только одну
    PHP:
    1. $arr[0][0]['maxItemLen'] = 0;
    2. array_walk($extLang, 'counter', [&$extLang]);
    3. function counter($item, $key, $arr): void
    4. {
    5.     if (is_string($item))
    6.         $arr[0][0]['maxItemLen'] = max($arr[0][0]['maxItemLen'], strlen($item));  
    7. }
     
    #5 Vladimir Kheifets, 12 сен 2024
    Последнее редактирование: 12 сен 2024
  6. Vladimir Kheifets

    Vladimir Kheifets Новичок

    С нами с:
    23 сен 2023
    Сообщения:
    485
    Симпатии:
    94
    Адрес:
    Бавария, Германия
    (дополнение)
    Если Вам требуется вычислить maxItemLen и при этом не обязательно применять функцию array_walk, то можно сделать так:
    PHP:
    1. $extLang = [
    2.     'rb' => 'Ruby',
    3.     '*.py' => 'Python',
    4.     '*.php' => 'PHP',
    5.     'js' => 'JavaScript',
    6. ];
    7.  
    8. $maxItemLen = max(array_map('counter', $extLang));
    9. function counter($item)
    10. {
    11.     return strlen($item);
    12. }
    13.  
    14. echo "maxItemLen = ", $maxItemLen;
    15. /*
    16. maxItemLen = 10
    17. */
    P.S. При этом массив исходых данных не будет переписан.
     
  7. cycymora

    cycymora Активный пользователь

    С нами с:
    31 май 2021
    Сообщения:
    8
    Симпатии:
    0
    Этот вариант мне и вправду нравится!
    Но, тогда логичнее написать просто:
    PHP:
    1. $maxItemLen = max(array_map('strlen', $extLang));
    Но по сути, я не ищу способа как обойти массив, а просто разбираюсь с языком. Вот дочитал я книжку до функции array_walk(). И вижу, что ей можно передать третий параметр. Стал размышлять на тему, каким этот параметр может быть, чтобы это было и вправду полезно. Возникла идея, что если бы был конвеер из array_walk(), то можно было бы подать на вход некоторый массив, и на нем что-то вычислить и получить результат. А при необходимости такой конвеер можно было бы легко перестраивать. Вот в этот момент и возникла мутная ситуация. Почему я в array_walk() могу сделать передачу внешнего массива по ссылке, только в том случае, если в качестве носителя этой ссылки будет массив? А если в качестве носителя ссылки будет переменная, то ничего не получается? Это какое-то особое поведение array_walk, или так в остальных подобных функциях? Чем ссылка сохраненная в переменной отличается от ссылки сохраненной в массиве? В общем, я надеюсь найти ответы на эти вопросы здесь на форуме. Заранее всем спасибо!