scandir
порядки по возрастанию или убыванию в алфавитном порядке. Но вы хотите отсортировать по дате последнего изменения. Так что вам нужно применить функцию сортировки к нему. Например, вы можете сделать это с помощью filemtime
и uasort
$items = glob ...
uasort($items, function($a,$b) { return filemtime($a) > filemtime($b); })
Отразить filemtime($a) > filemtime($b)
в filemtime($a) < filemtime($b)
для asc / desc http://php.net/manual/en/function.scandir.php#refsect1-function.scandir-parameters
Вероятно, это скорее вопрос стиля, чем что-либо еще. Лично я бы поставил
_ -> error "Impossible! Empty list in step"
, лишь бы отключить предупреждение :)
Чтобы прокомментировать мой предыдущий комментарий, я понял, что есть способ подтвердить пропущенный случай, но все же получить полезную ошибку с номером файла / строки. Однако он не идеален, так как будет отображаться только в неоптимизированных сборках (см. здесь ).
...
[]:xs -> assert False (error "unreachable because I know everything")
В этом особом случае вы можете устранить предупреждение, выполнив следующие действия:
gb_groupBy p input = foldr step [] input
where
step item acc = case acc of
[] -> [[item]]
(xs:xss) -> if p (head xs) item
then (item:xs):xss
else [item]:acc
Сопоставление с образцом завершено, и «невозможное» условие пустого списка в заголовке аккумулятора будет вызывают ошибку времени выполнения, но не предупреждают.
Другой способ взглянуть на более общую проблему неполных сопоставлений с образцом - рассматривать их как «запах кода», то есть признак того, что мы пытаемся решить проблему неоптимальным образом. , или не-Haskellish, способом, и попробуйте переписать наши функции.
Реализация groupBy с помощью foldr делает невозможным применение его к бесконечному списку, что является целью разработки, которую функции Haskell List пытаются достичь везде, где семантически разумно , Рассмотрим
take 5 $ groupBy (==) someFunctionDerivingAnInfiniteList
Если первые 5 групп относительно равенства конечны, ленивое вычисление прекратится. Это то, что ты можешь » Не делайте этого на строго оцененном языке. Даже если вы не работаете с бесконечными списками, написание таких функций даст лучшую производительность для длинных списков или позволит избежать переполнения стека, которое происходит при оценке выражений типа
take 5 $ gb_groupBy (==) [1..1000000]
В List.hs groupBy равно реализовано следующим образом:
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs
Это позволяет интерпретатору / компилятору оценивать только те части вычисления, которые необходимы для получения результата. span дает пару списков, где первый состоит из (последовательных) элементов из заголовка списка, удовлетворяющих предикату, а второй - остальная часть списка. Он также реализован для работы с бесконечными списками.
Я считаю, что проверка полноты по шаблонам случаев обязательна. Я стараюсь никогда не использовать _
в случае на верхнем уровне, потому что _
соответствует всему, и, используя его, вы подрываете ценность проверки полноты. Это менее важно для списков, но критически важно для определяемых пользователем алгебраических типов данных, потому что я хочу иметь возможность добавить новый конструктор и отключить компилятор для всех отсутствующих случаев. По этой причине я всегда компилирую с включенным -Werror
, поэтому я не могу исключить случай.
Как уже отмечалось, ваш код может быть расширен с помощью этого случая
[] : _ -> error "this can't happen"
Внутренне, GHC имеет функцию паники
, которая, в отличие от error
, выдает координаты источника, но я посмотрел на реализацию и не смог понять ее.
Система типа - ваш друг, и предупреждение о том, чтобы вы знали, что ваша функция имеет трещины. Очень лучший подход - пойти на более чистый, более элегантный посадку между типами.
Рассмотрим определение ГКГ Groupby
:
groupBy :: (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy eq (x:xs) = (x:ys) : groupBy eq zs
where (ys,zs) = span (eq x) xs