Roman
Как все сложно.
что конкретно сложно?
Roman
Do you speak English?
йес, сори, просто лень переводить, я думаю тут не такой сложный текст чтоб его сложно было понять 🙂
Zver
что конкретно сложно?
Читать это месиво сложно и просто в нем запутаться.
Pavel
Честно говоря, даж не хочется поднимать ещё раз тему констов. Но меньше боилер плейта — лучше.
Pavel
это не константы) или ты про keyword?
Да просто раскладку ради пяти букв лень переключать.
Roman
Читать это месиво сложно и просто в нем запутаться.
либо так, либо опасные мутабельные указатели везде..
Roman
Честно говоря, даж не хочется поднимать ещё раз тему констов. Но меньше боилер плейта — лучше.
если ты про const как boilerplate, то сейчас boilerplate это копирование, копирование, копирование. Представленный вариант boilerplate'а служит чисто ради безопасности и я вляется меньшим злом по сравнению с копированием =)
Zver
Я родился во времена ассемблера, поэтому мне мутабельность кошернее, чем это аля раст нечитаемое месиво.
Dorian
Roman
Я родился во времена ассемблера, поэтому мне мутабельность кошернее, чем это аля раст нечитаемое месиво.
возможно проблема "неприязни" связана с тем, что большинство людей на Go ещё не пишут большие проекты с большими командами и огромной кодовой базой (> 50k LOC как минимум) написать 1 человеку небольшой CLI automation tool до 1к LOC можно и без иммутабельности совершенно спокойно, и я вам открою тайну: вам даже не придётся использовать const в таком случае нигде (!) но вот когда 100 человек, работают над 1кк LOC и малейшая ошибка может стоит огромных денег - mutable shared state это рай для багов, они плодятся там как саранча и они сожрут вам все нервы, деньги и время. поэтому если вы хотите чтоб Go был конкурентноспособным в enterprise сфере и в сфере больших open source проектов, тогда без immutability никак.
Ευγένιος
У меня даже шрам остался.
Eugene
mutable shared state напрямую ведь с проблемами concurrency связан
Roman
ведь иммутабельность должна быть в языке изначально заложена во время проектирования языка?
мы это уже обсуждали. 1. Immutability не была заложена в язык изначально 2. Тем не менее она нужна 3. Мы (и Google видимо тоже) не хотим ломать совместимость 4. Поэтому мы "накладываем" иммутабельность на существующий язык посредством перегрузки const keyword'а о чём собственно и proposal
Eugene
но var и const в одной строке выглядят сомнительно
Roman
но var и const в одной строке выглядят сомнительно
var это декларация переменной, const в данном случае это часть декларации типа данной переменной иммутабельный int != int иммутабельный Object != Object etc.
Eugene
а если создать изменяемые и неизменяеме структуры данных в библиотеке(вместо того, чтобы менять язык)?
Eugene
и как вы их создадите?
это надо продумать, в kotlin либе делают Immutable Collections
Roman
это надо продумать, в kotlin либе делают Immutable Collections
всё уже продумали в proposal'е, но если таки есть непродуманные моменты то конечно уточните, нам это важно
Eugene
всё уже продумали в proposal'е, но если таки есть непродуманные моменты то конечно уточните, нам это важно
вроде изменения хотите внести именно в сам язык, а не в либу языка, правильно понимаю?
Roman
вроде изменения хотите внести именно в сам язык, а не в либу языка, правильно понимаю?
какую либу языка? изменения конкретно касаются компилятора. Компилятор должен во время компиляции проверить происходят ли где либо в коде попытки мутации того, чего мутировать нельзя
Eugene
?разве это нормально читается: var immut2mut const * Object = &const(Object{})
Roman
?разве это нормально читается: var immut2mut const * Object = &const(Object{})
это без implicit conversion, поэтому я таки предлaгаю implicit conversion на non-const -> const
Roman
Eugene
с implicit вот так: var immut2mut const * Object = &Object{}
так это тоже вызывает сомнения
Eugene
как думаете, если этот код показать junior-у: var mut2immut * const Object = &Object{} var immut2mut const * Object = &Object{} var immut2immut const * const Object = &Object{} func NewConstSlice() const [] * const Object { return [] * const Object { &Object{}, &Object{}, } } поймёт ли он быстро?
Anonymous
скорее в окно выйдет
Roman
так это тоже вызывает сомнения
как часто вы декларируете переменные через var? ничего страшного нет в func Func(s const[] string) {} или даже в экстремальных случаях как: func Func(m const map[const * const Object] const * const Object) {} можно сделать так: type ConstObjRef const * const Object type ConstMap const map[ConstObjRef] ConstObjRef func Func(m ConstMap) {} учитывая что вас никто не заставляет использовать иммутабельные типы
Vladimir
Насколько помню, было высоко оцененное предложение (можно поискать) использовать слово “readonly” как модификатор параметра функции. Без const и без изменений в объявлении переменных
Vladimir
Типа того. Но только для объявления функции
Eugene
mutable shared state - это проблема concurrency, но по идее, решается с помощью мьютексов
Eugene
но, например, есть https://golang.org/pkg/sync/#Map
Eugene
он же concurrent-safe, правильно?
Roman
как думаете, если этот код показать junior-у: var mut2immut * const Object = &Object{} var immut2mut const * Object = &Object{} var immut2immut const * const Object = &Object{} func NewConstSlice() const [] * const Object { return [] * const Object { &Object{}, &Object{}, } } поймёт ли он быстро?
1. хуже будет если ваш джун по незнанию мутирует какой-то слайс, который ему мутировать нельзя, потому-что вы этого без тщательного code-review можете не заметить и создать баг. 2. С иммутабельностью ему просто компилятор этого сделать не позволит и он за пару дней поймёт что такое immutable variables / arguments / return values / methods / receivers 3. как-раз джуны делают ошибки с mutable shared state чаще всего, потому-что недостаточно понимают такие вещи как pointer aliasing (https://en.wikipedia.org/wiki/Pointer_aliasing) 4. вы считаете что копирование красивее и с ним меньше boilerplate'а? func (rec *T) ReadOnly(s []*Object) [] *Object { s_copy := make([] *Object, len(s)) for i, item := range s { // Clone must create an exact copy of *Object to avoid aliasing s_copy[i] = item.Clone() } // Pass copy to third-party function thirdparty.Dependency(s_copy) // now return an internal slice, but copy it to prevent mutations internal_copy := make([] *Object, len(rec.internal)) for i, item := range rec.internal { // Clone to avoid aliasing internal_copy[i] = item.Clone() } return internal_copy } вы сильно ошибаетесь: func (rec * const T) ReadOnly(s [] * const Object) [] * const Object { thirdparty.Dependency(s) return rec.internal } или же вот так: type ConstSlice [] * const Object func (rec * const T) ReadOnly(s ConstSlice) ConstSlice { thirdparty.Dependency(s) return rec.internal }
Eugene
я правильно понимаю, что вы предлагаете решение проблемы, когда в более 2-х потоках одновременно записывается значение одной переменной?
Daniel
нет
Daniel
это совсем другая проблема
Daniel
на самом деле - в первую очередь человек хочет запретить менять то, что меняться не должно, себе
Eugene
на самом деле - в первую очередь человек хочет запретить менять то, что меняться не должно, себе
а я думал, что mutable shared state связан с тем, что из множества потоков одновременно записываются значения в одну переменную
Daniel
(ну или вот я, как тимлид - когда я тимлид - хочу запретить тиме писать код с глобальным стейтом мутирующим)
Eugene
то есть вот это: concurrent access to shared mutable state
Roman
а я думал, что mutable shared state связан с тем, что из множества потоков одновременно записываются значения в одну переменную
shared state = состояние, которое делится между несколькими акторами. акторы могут быть как функции, так пакеты, так и потоки. Помогает ли иммутабельность при написании потенциально конкурентного кода? Да, потому-что у нас есть гарантия того, что то, что помечено иммутабельным, менять нельзя, а значит нельзя будет пообещать n потокам что ты не будешь писать в X и всё-равно это сделать Иммутабельность это только про конкурентность? Нет, это скорее про ещё более точно определённые типизированные интерфейсы. Если каким либо стейтом делятся несколько функций разных вендоров (не конкурентно) то мутабельность может порадить страшные баги потому-что кто-то, где-то накосячил
Стас
вопрос о правильности подхода: встретил комментарий на редите "Also, Go is a "Get Shit Done" language: you don't design Go programs as you would design a Java project. You write the code, prove it works, then generalize and clean up the mess. What you're left with is clean, idiomatic Go." т.е. автор, как я понял за то, чтобы написать по каким-то эскизам код, потом посотреть на него, почистить всякое дерьмо, потом снова посмотреть на код и т.д.
Стас
вы придерживаетесь такого принципа?
Roman
https://github.com/romshark/Go-2-Proposal---Immutability#39-doesnt-the-const-qualifier-add-boilerplate-and-make-code-harder-to-read
Daniel
вы придерживаетесь такого принципа?
вообще-то да. java провоцирует over-engineering, и это давно известный печальный факт go местами провоцирует under-engineering, но это настолько очевидно, что тимлид легко даст вам по рукам
snip
Идея с const нежизнеспособна и не потому что иммутабельность не нужна, а потому что в том виде как он описан в пропозале он выглядит чужеродным в го. Го это простота на грани примитивности, многие правильные концепции сюда не завезли не потому что они не нужны, а потому что не нашли как их реализовать так же просто как и все остальное в го. Если хочется правильных и нужных концепций пишите на раст
Roman
Причём тут компилятор? Я про людей)
и в чём вы видите сложность?
snip
const * const это сложно
snip
И уродливо
Daniel
> Если хочется правильных и нужных концепций пишите на раст вот откуда эта уверенность? нам что, уже дали большой проект на расте? мы что, уже убедились, что в нем правильные абстракции и нужные концепции? все, что я слышал про попытки применения раста в проде (я слышал мало), заканчивалось словами "оно падало, стектрейс был неинформативен". в 1/3 случаев за этим следовало "и мы переписали все на go"
Roman
const * const это сложно
а []string по вашему это легко получается?
snip
Но спорить я не хочу я высказал мнение, а уж прав или нет покажет время
Roman
Но спорить я не хочу я высказал мнение, а уж прав или нет покажет время
коллега, вы не правы, потому-что pointer aliasing и shared mutable state это сложно! не надо выдавать эти концепции за "просто" потому-что синтаксис легче... что такое синтаксис, если вам потом 10 часов дебажить непонятный баг?
Daniel
ну вот мы тут думаем, как завезти compile-time контроль иммутабельности в go. коллега Роман целый пропозал написал. а я свой не написал пока, но напишу обязательно
snip
ну вот мы тут думаем, как завезти compile-time контроль иммутабельности в go. коллега Роман целый пропозал написал. а я свой не написал пока, но напишу обязательно
Ну мне это видится как попытался привнести идею из другого мира в мир го, идея иммутабельности хорошая и нужная, но const это сложно и уродливо
snip
Я даже думаю что дженерики и обработку ошибок им пропихивают откуда то сверху
snip
Потому что сделать это просто и при этом правильно как то не получается
Daniel
ну вот именно пропозал Романа оставляет ощущение чуждости, да
Roman
Ну мне это видится как попытался привнести идею из другого мира в мир го, идея иммутабельности хорошая и нужная, но const это сложно и уродливо
const это может быть и уродливо (красота субъективное понятие), но это не сложно, а наоборот проще, чем сидеть гадать и писать копирующие функции и циклы, городить ненужные интерфейсы и т.д.