Паттерн использования такой: идёт поток ивентов, среди них нужно учитывать только последний по какому-то id-полю. То есть пока я думал сделать LRU-кеш, переписывая по этому самому id-полю значения, при удалении из LRU считать объект "конечным", также при окончании ивентов всё, что внутри LRU считать конечным.
M-x customize-group
grep
В поле `grep-find-command` вместо
'("find . -type f -exec grep -nH -e {} +" . 34)
Ставьте:
'("find . -type f -exec cut -c1-2000 | grep -nH -e {} +" . 34)
Таким образом каждая линия будет обрезаться до первых 2000 символов при поиске. Мне лично это как раз то, что нужно.
Собственно, вопросы:
1. что делать?
2. есть ли "How to Design Programs" на русском?
3. насколько сумасшедшей считается идея попробовать перевести эту книгу на русский постепенно?
Спасибо!
изобилии фиговых интерфейсов можно будет сесть и за один-два вечера
наотправлять "пулл-реквестов" к любимым приложениям, которые будут
банально расставлять отступы, выравнивать шрифты ну и так
далее. Почему-то на андроиде это делать, видимо, очень сложно.
Драйвер редиса возвращает `Redis (Either Reply a)`. При операции `HGET` возвращает, соответственно, `Redis (Either Reply (Maybe ByteString))`, типа значения по ключу может и не быть. Программист для упрощения пишет сначала специальную функцию `redis'`, которая заворачивает ответ редиса в EitherT-based монаду, чтоб соединять подобные вычисления и возвращать первую неудачу: ``` newtype Redis' a = Redis' (EitherT Redis.Reply Redis.Redis a) deriving (MonadIO) instance Monad Redis' where return = Redis' . EitherT . return . Right (Redis' m) >>= f = Redis' $ m >>= \rv -> unwrapRedis' $ f rv redis' = Redis' . EitherT ``` Таким образом, теперь, если вы получаете ответ `Redis (Either Reply a)`, вы его преобразуете в ``` Redis' (EitherT Reply Redis a) ``` и можете соединять подобные вычисления в do-блоке типа: ``` do res <- redis' $ Redis.hget foo bar res2 <- redis' $ Redis.hget baz zab ``` и вычисление остановится на первом возврате ошибки. Далее. Программисту необходимо по кучке значений сделать `HGET` и вернуть это как-то внутри кортежа, поскольку мы внутри новой монады `Redis'` -- завернуть результат в неё. В случае, если значения хоть по одному ключу не существует, хочется вернуть `Nothing` для всех. Потому создаётся новая монада: ``` newtype HashFields a = HashFields (MaybeT Redis' a) deriving (Functor, Monad) instance Applicative HashFields where pure = return (<*>) = ap ``` описывающая вычисления типа `Redis'`, которые могут вернуть неудачу. Пишется новая функция ``` hashField = HashFields . MaybeT . redis' ``` способная завернуть результат неудачи в новую монаду, которая умеет останавливаться на первой неудаче. Также пишется специальная функция для `HGET`: ``` getField :: ByteString -- ^ Key -> ByteString -- ^ Hash field name -> HashFields String getField key field = fmap toString $ hashField $ Redis.hget key field ``` Также напишем функцию, которая "запустит" наше вычисление: ``` getRedisFields :: forall a. HashFields a -> Redis' (Maybe a) getRedisFields (HashFields f) = runMaybeT f ``` И теперь лёгким движением руки мы можем сделать что-то вроде: ``` getRedisFields ((,,,,,) <$> getField k "foo" <*> getField k "bar" <*> getField k "baz" <*> getField k "zab" <*> getField k "rab" <*> getField k "oof") ``` Вопрос: вам не кажется это "слишком"? Я пока еще не настолько просто манипулирую типами в голове, чтоб ощутить всю ситуацию, хорошо хоть в целом могу медленно прости по шагам по коду, но есть ощущение, что что-то здесь не так.
Spiderpig, Spiderpig, does whatever Spiderpig does!
(c) Чувак, отвечающий на критику Леннарта о том, что Убунту без
Системд обречены. // да, новые разборки, новые расколы и выяснения
отношений
gentooexperimental.org