Ох нет, и вот почему: дело в том, что все шелы работают с историей в предположении, что никто, кроме них в файл с историей лазить не будет, поэтому ah поступает несколько хитрее, чем просто привязывается к номеру (к номеру из HISTFILE привязываться, конечно, можно, но это работает только с несколькими довольно жесткими предположениями). Поэтому синхронизация истории в отрыве от синхронизации HISTFILE — занятие бессмысленное. С тем же успехом можно просто rsync'ать ~/.ah :)
В общем, я пока просто не представляю, как это должно выглядить и работать.
Самым простым и предсказуемым образом, никакой магии :) Есть 3 флага для очистки. --all удаляет все-все, --keepLatest оставляет последние n выводов (хронологически), --olderThan удаляет все записи старше n дней.
function execute_with_ah {
BUFFER="ah t -- $BUFFER"
zle accept-line
}
zle -N execute_with_ah_widget execute_with_ah
bindkey '^J' execute_with_ah_widget
bindkey '^M' execute_with_ah_widget
Единственное, что останавливает: пока очень плохо работают приложения с ncurses. Ищу сейчас, каким образом можно их правильно запускать, но прогресса мало (в частности ah t -- htop лучше не делать).
Я как раз сейчас с этим экспериментирую (preexec в zsh и его эмуляция в bash), и на самом деле это изначальная цель. Но пока не все так гладко, особенно с bash'ем. В основном, все работает, но когда что-то отваливается, приходится мучительно все отключать и чесать голову, как подебажить. Так что пока без этого.
А чем Go лучше? В нем для реализации интерфейсов достаточно всего-навсего иметь методы с теми же сигнатурами. И все, считается, что структура реализует интерфейс. То есть никаких дополнительных телодвижений не нужно. Просто считайте, что наличие __iter__, например, говорит о том, что класс теперь Iterable. В этом случае, так как и там, и там в отношении подобных вещей duck typing, разницы принципиальной нет.
Не могу согласиться. go get настолько непродуман, что сообщество изобретает велосипеды один офигительнее другого. Зачем-то есть разница между работой со срезами (фундаментально, та же структура из интов), картами (тоже представляется в виде структуры) и своими struct'ами. Библиотеки для работы с текстом наводнены разными Do и DoString. Генерики имеют все шансы повторить историю своих «коллег» из Java. Мне сложно согласиться, что он тщательно продумывается, стандартная библиотека хоть и большая, но крайне неоднородная, часто приходится делать такие вещи, которые в 2014 уже не ожидаешь от нового языка.
А про недостаток синтаксического сахара: мой болевой порог тоже позволяет писать на Go, но при этом я не могу отделаться от мысли, что такая простота «хуже воровства».
Безусловно, сделать так, чтобы формально код заработал, несложно. Можно вернуть канал, можно вернуть срез. Я не про то: большая часть методов языка работает с интерфейсами. Использовать такой интерфейс, чтобы можно было итерировать свой объект нельзя. Использовать такой интерфейс, чтобы можно было, грубо говоря, использовать [] тоже. Квадратные скобки де-факто введены только для срезов и словарей. Интерфейс для работы с make отсутствует.
В языке есть несколько хороших средств, но их можно использовать только с заранее определенным набором сущностей, от этого возникает стойкое ощущение неконсистентности. Можно сказать, что да, есть примитивы, есть структуры, вот вам примитивы, определяйте свои структуры и используйте структуры как вам угодно. Но, черт побери, это же встроенные возможности языка.
Если бы язык был консистентный, то там был бы примитив, который можно итерировать, и работали бы с ним как с данностью. Все. Это было бы нормально. И массивы бы итерировали с помощью какого-нибудь .At(index int), и из словаря бы брали с помощью .Get(key interface{}). Язык был бы шумный, но не возникало бы подобного вопроса.
Кстати, в 1.5 GC собираются сделать намного более предсказуемым, чем есть сейчас. При идеальном раскладе возможно слегка просядет производительность, зато не будет внезапных stop the world.
Эта проблема, безусловно, решается, но все-таки хотелось бы иметь продуманную полноценную стандартную библиотеку. Сейчас она хороша только пока вы работаете с сетью, в остальном складывается ощущение, будто написана довольно хаотично и «чтобы было». Если посмотреть tech talk об истории языка, то не возникает ощущения, будто над многими вещами там и правда заморачивались.
Сторонние библиотеки пока сыры и плохо документированы. Обычные библиотеки документированы лучше, но чаще всего приходится лезть в исходники, чтобы понять, как оно на самом деле работает (например, редко когда по документации можно понять, как разобрать ошибку из кортежа). Но это — теоритически — еще можно поправить. А вот чего нельзя поправить, так это то, что со своими структурами зачастую нельзя работать как с теми, что идут вместе с языком. Хороший пример — это итерация.
В Go 4 разных синтаксиса для определения цикла for. Если вы итерируете стандартный срез, массив или мэп, то все ок. Но вот использовать те же конструкции для своих структур уже вряд ли получится.
Давайте пример:
type TreeNode struct {
Value interface{}
Left *TreeNode
Right *TreeNode
}
type BinaryTree struct {
Root *TreeNode
}
Думаю, понятно, что здесь происходит. Структуры определили, давайте теперь попробуем прицепить к ним методы, чтобы можно было делать вот так:
for node := range tree.InOrder() {
fmt.Println(node)
}
for node := range tree.PreOrder() {
fmt.Println(node)
}
Думаю, понятно, что здесь должно происходить. Так вот, так делать нельзя. Вы не можете использовать range таким образом. Приходится явным образом доставать итератор и итерировать его вот так:
iterator := tree.PreOrderIterator()
for iterator.HasNext() {
fmt.Println(iterator.Extract())
}
Или функция make. Отличная функция, инициализирующая неявные структуры, с которыми работают срезы или словари. О, мы только что написали свою суперкрутую структуру, довольно сложную в инициализации, хочется создавать ее тем же образом, что и тот же словарь (например, написали свой Set). Ничего подобного сделать нельзя.
Поэтому со всеми бибилиотеками контейнеров не получится работать всеми средствами языка, инициализировать аналогичным с теми же срезами или картами образом не получится. И это только один пример. А ведь еще есть отсутствие генериков, принуждающее (!!!) копипастить, еще есть абсолютно наколеночный go get, про который во времена PyPI, Gem'ов или npm'ов вообще говорить стыдно.
Какое в Go стандартное средство для dependency management'а? Так ведь нет его фактически. Роб Пайк сказал, что им и этого хватает, пускай коммьюнити пишет. Комьюнити написало Godep, GPM, еще какие-то поделки есть. Но единого способа, единообразной экосистемы в Go просто не существует. Зато есть вот такой костылина.
Я сейчас пишу и на том, и на том; к Go у меня смешанные чувства. Пока что я его вижу как отличный язык для написания небольших демонов, работающих с сетью. В остальных отношениях от него постоянно возникает неприятное ощущение недоделанности, непродуманности какой-то, даже не знаю, как лучше выразиться.
По уровням абстракции он очень несбалансированный: например, сопрограммы реализованы довольно хорошо и удобно, а вот кроссплатформенное получение кода возврата от процессов, запущенных через exec.Command, уже заставляет писать несколько файлов под разные ОС. Довольно простая работа с http, но какая-нибудь другая область применения — и вот уже танцуешь с syscall. Обрабатываешь очередной назойливый err, и кажется, что просто взяли старый-добрый C, и натянули на него какое-то хипстерское шмотье.
Никак не могу отделаться от ощущения, что это какой-то DSL для написания всяких сетевых штук.
У меня нет админского опыта (я разработчик), возможно что-то делал неправильно, но в моем случае мне показалось, что так просто избавиться от засорения системы с помощью Docker'а не получается. Такая ситуация: приложение с большим количеством зависимостей, регулярно обновляющихся. Обновить их в одном контейнере — задача несложная. Однако если контейнер нужно разворачивать еще где-то еще (скажем, для масштабирования), то приходится мейнтейнить еще и Dockerfile с реестром, то есть делать одно и то же в разных местах. Если держать эти зависимости в прямо в контейнерах, то при откате версии в случае беды, надо бы накатить пропущенные security-апдейты. После пары таких случаев подмывает держать их на монтируемом томе. А и данные нужно где-то хранить, подключаешь другой том. И сидишь, думаешь, что что-то идет не так: вроде и контейнеризация, а возни только прибавилось.
Я смотрел на Docker больше как на средство дистрибуции не пакетов даже, а системы из нескольких связанных процессов (не Docker-way, само собой, но как способ упростить нетривиальный деплой). Собственно, мой первый вопрос был вызван тем, что по какой-то причине я был свято убежден, что с приходом libcontainer проблему подключения к любому контейнеру начали каким-то образом решать. Ну окей, не lxc-attach, так nsenter :(
Вот это меня и печалит: вроде бы и новое поколение контейнеров (если предыдущими считать OVZ или джейлы FreeBSD), а проблема так и не решена. Даже более того, раз появляются подобные инструменты, то это как бы и не проблема, а фича. Ernillew в общем, прав, я не очень понимаю, почему вокруг Docker стоит такой шум.
Отлично. SSH нам незачем, если можно влезать в чужие namespace. Получается, я таким образом могу влезать в те контейнеры, к внутренностям которых мне изначально никто доступа не давал?
Они еще там же объявили о том, что разработка будет вестись подобно тому, как разрабатывается разрабатывается Firefox или Chrome: 3 канала с шестинедельными итерациями. Стабильный релиз каждые 6 недель.
HISTFILE
привязываться, конечно, можно, но это работает только с несколькими довольно жесткими предположениями). Поэтому синхронизация истории в отрыве от синхронизацииHISTFILE
— занятие бессмысленное. С тем же успехом можно просто rsync'ать~/.ah
:)В общем, я пока просто не представляю, как это должно выглядить и работать.
--all
удаляет все-все,--keepLatest
оставляет последние n выводов (хронологически),--olderThan
удаляет все записи старше n дней.Единственное, что останавливает: пока очень плохо работают приложения с ncurses. Ищу сейчас, каким образом можно их правильно запускать, но прогресса мало (в частности
ah t -- htop
лучше не делать).preexec
в zsh и его эмуляция в bash), и на самом деле это изначальная цель. Но пока не все так гладко, особенно с bash'ем. В основном, все работает, но когда что-то отваливается, приходится мучительно все отключать и чесать голову, как подебажить. Так что пока без этого.__iter__
, например, говорит о том, что класс теперьIterable
. В этом случае, так как и там, и там в отношении подобных вещей duck typing, разницы принципиальной нет.Всегда есть больше 1 способа :)
go get
настолько непродуман, что сообщество изобретает велосипеды один офигительнее другого. Зачем-то есть разница между работой со срезами (фундаментально, та же структура из интов), картами (тоже представляется в виде структуры) и своимиstruct
'ами. Библиотеки для работы с текстом наводнены разнымиDo
иDoString
. Генерики имеют все шансы повторить историю своих «коллег» из Java. Мне сложно согласиться, что он тщательно продумывается, стандартная библиотека хоть и большая, но крайне неоднородная, часто приходится делать такие вещи, которые в 2014 уже не ожидаешь от нового языка.А про недостаток синтаксического сахара: мой болевой порог тоже позволяет писать на Go, но при этом я не могу отделаться от мысли, что такая простота «хуже воровства».
[]
тоже. Квадратные скобки де-факто введены только для срезов и словарей. Интерфейс для работы сmake
отсутствует.В языке есть несколько хороших средств, но их можно использовать только с заранее определенным набором сущностей, от этого возникает стойкое ощущение неконсистентности. Можно сказать, что да, есть примитивы, есть структуры, вот вам примитивы, определяйте свои структуры и используйте структуры как вам угодно. Но, черт побери, это же встроенные возможности языка.
Если бы язык был консистентный, то там был бы примитив, который можно итерировать, и работали бы с ним как с данностью. Все. Это было бы нормально. И массивы бы итерировали с помощью какого-нибудь
.At(index int)
, и из словаря бы брали с помощью.Get(key interface{})
. Язык был бы шумный, но не возникало бы подобного вопроса.Сторонние библиотеки пока сыры и плохо документированы. Обычные библиотеки документированы лучше, но чаще всего приходится лезть в исходники, чтобы понять, как оно на самом деле работает (например, редко когда по документации можно понять, как разобрать ошибку из кортежа). Но это — теоритически — еще можно поправить. А вот чего нельзя поправить, так это то, что со своими структурами зачастую нельзя работать как с теми, что идут вместе с языком. Хороший пример — это итерация.
В Go 4 разных синтаксиса для определения цикла
for
. Если вы итерируете стандартный срез, массив или мэп, то все ок. Но вот использовать те же конструкции для своих структур уже вряд ли получится.Давайте пример:
Думаю, понятно, что здесь происходит. Структуры определили, давайте теперь попробуем прицепить к ним методы, чтобы можно было делать вот так:
Думаю, понятно, что здесь должно происходить. Так вот, так делать нельзя. Вы не можете использовать
range
таким образом. Приходится явным образом доставать итератор и итерировать его вот так:Или функция
make
. Отличная функция, инициализирующая неявные структуры, с которыми работают срезы или словари. О, мы только что написали свою суперкрутую структуру, довольно сложную в инициализации, хочется создавать ее тем же образом, что и тот же словарь (например, написали свойSet
). Ничего подобного сделать нельзя.Поэтому со всеми бибилиотеками контейнеров не получится работать всеми средствами языка, инициализировать аналогичным с теми же срезами или картами образом не получится. И это только один пример. А ведь еще есть отсутствие генериков, принуждающее (!!!) копипастить, еще есть абсолютно наколеночный
go get
, про который во времена PyPI, Gem'ов или npm'ов вообще говорить стыдно.Какое в Go стандартное средство для dependency management'а? Так ведь нет его фактически. Роб Пайк сказал, что им и этого хватает, пускай коммьюнити пишет. Комьюнити написало Godep, GPM, еще какие-то поделки есть. Но единого способа, единообразной экосистемы в Go просто не существует. Зато есть вот такой костылина.
По уровням абстракции он очень несбалансированный: например, сопрограммы реализованы довольно хорошо и удобно, а вот кроссплатформенное получение кода возврата от процессов, запущенных через
exec.Command
, уже заставляет писать несколько файлов под разные ОС. Довольно простая работа с http, но какая-нибудь другая область применения — и вот уже танцуешь сsyscall
. Обрабатываешь очередной назойливыйerr
, и кажется, что просто взяли старый-добрый C, и натянули на него какое-то хипстерское шмотье.Никак не могу отделаться от ощущения, что это какой-то DSL для написания всяких сетевых штук.