1.82K subscribers
3.31K photos
132 videos
15 files
3.58K links
Блог со звёздочкой.

Много репостов, немножко программирования.

Небольшое прикольное комьюнити: @decltype_chat_ptr_t
Автор: @insert_reference_here
Download Telegram
😏 Проказа детей
💀 Проказа у детей
👍2
Я: прошу принести два кусочка хлеба

Хлеб:
😁6
Forwarded from Сколопендра.Шитпостинг (Александра Малютина)
Инверсия копипасты про тян #2: Эх, как же хочется массивную, загорелую, высокую, опытную в с*ксе, целованную, с накачанными руками, большими ступнями, бритую налысо альфу, успешную, с кучей друзей и подруг, открытую экстровертку, дабы вместе с ней участвовать в приятном социуме.
👍7💩3❤‍🔥2🤮2😭2
I don't use Arch BTW
🤡26👎14🤮65💔3👍2
🍌13😁1💩1
Блог*
Документация Go: "Go — простой язык, в нём есть только один цикл: for". Тем временем for: - Безусловный цикл - Цикл с предусловием - Цикл в стиле C - Цикл по слайсу - Цикл по строке - Цикл по мапе - Цикл по каналу
#prog #go

Тем временем в Go предложили сделать цикл по функциям (и по числам, но сегодня речь не об этом). Если конкретно — по функциям вида func(yield func(T1, T2) bool) bool (а также func(yield func(T) bool) bool и func(yield func() bool) bool). Эти функции принимают тело цикла в виде функции, которая принимает на вход очередную переменную итерации и возвращает, нужно ли продолжать итерирование. Реализовывать это предлагают в виде синтаксической трансформации: код вида

for k, v := range iterfunc {
// body
}

преобразовывать в

iterfunc(func (k K, v V) bool {
// body
return true
})

То есть реализовывать push-итератор (или, иначе, внутренняя итерация). Ввиду того, что в Go синтаксис вызова метода без скобок генерирует замыкание, захватывающее значение перед точкой, это делает возможным использование циклов для итераторов коллекций:

for elem := range collection.Iter {
// ...
}

Выглядит вроде просто, но такой подход порождает кучу дизайн-вопросов. Окей, break транслируется в return false, а continue — в return true. Но вот что делать с return в теле цикла? С goto (да, он есть в Go)? С defer (особенно, если там внутри recover)? Последнее, кстати, вызвало больше всего вопросов в обсуждении. Да, это возможно всё проделать (более того, тестовая реализация, покрывающая всё это, уже есть), но семантика в этом случае вызывает вопросы. В частности:

* а как вообще отличается возврат из yield за счёт достижения конца итерации и за счёт return из функции, в которой цикл?
* что делать, если функция-итератор игнорирует возвращаемое значение yield?
* нормально ли это вообще, что при исполнении break может исполниться некий произвольный код, то есть итерация не обязательно будет немедленно завершена?
* что делать, если yield (который, я напомню, может включать в себя нелокальный control flow) утекает и вызывается вне цикла?
* можно ли сделать генерируемые компилятором проверки на подобное поведение без того, чтобы угробить перформанс из-за убогости Go-шного инлайнера?
* должны ли средства для инспектирования стека из пакета runtime показывать фреймы функции-итератора?

Всех этих проблем лишены pull-итераторы (aka внешняя итерация) — функции вида func () (T, bool). Они реализуемы на Go уже сейчас, они не требуют изменения языка¹, без проблем позволяют использовать весь control flow. А ещё — хотя я упоминания этого в обсуждении предложения не видел — позволяют сделать zip на итераторах (что на pull-итераторах, кажется, вообще не реализуемо (хммммм)). Наверное, можно подумать, что подобные итераторы уже предлагали к реализации. И вы абсолютно правы!

Но то обсуждение застопорилось по ряду причин.

Первая проблема — итерация с возможными ошибками. Честно, вот это как раз меньшая из проблем — можно было бы просто сделать стандартный обобщённый тип для пары (значение, ошибка), что и так используется в коде на Go (а ещё лучше, чтобы можно было использовать деструктуризацию — добавить наконец в язык настоящие кортежи вместо недоразумения под названием multiple function return values).

Вторая проблема — освобождение ресурсов после итерации — скажем, для итератора по содержимому файла или по результату SQL-запроса (для push-итераторов это не проблема, поскольку они могут исполнять произвольный код после вызова yield). Это вызвало кучу обсуждения на тему того, как это реализовать. В частности: нужен ли метод Stop() в интерфейсе итератора или вынести в отдельный интерфейс, кто и как должен этот метод вызывать, можно ли просто использовать io.Closer для семантики очистки ресурсов...

В конечном счёте это обсуждение просто закрыли.

Для сравнения, в языках без GC (читай, C++ и Rust) для очистки используется RAII, а в языках с GC есть средства для явного автоматического закрытия по выходу из области видимости: try-with-resources и AutoCloseable в Java, using и IDisposable в C#, with и context manager в Python. В Go есть... Финализаторы. Которые не без своих проблем (1, 2), главная из которых — они не дают никаких гарантий по тому, когда будут выполнены.
👍4🤣4🤮1
Блог*
Документация Go: "Go — простой язык, в нём есть только один цикл: for". Тем временем for: - Безусловный цикл - Цикл с предусловием - Цикл в стиле C - Цикл по слайсу - Цикл по строке - Цикл по мапе - Цикл по каналу
И да, я кое о чём умалчивал до этого момента. Было обсуждение, которое рассматривало и pull-, и push-итераторы. Но реализовать Russ Cox в итоге решил push-итераторы.

Воистину, проклятый язык.

¹: хотя без языковой интеграции их использование выглядит немного неловко:

for e, _ok := it.Next(); _ok; e, _ok = it.Next() {
// statements
}
👍5🤡3
Блог*
Сасный супермаркет
Интересно. Ценники все, разумеется, на армянском. Но вот на этикетках-наклейках на развесную продукцию (фрукты, овощи, готовая еда) название написано на русском
Блог*
I don't use Arch BTW
😁24🤡4❤‍🔥1👌1
#meme про рычаг
😁13👍1👎1
Приснилось, что я форкнул Go и добавил в него иммутабельность. К чему бы это?
👍10😁71🤔1
😒🤚 Завязывать узлы на шнурках
😏👉 Завязывать узлы на типах
💩5
Forwarded from Обратная сторона Луны (Луна)
🤮64💩4🤡2🤔1
До сих пор канал Вафеля цитирует Блог* больше, чем другие цитирующие Блог* каналы, а канал Вафеля — самый цитируемый в Блог*е
🤔3😐1
#prog #go

Go не разрешает битовые сдвиги для чисел с плавающей точкой. Например, следующая программа не компилируется:

package main

import "fmt"

func shift(x float32) float32 {
return x << 3
}

func main() {
fmt.Println(shift(1.0))
}

С ошибкой:

./prog.go:6:9: invalid operation: shifted operand x (variable of type float32) must be integer

Разумеется, если удалить функцию и заинлайнить её по месту вызова, то поведение не должно измениться:

package main

import "fmt"

func main() {
fmt.Println(1.0 << 3)
}

И это выдаёт... Ан не, не выдаёт никакой ошибки — компилируется и печатает 8.

Может, для константных выражений в Go исключение? Попробуем поменять 1.0 на 1.1:

./prog.go:6:14: invalid operation: shifted operand 1.1 (untyped float constant) must be integer

Спасибо, Go, очень полезно /s
🔥10🤡7👌1