Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
В комментариях к посту автора я попросил хотя бы одного человека привести три примера из своего реального кода, где ему нужно было бы вставлять элемент в середину массива — не написал никтоВ самом деле, лично я так в середину массива элементы не вставляю. Вот пример из реального проекта, где я вставляю элемент в серёдку (при этом рост этих массивов у меня ещё и спрогнозирован и их «capacity» равняется удвоенному прогнозу):
// если вставка требуется по индексу, который больше
// массива, просто добавляем в конец
if i >= len((*arr)[org]) {
(*arr)[org] = append((*arr)[org], value)
} else {
// надо добавить любой элемент в конец, чтобы появилось место
// если в срезе место есть, оно будет использовано автоматически
(*arr)[org] = append((*arr)[org], nil)
copy((*arr)[org][i+1:], (*arr)[org][i:])
(*arr)[org][i] = value
}
Для таких штук существуют другие структуры данных: односвязный список, двухсвязный список, двунаправленная очередь.
insert?a = append(a[:pos], append([]T{x}, a[pos:]...)...)
Надеюсь не появится как в прошлой теме комментатор, говорящий о великом множестве заранее неизвестных типов, для которых понадобится применять этот метод.
numbers = append(numbers[:2], append([]int{3}, numbers[2:]...)...)
numbers = append(numbers[:2], 3, numbers[2:]...)
попытка восстановить баланс разумного доброго и вечного
Любой, кто писал на С/C++, знает во что превращаются проекты, после того, как кодом поработают 5-10 программистов, и код пройдет несколько стадий рефакторинга
писать несколько месяцев REST-бекенд на C++ и нанять для этого ещё 2 rock-star C++ программиста
и в Go, в отличие от, скажем С++, нет undefined behavior при сокрытии переменных
Go — это другой язык, это не C++
В отличии от многих других языков, Go рождался не студентами-любителями в порыве написать что-нибудь свое, и не теоретиками, гоняющимися за фишками из свежих научных трудов
не слишком основательно прорабатывает аргументацию, смещая акцент в эмоции. «Инженерный» троллинг :)
я всё ещё под впечатлением от рекомендации автором статьи использования связного списка для реализации сортированных массивов.
v.insert(upper_bound(v.begin(), v.end(), x), x);
который помогает вам делать более быстро более качественный код
перейти на Go и написать все быстро и качественно
Распять мерзавца, как он посмел высказать свое мнение! Четвертовать его!
И внезапно язык становится неудобным во всем
Я не преувеличу, если скажу, что немного разочарован в сообществе программистов. Более того, все эти кровавые холивары происходят по той же самой причине.
А тут — набор ad-hoc-костылей и решений с потолка, уж простите.
То есть идея в том, что глядя на вставку в середину массива, человек должен заподозрить неладное и убедиться, что оно к месту.
s = append(s, 0)
copy(s[i+1:], s[i:])
s[i] = x
append(arr1,1,arr2,3,arr4,5)
Строгий язык не может быть удобным.
Правда я так и не увидел аргументов (т.е. конкретных примеров) как строгость делает язык неудобным.
Следуя такой логике можно дойти до того, что JavaScript/PHP очень удобные языки. Удобнее Питона и тем более Java/C#. Но я бы не согласился с такими утверждениями.
язык должен быть удобным не для написания кода, а в первую очередь для его сопровождения.
Внезапно, но вроде как именно этот пункт выставляется одним из основных преимуществ Node.js для новичков.
проще и удобнее, а следовательно и быстрее
То, что в языке нет generics — я тоже не считаю плюсом.
Сопровождение — это не review и комментирование, а debugging и внесение серьезных изменений в приложение. А эти моменты — часто отнимают куда больше времени, нежели «первичное» написание кода.
Если проект был нормально спроектирован
//go:generate toolname -params -blabla
//Hey! Look at my awesome function Blabla
//Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
func Blabla() {
// code...
}
public class SomeClass
{
///<summary>Это пойдет в документацию</summary>
///<remarks>И это пойдет в документацию</remarks>
///<param name="f">f-word</param>
///<returns>a swear based on <paramref name="f"/></returns>
//а тут программист может писать что угодно, это не войдет ни в какую документацию
public bool WhatThe(string f)
{
}
}
//Это комментарий
///Эта функция считает синусы
Обсуждаемая выше проблема — чистой воды теоретизирование
Я не знаю, как вы умудряетесь новой сущностью ломать совместимость, наверное вы избранный.
А это плохо.
Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.
Раз избранный, то поясню — новая сущность в Go 1.5 == ошибка компиляции в Go 1.4.
Главное навесить ярлык. Ясно, спасибо.
То есть Go 1.5 совсем не добавляет ничего нового в сравнении с Go 1.4? Я вас правильно понял?
это должен быть комментарий
Он не должен
Это не должна быть инструкция для препроцессинга… или еще что-то, что придет в голову создателю языка.
Лишить язык программирования возможности писать комментарии — это плохое решение.
Нет, прямая совместимость не гарантируется, но при обсуждении различных дизайнов, там где можно её не ломать, лучше не ломать. Так поняли?
Не очень понимаю, почему язык должен вам что-то, что пришло лично вам в голову, а не создателям языка.
Согласен. Только непонятно, про какой вы язык говорите.
Нет. Если совместимости все равно нет, тогда зачем вы к ней аппелируете?
Я говорил про комментарий. То, что он должен исходит из его определение.
Про Go, в котором комментарии были заменены на метаданные.
Я к ней аппелирую, потому что это один из моментов, по которым принимаются решения. Уже писал, что дизайн языка — это не черное и белое, и не бинарный выбор «очевидно, что это должно быть так» и «не так». Неужели это и вправду нужно разъяснять 15 комментариев подряд?
В Go не заменяли комментарии на метаданные.
По определению самолёт — должен летать.
Сколько вы пишете на Go, кстати?
А вот и пошли аргументы в стиле «сначала добейся».
Если же это «не пробовал, но порицаю», то ценность такой дискуссии нулевая.
Единственная причина, по которой их сделали именно так — недальновидность создателей первой версии Java.Если пытаетесь намекать на дальновидность разработчиков .NET, который появился в 2000, то стоит посмотреть на то, что java появилась в 1995.
//Hey! Look at my awesome function Blabla
//go:generate toolname -params -blabla
//Lorem ipsum dolor sit amet, consectetur adipiscing elit.
//Donec tortor erat, rhoncus ac turpis id, ullamcorper congue odio
func Blabla() {
// code...
}
Магические комментарии — это костыль. Претензии к тому, КАК сделали.Лучший критический комментарий за два поста, imho.
Статья же автора о том, что дизайн языка «плохой» — это, к сожалению, не более, чем попытка привлечь к себе внимание
й и й. С++ это не пойметПонятно что библиотеки есть для всего. Речь именно про стандартную библиотеку языка, в которой это можно было бы удобно объединить со стандартным же IO.Вы про collation? IO без разницы какой вариант нормализации вы применяете, выведет как есть.
Про второе, ну вот, например, смотрите, очевидно, что й и й — одна и та же буква, но на на самом деле это й и й. С++ это не поймет
#include <iostream>
#include <string>
int main() {
std::string s {"пр?вет, мир"};
s[s.find('?')] = 'и';
std::cout << s << '\n';
}
А они где-то работают?
> let s1 = "vae";; val s1 : string = "vae" > let s2 = "v\u00e6";; val s2 : string = "væ" > System.StringComparer.InvariantCulture.Equals(s1, s2);; val it : bool = true > System.StringComparer.Ordinal.Equals(s1, s2);; val it : bool = false
И как взять в слове vae третью букву?
> s1.[2];; val it : char = 'e' > s2.[2];; System.IndexOutOfRangeException: Index was outside the bounds of the array.
[] идет посимвольно. а не побайтно.Обе эти строки — одно и то же слово, и в нём одна и та же третья буква — «e».
А при работе нужно чтобы поиск/замена понимали, что символ UTF8 может состоять из нескольких байт и даже слов UTF16Это вопрос к используемому вами движку regexp. Он не обязательно входит в стандартную библиотеку. И не обязательно одинаков между системами в том случае, когда входит в неё.
Про legacy-систему, где консоль «типа» 866, а на самом деле — смесь 866 и 1251 (параметры в argv передаются в cp1251) лучше постараться забыть, как страшный сон =)Суть в том, что страшным сном оно становится как раз из-за того, что в C++ нет нормальной поддержки строк, которая бы брала всю работу по конвертации на себя.
Это вопрос к используемому вами движку regexp. Он не обязательно входит в стандартную библиотеку.Я даже не про regex. Но он, кстати, сейчас входит в стандартную библиотеку.
И не обязательно одинаков между системами в том случае, когда входит в неё.Реализация может быть не одинакова, а поведение должно быть одинаково, иначе у вас получается некроссплатформенный код, что плохо.
Суть в том, что страшным сном оно становится как раз из-за того, что в C++ нет нормальной поддержки строк, которая бы брала всю работу по конвертации на себя.
<codecvt> в целом и codecvt_utf8 в частности для конвертации, включая суррогатные пары.суррогатные парыСуррогаты есть только в utf16, т. к. не всякий codepoint может быть представлен одним uint16. В utf8 этой проблемы нет.
#include <iostream>
int main() {
std::cout << "привет, мир\n";
}
#include <iostream>
#include <locale>
#include <codecvt>
int main() {
// вариант 1: просто конвертируем строку wchar_t -> utf8
std::cout << std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(L"привет, мир\n");
// вариант 2: объясняем потоку, чтобы он конвертировал wchar_t -> utf8 при выводе
std::wcout.imbue(std::locale(std::wcout.getloc(), new std::codecvt_utf8<wchar_t>()));
std::wcout << L"привет, мир\n";
}
Я не хочу ничего говорить, я хочу, чтоб строка текста выводилась как текст. Всякие кодировки оставьте в прошлом векетак вроде только вот совсем относительно недавно начали понимать что важно знать кодировку применительно к строке, иначе зоопарк выходит как в прошлом веке.
1) Я не хочу ничего говорить, я хочу, чтоб строка текста выводилась как текст. Всякие кодировки оставьте в прошлом веке.В какой кодировке? Текста без кодировки не существует. Строка — суть просто набор байтов.
Ну вот я прошу кодировку «чтоб было читаемо независимо от того, куда идет вывод и на какой системе». Как?Utf-8?
Строка — суть просто набор байтов.Нет. Строка — суть кусок текста. То, что вы там напридумывали — это все от бедности. Строка не может быть «просто набором байтов» хотя бы потому, что строкам и тексту уже тысячи лет, а эти ваши байты вот только придумали.
Нет. Строка — суть кусок текста. То, что вы там напридумывали — это все от бедности. Строка не может быть «просто набором байтов» хотя бы потому, что строкам и тексту уже тысячи лет, а эти ваши байты вот только придумали.Понимаете какая штука… Компьютеры оперируют только битами, в оперативной памяти нет никаких букв, текстов и строк, там и чисел-то так таковых нет. Даже чтобы получить обыкновенный int и то нужно знать сугубо вторичную для пользователя вещь: хранится ли это число в little-endian или big-endian. Считайте это «кодировкой» чисел. Если вы не знаете «кодировку», вы не сможете интерпретировать биты в виде числа.
И знать про little или big endian нужно только в качестве разминки для ума, но для проведения вычислений эти знания не требуются — спросите любого бухгалтера.Вот тут и настаёт привет: пока числа на бумажке у бухгалтера, у них действительно нет никаких little- и bin-endian. Но это представление появляется, как только числа набирают кнопочками на клавиатуре.
Символы же в компьютер вводят не в виде набора бит.Вводят не биты. Но в оперативной памяти символы (и, соответственно, текст — массив символов) имеют представление в виде бит.
И обычно хотят чтобы при всех преобразованиях он оставался текстом и выводился обратно(на экран, принтер и тд) именно в виде того же набора символовНужно использовать одну и ту же кодировку.
The Single Most Important Fact About Encodings
If you completely forget everything I just explained, please remember one extremely important fact. It does not make sense to have a string without knowing what encoding it uses. You can no longer stick your head in the sand and pretend that «plain» text is ASCII.
There Ain't No Such Thing As Plain Text.
If you have a string, in memory, in a file, or in an email message, you have to know what encoding it is in or you cannot interpret it or display it to users correctly.
reversed(items) возвращает итератор:>>> x = [1, 2, 3, 4]
>>> reversed(x)
<list_reverseiterator object at 0x10092c668>
В го вы тоже можете написать функцию которая вернет список обратный заданному… но это копирование памяти которого можно избежать.
for (auto i : boost::adaptors::reverse(x)) {
;;
}
Это было убрано намеренно, потому что выражение s[i:j] может молча дать неверный результат, если j станет меньше нуля.Выражение s[i:j] может молча дать неверный результат, если i или j станет не тем положительным числом, о котором думает программист, представляете! И то, что j станет вдруг отрицательным после того как было положительным ещё менее вероятно, и это, скорее всего, будет уже совсем другая проблема.
Вы случайно не подрабатываете евангелистом Go в Google на полставки: ?)
50+ лет
создание UNIX
В иерархической системе каждый индивидуум имеет тенденцию подняться до уровня своей некомпетентности
for number := range numbers {}студентами-любителями в порыве написать что-нибудь свое
А вот автор статьи явно считает, что Go идеально спроектирован профессионалами
package core
type KernelAPI interface {
...
LoadDump(fileName string) error
...
}
package importer
import "core"
type Importer interface {
ImportCSV(kernel *KernelAPI)
}
авторы Go, исходя из своего, более чем, полувекового опыта разработки, видят [...] Решение, [...] уменьшающее риск хитрых ошибок в long term. Понятно, что не все мыслят на long term, отсюда и конфьюз.
У программистов без опыта, конечно, приоритеты другие.
пропасть, между программистами-практиками и программистами-теоретиками [здесь к ним причислен программист из Mozilla, ага].
Go рождался не студентами-любителями в порыве написать что-нибудь свое, и не теоретиками, гоняющимися за фишками из свежих научных трудов. Go есть результатом колоссального опыта, отбора только проверенных временем концепций и очень глубокого понимания проблематики мира разработки ПО.
«Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует.»
Bjarne Stroustrup.
Пока читал вброс от Ильи хотелось дать ему леща отцовского, да обещал в интернетах не срываться. :) Для меня самые важные показались последние абзацы, потому что я уже потратил 6 мес на своей работе внедряя Go. (Пока результат не очень — пишем внедряем, выпиливаем потому что все боятся начинать). И что самое страшное после каждого выпиливания, я получаю набор статей от моих коллег типа той что состряпал Илья, как аргумент что язык сырой и что пока рано на него переходить. Я смело могу сказать что болтовня таких малолеток не только замедляет развитие языка, но еще и не дает развиваться специалистам, которые хотят его попробовать в продакшене. Но Илье то этого не понять, потому что сидя за партой в школе можно только догадываться о том как же живет программист в реальном мире и на сколько трудно привносить какие-то новые технологии в старые компании.
потратил 6 мес на своей работе внедряя Go
Пока результат не очень
Go это не Python, это разные языки. Некоторым людям сложно даётся факт, что никакие языки, кроме Питона, не являются Питоном
Go — это другой язык, это не C++.
пхп рожден для того что, бы умиратьне помню кто сказал но это факт
критика «дизайна сокрытия переменных» должна подразумевать предложение альтернативного, более удачного дизайна — тогда дискуссия имеет шанс быть предметной.
var c = new Something();
{
var c = new Something();
}
CS0136 A local or parameter named 'c' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
let Secret () = (42, 1)
let a = 0
a |> printfn "before %A"
begin
let (a, _) = Secret()
a |> printfn "inside %A"
end
a |> printfn "after %A"
before 0 inside 42 after 0
let Secret () = (42, 1) let a = 0 a |> printfn "before %A" let (a, _) = Secret() a |> printfn "inside %A" a |> printfn "after %A"
error FS0037: Duplicate definition of value 'a'
number := 0
fmt.Println("before", number)
{
number, _ := Secret()
fmt.Println("inside", number)
}
fmt.Println("after", number)
before 0 inside 42 after 0
number := 0
fmt.Println("before", number)
number, _ := Secret()
fmt.Println("inside", number)
fmt.Println("after", number)
no new variables on left side of :=
number := 0
fmt.Println("before", number)
number, err := Secret()
if err != nil {
panic(err)
}
fmt.Println("inside", number)
fmt.Println("after", number)
before 0 inside 42 after 42
Go — это язык для программирования на Go, а не новый синтаксис для Java, для Haskell, или для других существующих языков. Чтобы написать хорошую программу на Go, нужно мыслить по-другому, чем при программировании на Java. Вместо этого современные программисты сокращают путь: берут готовый код, и переписывают его на Go. Код на Go при этом, действительно, порой выходит неуклюжим. Но дело не в Go: если бы эту же программу с самого начала писали на Go, используя другие подходы — более естественные для Go и менее применимые в той же Java — то код бы получался более живой и яркий. Но чтобы научиться мыслить по-другому, нужно затратить время и силы — больше, чем критики Go могут себе позволить. Насколько проницательных отзывов о Go вы могли бы ожидать от человека с десятью годами опыта на Java и десятью минутами опыта на Go?
Называть это «плохим дизайном языка» — чрезвычайно глупо
Дайте ваше определение "плохого дизайна языка".
Помимо этого, каждый импорт — это замедление процесса компиляции, и там где Go-программисты не успевают моргать глазом, С++-программисты идут пить кофе и ждать
С(++) — чуть ли не единственные языки, которые замедляются неиспользуемыми инклудами. Все остальные как-то не замедляются.
Почему Go — это хорошо продуманный язык программирования