LINUX.ORG.RU

Гвидо Ван Россум уходит на пенсию

 


2

3

Создатель языка Python, последние шесть с половиной лет работавший в компании Dropbox, уходит на пенсию.

Эти 6,5 лет Гвидо работал над Python и развивал культуру разработки Dropbox, которая переживала стадию перехода от стартапа в крупную компанию: был ментором, наставлял разработчиков писать понятный код и покрывать его хорошими тестами. Он также составил план перевода кодовой базы на python3 и начал воплощать его в жизнь.

Также занимался развитием mypy — статического анализатора Python-кода, который был изначально разработан другим сотрудником Dropbox, нанятым Гвидо.

Помимо этого был активным участником движения за привлечение женщин в IT.

>>> Подробности

anonymous

Проверено: a1batross ()
Последнее исправление: Deleted (всего исправлений: 5)

Гнидо-Опоссум не нужен и его пестон тоже.
Испохабил целое десятилетие в ИТ! Сколько ещё неокрепших умов будут прыгать с этими «отступами»! :((( Козлопотам и язык его такой же.

matumba ★★★★★
()
Ответ на: комментарий от Deleted

Ты всегда пишешь новый код, глядя на старый? Это не норма. IDE должна показать тебе аннотацию, проверить, что ты вставил адекватные аргументы и что возвращаемое значение вписывается в выражение

Я имею ввиду не типы, а комментарий. Пока код длинный — тот комментарий нужен, чтобы через год с первого взгляда понять, какие возвращаются переменные окружения и в каком порядке. А когда код короткий, то нет никакой разницы — читать код или комментарий, ведь по коду тоже всё сразу видно.

Но часто ловишь себя на мысли, что ты думаешь не о том, как решить задачу, а о том, как уложить решение в свою систему типов

И это правильные мысли.

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

И если ты упирался в систему типов, то, возможно, ты ее недостаотчно хорошо знаешь.

Вполне возможно. Можем взять пример, пусть те же screepы. Почти пример из туториала — чтобы послать крипа к башне, в код его роли пишут:

var tower = Game.getObjectById('85a5a0054b9c590fca1e34e6');
creep.moveTo(tower);
Это — два метода: Game.getObjectById() и Creep.moveTo(). Как их описать на TS?

На JS moveTo() принимает коодинаты или любой объект, у которого они есть. А getObjectById() может вернуть вообще любой объект по его строковому идентификатору. Как теперь это переложить на типы?

anonymous
()
Ответ на: комментарий от matumba

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

Для фунциональных или интеграционных тестов питон вообще мастхэв.

anonymous
()
Ответ на: комментарий от anonymous

Лет ми гугл фор ю

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/screeps/index.d.ts#L1378

https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/screeps/index.d.ts#L2930

На JS moveTo() принимает коодинаты или любой объект, у которого они есть.

Через перегрузку функций и интерфейсы, очевидно

А getObjectById() может вернуть вообще любой объект по его строковому идентификатору. Как теперь это переложить на типы?

Никак. Возвращаешь тип, который указываешь как generic

const creep = getObjectById<MyFuckenCreep>("my_fucken_creep");

В vuex похожая беда, только хуже. Там в модулях стринги изо всех щелей торчат. Это даже по меркам js неадекватно

https://vuex.vuejs.org/guide/modules.html

Впрочем, если есть список фиксированных айдишников, всегда возвращающих оинаковые типы, можно эти соответствия через перегрузку функций изобразить. Как, например, сделано в Document.createElement

Deleted
()
Последнее исправление: Deleted (всего исправлений: 6)
Ответ на: комментарий от anonymous

Все здравомыслящие люди опасаются, что wasm и бинари с корпоративными закладками угробят остатки свободы

Обязательно угробят. Остатки твоей приватности. Но на открытость технологии это врят-ли повлияет. Тебе и сейчас и потом не придется согласовывать контент своего сайта с правилами какого-нибудь говномаркета или говностора, неделями ждать пока говностор проверит изменения, опасатсья что говномаркет что-то там заблокирует

Тебе не придется писать несколько версий сайта под разные бренды мобилок, только потому, что ковнокорпорации не договорились об общем API

Deleted
()
Ответ на: комментарий от anonymous

Пока код длинный — тот комментарий нужен, чтобы через год с первого взгляда понять, какие возвращаются переменные окружения и в каком порядке

Вот только когнитивная нагрузка возраскает многократно. Тебе надо не забывать менять докстринг при каждом изменении контракта. Тебе надо каждый раз перечитывать текст на человеческом. И все-равно IDE/компилер не сможет ничего почерпнуть из такого докстринга. Сизифов труд как он есть

А когда код короткий, то нет никакой разницы — читать код или комментарий, ведь по коду тоже всё сразу видно

В идеале, при наведении на имя функции, описанной в другом файле, IDE покажет тебе ее полную аннотацию (с разрезолвенными генериками, если удастся, и коментарием). А в твоем случае оно должно показать весь исходник?? Который ты будешь перечитывать до посинения??

Правильные для академической чистоты кода. Но решение они не упрощают

Нет. Именно упрощают. Если написать ***ню, то она потом аукнется и не раз

Deleted
()
Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от Deleted

Впрочем, если есть список фиксированных айдишников, всегда возвращающих оинаковые типы

Айдишник — это уникальный 12-байтный идентификатор любого объекта в игре. Понятия не имею, значит ли он что-нибудь...

Никак. Возвращаешь тип, который указываешь как generic
const creep = getObjectById<MyFuckenCreep>("my_fucken_creep");

Да, как-то так обычно и делают. Из-за этого и возникает проблема — конкретный тип часто не важен, а потому не известен.

Дело в том, что эти длинные айдишники не загоняют руками в код. Вместо этого создают абстрактную роль, а айдишник записывают, как параметр в json-памяти. Что-то вроде:

creep.memory.role = 'guard';
creep.memory.target = '85a5a0054b9c590fca1e34e6';

И тот код превращается в:

var something = Game.getObjectById(creep.memory.target);
creep.moveTo(something);
Хочешь перебросить крипа на другую цель — не нужно исправлять и перезаливать код, ты просто меняешь ему айдишник цели в памяти прямо в рантайме.

На JS это работает. А как это переложить на типы?

Костылять десяток ролей, вроде 'guardTower', 'guardMineral', 'guardSource', 'guardCreep'... реализация которых будет отличаться только именем типа?

Да, так можно. Но об этом же и шла речь — типы мешают, «думаешь не о том, как решить задачу, а о том, как уложить решение в свою систему типов» и «приходится выбирать не совсем хорошее решение только потому, что оно лучше вписывается в существующие типы»

anonymous
()
Ответ на: комментарий от anonymous

Если список ролей фиксирован, то это enum. Пишем обертку над getObjectById, которая принимает creep, и возвращает тип в зависимости от memory.role

Костылять десяток ролей, вроде ‘guardTower’, ‘guardMineral’, ‘guardSource’, ‘guardCreep’… реализация которых будет отличаться только именем типа?

Да. У них всяко есть базовые общие поля, плюс какие-то екстеншены. Это всё выражается через систему типов

Хочешь перебросить крипа на другую цель — не нужно исправлять и перезаливать код, ты просто меняешь ему айдишник цели в памяти прямо в рантайме

Обертка convertCreep, в которую передаешь крипа и роль из enum-а

Deleted
()
Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от crutch_master

Смешались в кучу кони, люди

Неужто только скриптоговно это «Управляемый код, байт-код, витруальные машины, гц и всё такое прочее»?

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

php, python, ruby и js - это все языки для виртуальных машин с байткодом/jit, гц, динамической типизацией и сопуствующими плюшками/косяками. Тебе в принципе не нравится идея вм, когда код гоняет не сразу процессор, а какая-то виртуальная машина?

crutch_master ★★★★★
()
Ответ на: комментарий от Deleted

Неужто только скриптоговно это

Так вм - это и есть скриптоговно. На той же яве попробуй плотно поработать с рефлексией, будет тоже самое, что на питоне, только хуже.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

На той же яве попробуй плотно поработать с рефлексией

Для этого должны быть особые основания. Что-то принципиально невыразимое через обычные инструменты

будет тоже самое, что на питоне, только хуже

Сам придумал или понял на горьком опыте? На котлине тоже хуже? На шарпе? Если на питоне лучше, то на лиспе вообще идеально?

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

Для этого должны быть особые основания. Что-то принципиально невыразимое через обычные инструменты

Да да, нинужно.

Сам придумал или понял на горьком опыте?

Второе.

На котлине тоже хуже?

Не пробовал.

На шарпе?

Чем он принципиально отличается от явы?

Если на питоне лучше, то на лиспе вообще идеально?

Нет.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Да да, нинужно

Нужно, но не настолько, чтобы ради рефлексии весь язык превращать в желеобразное нечто. В руст вона тоже рефлексия есть

Чем он принципиально отличается от явы?

Наслаждайся https://en.wikipedia.org/wiki/Comparison_of_C_Sharp_and_Java

Нет

Как нет!? Код == данные! Модификация AST в рунтайме! Никакая гадкая IDE не сможет догадаться как всё изменит твой гениальный defmacro. Да сам интерпретатор о***ет от того как изящно ты его трахнул. Рай для скриптобойцов из этого itt треда

Deleted
()
Последнее исправление: Deleted (всего исправлений: 3)
Ответ на: комментарий от crutch_master

Снова приведу в пример этого «специалиста с расширенным сознанием»

https://youtu.be/VFBXx7O9BxU?t=2089 (34:50)

«ты можешь делать все что угодно»

«у пайтона нет приватных полей»

«ты можешь вызывать код пайтона внутри пайтона»

«ты пишешь какие-то инструкции, которые зависяот только от инструкций, которые были раньше, то что будет дальше никак интерпретатор особо не касается»

«это бесполезно и так никто не делает, но это можно»

..не знаю как называется эта болезнь

Deleted
()
Последнее исправление: Deleted (всего исправлений: 3)
Ответ на: комментарий от Deleted

Наслаждайся

Не увидел рефлексию в списке.

Нужно, но не настолько, чтобы ради рефлексии весь язык превращать в желеобразное нечто.

Ну как ты себе представляешь язык, на котором ты только и делаешь, что пляшешь вокруг рефлексии? Естественно он будет желеобразный, потому что задача такая.

Как нет!?

Лисп это уж слишком.

crutch_master ★★★★★
()
Ответ на: комментарий от Deleted

не знаю как называется эта болезнь

Это называется вкусовщина.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Не увидел рефлексию в списке

ctrl+F

Ну как ты себе представляешь язык, на котором ты только и делаешь, что пляшешь вокруг рефлексии?

Зачем мне визуализировать говно?

Лисп это уж слишком

Какие-то рамки приличия у тебя есть, уже хорошо :) Лучше чем «tcl для души»

Deleted
()
Ответ на: комментарий от crutch_master

Ну как ты себе представляешь язык, на котором ты только и делаешь, что пляшешь вокруг рефлексии? Естественно он будет желеобразный, потому что задача такая.

Что за задача?

anonymous
()
Ответ на: комментарий от Deleted

ctrl+F

+- тоже самое.

Зачем мне визуализировать говно?

За тем, что там будет тот же питон/жс. Думаешь почему на жс клепают каждый день по фреймворку, пока жабка который год сидит на своём спринге? Потому что могут, вот и клепают.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Думаешь почему на жс клепают каждый день по фреймворку

Потомучто веб – последний оплот свободки в мире айти?

пока жабка который год сидит на своём спринге

Потому-что в этой узкой нише куча конкурентов?

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от crutch_master

«Мягкий» код, в котором можно всё настраивать прямо на ходу.

Это не задача, а твоя фантазия. Из этой фундаментальной ошибки все твои дальнейшие рассуждения сыпятся, они не имеют смысла.

anonymous
()
Ответ на: комментарий от crutch_master

Давай реальную задачу или обделался!

anonymous
()
Ответ на: комментарий от crutch_master

На русте сотни фреймворков, сделанных на коленке. В конце ноября их процент еще возрастет

На гошечке так вообще горы

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от Deleted

На русте сотни фреймворков, сделанных на коленке. В конце ноября их процент еще возрастет
На гошечке так вообще горы

Не писал, ничего не могу сказать про то, сколько надо там будет копипастить, чтобы сделать key["value"]

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

key[«value»]

Прям так и пишешь? Дизреспект. Даже на твоем мягком можно написать правильно: key.get(‘value’, default_value). На русте то же самое

Deleted
()
Ответ на: комментарий от crutch_master

Что он себе позволяет?

Я не спорю, можно сделать себе жс на плюсах. Но зачем?

И правда, зачем делать делать из языка с нормальной типизацией какое-то говно? key[«value»] в плюсцах тоже таки можно, это вообще никаким боком к «мягкости» говна не имеет отношения.

anonymous
()
Ответ на: комментарий от Deleted

Прям так и пишешь?

Да.

Даже на твоем мягком можно написать правильно: key.get(‘value’, default_value)

Не нужно, потому что там ничего такого не может быть, чтобы выдавать default_value.

crutch_master ★★★★★
()
Ответ на: комментарий от crutch_master

Как это там можно, показывай.

class X {
    type operator()(const std::string &value) { ... }
}

X key;
type value = key["value"];

Ну и в стандартных std::map оно уже есть изначально.

anonymous
()
Ответ на: комментарий от crutch_master

Понятно. Копипасть все свои value в operator(), luke. Или юзай map.

Что копипастить?

Да, я там опечатался, operator[] конечно.

anonymous
()
Ответ на: комментарий от anonymous

Адское программирование

А из забытого... Даже не знаю... Их было так много.

Да и кого из них считать «убийцей С++»? D и E 😉? Можно ли к ним отнести Vala, Genie, Julia, Nim...? А Objective C и Object Pascal считаются?

внезапно, АДА: 10 причин выучить Аду и вообще http://www.ada-ru.org

книжки и learn.adacore.com

TL;DR: правда, ну почему не выучить уже Аду, наконец? неужели ты правда думаешь, что действительно

Язык Пентагона — враг мира. Язык «Ады» — голос термоядерного ада… В языке «Ады» слышится проклятие роду людскому.

???

вот лет 30 руки до неё не доходили толком и было только шапочное знакомство с Ada 83. таки взял и прочитал книжки, поставил GNAT и потыкал.

по первому впечатлению — это такой продвинутый паскаль. ближе к модуле-2 и оберонам (в хорошем смысле) и несколько к С++. обероны особенно и немного модула как-то совсем уж обкоцанными кажутся. и тут либо брать Nim с питонячьим синтаксисом и какими-то TObject, или всё-таки пытаться переизобрести паскаль, опять по надцатому разу, ну и С++ с шаблонами в очередной раз.

вроде как Ада похожа на ту же модулу + generic пакеты и ООП + контракты + таски, встроенные в язык, или С++ в паскалевском синтаксическом сахаре. только более грамотно организованный.

скриптуха тоже есть, с соотв. либами. или вот например AdaScript SparForte — шелл с синтаксисом ада. можно написать скриптуху, потом допилить до нормальной компилируемой ады.

GNAT: устанавливается легко и просто, как и сам gcc с --enable-lanugages=c,c++,ada. немного напрягает, что хелловорд занимает 300 кб после strip. это многовато по сравнению с той же модулой или nim. с другой стороны, а) это язык с объектами, исключениями и асинхронными зелёными нитками (или поверх POSIX тредов, или даже на голом железе), то есть функционально мощнее даже плюсцов б) плюсцы с std::cout<<"hello world"<<std::endl занимают 600 Кб при -static сборке, что даже толще в) рантайм ады написан на аде и таки допилить его до ZFP очень даже просто

