Comments 56
У меня есть один вопрос к разработчикам на php. Ребята, объясните мне, почему вы называете словарь (отображение ключей на значения) массивом? Этот вопрос терзает меня уже долгие годы и я никак не найду на него ответ. В том же пайтоне, эти вещи честно называются словарями, списками и т.д. И это единственный язык, в процессе изучения которого, я не понимал, почему тернарный вопросик возвращает мне не то, что нужно. Ах да, потому, что он тут работает с заду на перед.
И это, наверное, единственный язык, который при выходе за пределы так называемого массива создает недостающий элемент и воспринимает его как null тем самым завершая цикл.
Да, прошу прощения, накипело.
И это, наверное, единственный язык, который при выходе за пределы так называемого массива создает недостающий элемент и воспринимает его как null тем самым завершая цикл.
Да, прошу прощения, накипело.
Не ради троллинга php, но мне тоже интересно почему было принято такое решение. Думаю для этого были какие-то причины.
Если вы про тернарный оператор, то вот здесь есть обсуждение.
Я вот и не подозревал о том, что такое может случиться, просто потому что привык для собственного удобства чтения везде ставить скобки.
Я вот и не подозревал о том, что такое может случиться, просто потому что привык для собственного удобства чтения везде ставить скобки.
Трудно, наверное, когда название чего-то приносит страдания долгие годы.
Что же они творят-то, бесстыдники-создатели php!
Что же они творят-то, бесстыдники-создатели php!
Потому что в PHP «массив» является одновременно массивом и упорядоченным словарем. Позволяет не плодить лишних сущностей. По-моему, это очень удобная фишка, которую другие языки (тот же JS) не поддерживают.
Сам термин «массив», наверное, не слишком точный, но тут уж ничего не поделаешь, таков PHP ;).
Сам термин «массив», наверное, не слишком точный, но тут уж ничего не поделаешь, таков PHP ;).
Я думаю, потому, что для его создания используется ключевое слово
array
. Хотя согласен, это не массив в привычном понимании.А что не устраивает собственно в названии «массив»?)
Все структуры, которые Вы перечислили имеют одну общую черту: «упорядоченное отображение, которое устанавливает соответствие между значением и ключом», почему бы не назвать все это одним словом по самой элементарной структуре данных — «Массив»?)
И, кстати, зря Вы упомянули пайтон, потому что я ни разу не встречал человека, который знает все встроенные типы данных(http://docs.python.org/2/library/datatypes.html), а вот любой программист PHP прекрасно их знает(http://php.net/manual/ru/language.types.php).
Все структуры, которые Вы перечислили имеют одну общую черту: «упорядоченное отображение, которое устанавливает соответствие между значением и ключом», почему бы не назвать все это одним словом по самой элементарной структуре данных — «Массив»?)
И, кстати, зря Вы упомянули пайтон, потому что я ни разу не встречал человека, который знает все встроенные типы данных(http://docs.python.org/2/library/datatypes.html), а вот любой программист PHP прекрасно их знает(http://php.net/manual/ru/language.types.php).
UFO just landed and posted this here
«Встроенные» — это __builtins__
>>> [item for item in dir(__builtins__)
... if isinstance(getattr(__builtins__, item), type) and item.lower() == item]
['bool', 'bytearray', 'bytes', 'classmethod', 'complex', 'dict', 'enumerate', 'filter', 'float', 'frozenset', 'int', 'list', 'map', 'memoryview', 'object', 'property', 'range', 'reversed', 'set', 'slice', 'staticmethod', 'str', 'super', 'tuple', 'type', 'zip']
А почему в Perl его называют HASHем не возникает вопрос?
Наверное потому что ru.wikipedia.org/wiki/%C0%F1%F1%EE%F6%E8%E0%F2%E8%E2%ED%FB%E9_%EC%E0%F1%F1%E8%E2
Читаем определение, дочитываем до конца и делаем выводы
Наверное потому что ru.wikipedia.org/wiki/%C0%F1%F1%EE%F6%E8%E0%F2%E8%E2%ED%FB%E9_%EC%E0%F1%F1%E8%E2
Читаем определение, дочитываем до конца и делаем выводы
Потому что в PHP и словари, и просто массивы заводятся с помощью ключевого слова array.
И обычный массив в PHP — это словарь, ключи, которого индексы.
И в словарь, который на самом деле словарь, можно сделать команду push в PHP.
И обычный массив в PHP — это словарь, ключи, которого индексы.
И в словарь, который на самом деле словарь, можно сделать команду push в PHP.
foreach работает со всем, что поддерживает интерфейс Traversable: с массивами, с простыми объектами (где перечисляются доступные свойства) и с Traversable-объектами (вернее, объектами, у которых определен внутренний обработчик get_iterator)Эта формулировка явно смущает, ведь ни массивы, ни простые объекты не поддерживают Traversable.
(Для проверки достаточно попробовать передать значение в
iterator_to_array
или применить instanceof
.)В оригинале это звучит так: "foreach works with all kinds of traversables".
Тут я, скорее всего, плохо перевел. Какую формулировку предложили бы вы?
Тут я, скорее всего, плохо перевел. Какую формулировку предложили бы вы?
В оригинале слово traversable используется в общем смыле. Перевести можно, например, так:
"
Меня оригинальная фраза тоже смущает, но по другой причине. В ней «разнообразные» применяется к набору всего лишь из двух: массивы и объекты.
"
foreach
поддерживает значения разных типов, например, обычные массивы, обычные объекты, объекты, поддерживающие Traversable
".Меня оригинальная фраза тоже смущает, но по другой причине. В ней «разнообразные» применяется к набору всего лишь из двух: массивы и объекты.
Level up! Предупреждён — значит, вооружён.
Лично у меня в голове отложилось только одно: чтобы не попасть в непонятное, надо всеми силами избегать модифицирования обходимого через foreach массива. Но таки да, во всем этом видна определенная логика, о наличии которой я раньше и не подозревал.
Эмпирически выведенный закон «хочешь действительно понять фреймворк — читай не документацию, а его код» применим и к языкам программирования.
Мне лично вообще трудно себе представить задачу, в которой может понадобиться модифицировать массив при обходе.
Мне кажется, что в 90% случаев foreach используется для чтения данных из массива
Мне кажется, что в 90% случаев foreach используется для чтения данных из массива
почему, такие ситуации легко представить
хотя я бы в них использовал while
массив не меняется — foreach
меняется — while
хотя я бы в них использовал while
массив не меняется — foreach
меняется — while
В PHP — и правда, сложно представить. Но такие задачи часто встречаются, например, при написании игр. Простейший пример: по экрану разбросаны квадраты, при нажатии на любой он взрывается. Тогда у нас получится цикл по коллекции объектов на экране, каждая итерация которого проверяет нажатие для конкретного объекта, и если оно успешно — сам объект удаляется из коллекции, зато добавляются новые (спрайт взрыва и искры).
тогда у нас получится цикл по коллекции объектов на экране, каждая итерация которого проверяет нажатие для конкретного объекта, и если оно успешно
OMG! это еще хуже, чем изменять массивы в цикле на php. Для этого существуют эвенты у каждого объекта и их обработчики. Представьте, что у вас 100к таких объектов? Цикл по всем и перестройка? Да ну нафиг-нафиг.
Почему нельзя сделать это через for?
Дело в том, что с объектами удобнее работать, когда они не просто валяются в общем массиве, но сгруппированы. Сложный объект из нескольких составных частей, которые должны двигаться вместе, удобне представить в виде группы объектов, которая имеет общую точку, относительно которой позиционируются вложенные объекты. В таком случае у нас получается по вложенному циклу на каждый такой сгруппированный объект, и понять, какой индекс цикла нужно ручками подкрутить на единицу вверх или вниз, становится абсолютно невозможно.
В этом случае не стоило бы явно прописать итератор для объекта?
Например?
Я говорю о том, чтобы руками указать, в каком порядке и каким образом foreach следует обходить вашу коллекцию.
p.s. Хотя не вполне понимаю, что мы тут обсуждаем. Сдается мне, врядли вы собираетесь писать такого рода игру на PHP, так что как он пытается защитить итератор от перезаписи тут уже не так важно.
p.s. Хотя не вполне понимаю, что мы тут обсуждаем. Сдается мне, врядли вы собираетесь писать такого рода игру на PHP, так что как он пытается защитить итератор от перезаписи тут уже не так важно.
Ужас, психоделическая картина, коллизии, шизофрения. Опасно работать программистом!
Не ради холивара, но все-таки не могу не сказать, что в C# обход коллекций сделан куда более логично и понятно. Никаких «внутренних индексов массива» нет. На каждый обход последовательности создается специальный объект — итератор, который хранит в себе текущий индекс и удаляется после окончания обхода. Если последовательность была изменена во время обхода, итератор бросает исключение.
Простите, что не в тему, но уже неоднократно сталкиваюсь с проблемой count, когда нет массива(переменной) или он пустой отрабатывает на true. Может кто сталкивался, в чём подвох не могу понять, заранее спасибо.
В каком смысле true? Он же целое число возвращает. На пустой массив или на null он возвращает 0.
Прочтите внимательней документацию. count (array ()) = 0, count (false) = 1
Давно уже не объявлять переменные считает дурным стилем.
Добавление $arr = array(); во первых много времени не занимает, во вторых как способ принудительной типизации тоже неплохо
Добавление $arr = array(); во первых много времени не занимает, во вторых как способ принудительной типизации тоже неплохо
Может Вам empty подойдёт?
наверно потому что он конвертит не массив в массив с одним елементом а потом считает.
use count((array)$any_data)
:^ ) Дык в этом то и соль, что так нельзя.
var_dump((array)false);
// array (size=1)
// 0 => boolean false
echo count((array)false); // 1
Ну да, я имел ввиду что false это тоже что-то, в отличии от null и хпх пытается превратить это в массив что бы посчитать. Немного криво, согласен, но логика ясна хотя бы
PHP может падать с segfault?
А можно поподробнее про
Это потому что ключ FYFY имеет коллизию с EzFY (вообще-то, все ключи из этого массива тоже)
Подозреваю, что подробности следует искать здесь:
github.com/php/php-src/blob/master/Zend/zend_hash.h
github.com/php/php-src/blob/master/Zend/zend_hash.h
Меня интересует, когда коллизии могут проявлять себя.
Например isset() выдает всё корректно на приведенных ключах.
Например isset() выдает всё корректно на приведенных ключах.
Да, про это я в курсе.
Я не понял про совпадение адресов. Ведь при совпадении хешей все равно сравниваются точные значения ключей.
Я не понял про совпадение адресов. Ведь при совпадении хешей все равно сравниваются точные значения ключей.
Я не знаток внутренностей, но по первой ссылке написано:
For those who don’t know how hashtables work: When you write $array[$key] in PHP the $key is run through a fast hash function that yields an integer. This integer is then used as an offset into a “real” C array (here “array” means “chunk of memory”).
Because every hash function has collisions this C array doesn’t actually store the value we want, but a linked list of possible values. PHP then walks these values one by one and does a full key comparison until it finds the right element with our $key.
Ну любой хеш так работает (либо я чего-то не знаю). Как я и написал выше:
>>PHP then walks these values one by one and does a full key comparison until it finds the right element
После грубого сравнения хешей (была найдена нужная линия хеша) идет уже точное сравнение значений в пределах связного списка в найденной линии.
Может работать меденно? Да. находить не то? Как? Мне вот не понятно всё еще.
Один вариант: unset освобождает один из элементов линии хеша, и в ту же ячейку записывается новое (другое) значение при присвоении. В итоге внешняя ссылка на эту ячейку остается корректной. Но это имхо.
Да и все равно я такой код, как в примерах статьи, не пишу. И не сталкивался с подобным.
>>PHP then walks these values one by one and does a full key comparison until it finds the right element
После грубого сравнения хешей (была найдена нужная линия хеша) идет уже точное сравнение значений в пределах связного списка в найденной линии.
Может работать меденно? Да. находить не то? Как? Мне вот не понятно всё еще.
Один вариант: unset освобождает один из элементов линии хеша, и в ту же ячейку записывается новое (другое) значение при присвоении. В итоге внешняя ссылка на эту ячейку остается корректной. Но это имхо.
Мне кажется, я нашел еще на эту тему, причем из недавнего:
habrahabr.ru/post/162685/
habrahabr.ru/post/162685/
Расскажите подробнее про коллизию хеша из самого последнего примера. У меня шок. Мне страшно дальше писать код!
Sign up to leave a comment.
О тонкостях работы foreach в PHP