подкупает то, что г) компилируется это примерно в то же, что и руками на сишке написал бы, и из сишки и в сишку элементарно прагмами и вызывается и линкуется. ну и GCC всё-таки, а не на коленке написанный невнятными студентами кодогенератор, как в оберонах. опять же, по сравнению с BlackBox Component Pascal оно менее герметичное и более командно-строчное. алсо, я так думаю, полезно было бы и сам BBCP на аде под GNAT переписать (там, кстати в GNAT есть фича pragma import(CPP, CppMethod, "цепепеметод"), правда, экспериментальная. на ada-ru.org пишут про «матрёшку» — платформу с QtAda + прочим суровым Энтерпрайзом.

например, в книжках есть примеры про то, как написать свой рантайм под STM или Pebble или RISC-V. выглядит несложно. ещё там тетрис на SPARK с контрактами прикольный.

вообще, ада на первый взгляд — паскаль/модула/оберон сделанный правильно, не сильно убого обкоцанный совсем уж как в обероне.

тащем-то, вполне себе кандидат на убийцу плюсцов. и кстати, то что языки вроде лиспа или ады «мёртвые» и не принадлежат какой-то одной корпорации — это и есть хорошо. можно не идти на поводу у моднявых хипстеров в погоне за фичами, а просто применять уже 40-60 летнюю классику, просто допиливая время от времени рантайм на какую-нибудь особо модную платформу.

anonymous
()
Ответ на: комментарий от Deleted

Если список ролей фиксирован, то это enum.

Не совсем фиксирован. В смысле, в каждый отдельный момент он фиксирован, но код эволюционирует. Пройдись через туториал (это минут 10 без регистрации и СМС), там роли на 2м шаге показывают.

Было бы классно один раз написать код, залить его в игру и пойти спать, а на утро подключиться и увидеть, что твои крипы развились, построили цивилизацию и захватили мир. 🙂

Но так у меня пока не получилось. Код постоянно меняется, приходится разбивать роли на несколько, вводить новые временные роли и руками назначать их (в этой колонии слишком много ресурсов, временно перебрасываем часть крипов таскать в соседнюю)...

У них всяко есть базовые общие поля, плюс какие-то екстеншены. Это всё выражается через систему типов

А вот это у меня не вышло сделать. Есть базовый RoomObject, но если объявить, что getObjectById() возвращает его, то дальше его никуда нельзя передать, и никакой метод у него вызвать нельзя.

Либо надо делать рантайм-проверки instanceof и downcast к конкретному потомку, но если мы делаем рантайм-проверки, то теряется весь смысл этой типизации.

Теоретически у нас должны быть обёртки только на входе, которые сразу отдают правильные типы. Но на практике, похоже, никто пока не осилил их написать. К тому же, поскольку мы не знаем, кого конкретно нам вернули, это будет куча instanceof-ов, которые ещё и будут тормозить нам код на каждом вызове.

Поэтому обычно пишут женерики и много копипастнутого кода. Но если у тебя получится сделать более удачный интерфейс — скинь на гитхаб!

anonymous
()
Ответ на: комментарий от anonymous

Вот тебе задача. Есть конфиг:

{
  data : {
    a : 1, 
    b : 2, 
    c : 3, 
    d : 4
  },
  results : {
    sum : "a,b,c",
    avg : "d,b",
    min : "a,c,d"
    max : "a,c"
  }
}
Надо вывести sum, avg, min, max. Формат конфига может быть любой, если тошнит от жсон, важны имена полей.

crutch_master ★★★★★
()
Последнее исправление: crutch_master (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Не нужно, потому что там ничего такого не может быть, чтобы выдавать default_value

И «сколько там будешь копипастить», чтобы ловить KeyError? В нормальном языке в таком случае вернется отциональный тип T | None. А главное, если забудешь проверить на None, компилер не даст работать с T

Deleted
()
Последнее исправление: Deleted (всего исправлений: 1)
Ответ на: комментарий от crutch_master

Вот тебе задача.

Ну и зачем тебе здесь мягкий код? Распарсил значения из results (это один хрен надо сделать), подставил соответствующие данные из data. Код на плюсах и JS будет почти одинаков, за исключением JSON.

anonymous
()
Ответ на: комментарий от anonymous
var cfg = {
  data : {
    a : 1, 
    b : 2, 
    c : 3, 
    d : 4
  },
  results : {
    sum : "a,b,c",
    avg : "d,b",
    min : "a,c,d",
    max : "a,c"
  }
}

var func = {}
func = {
    sum : a=>a.reduce((a,c)=> a + c),
    avg : a=>func.sum(a) / a.length,
    min : a=>Math.min(...a),
    max : a=>Math.max(...a)
}

for (let [f, args] of Object.entries(cfg.results)) {
    let arr = [];
    args.split(",").forEach(v=>arr.push(cfg.data[v]));
    console.log(f, func[f](arr));
}
//Выхлоп
//sum 6
//avg 3
//min 1
//max 3
crutch_master ★★★★★
()
Ответ на: комментарий от anonymous

Код на плюсах и JS будет почти одинаков, за исключением JSON

Показывай. У меня заняло это 12 минут от постановки задачи до решения, условимся на том, что конфиг всегда валидный. Код пишется быстро для конфига любой длинны.

crutch_master ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.