Я начинаю с этого места, чтобы оставлять заметки о вещах, которые следует обязательно учитывать при проверке согласованности API в Julia 1.0.
[x] Приоритет конвенций. Перечисление и расстановка приоритетов наших соглашений о том, что приходит в первую очередь с точки зрения аргументов функций для do-блоков, аргументов ввода-вывода для функций, которые печатают, вывода для функций на месте и т. Д. 19150).
[] Позиционные аргументы против ключевых слов. Давным-давно у нас не было аргументов ключевого слова. Их по-прежнему иногда избегают из соображений производительности. Мы должны делать этот выбор, основываясь на том, что делает API лучшим, а не на таком историческом багаже (необходимо также решить проблемы с производительностью ключевых слов, чтобы это больше не рассматривалось).
[] Инструменты метапрограммирования. У нас есть много инструментов, таких как @code_xxx
которые работают в паре с такими базовыми функциями, как code_xxx
. Они должны вести себя последовательно: одинаковые подписи, если есть функции с похожими подписями, убедитесь, что у них похожие версии макросов. В идеале все они должны возвращать значения, а не одни возвращающие значения и другие результаты печати, хотя это может быть сложно для таких вещей, как код LLVM и код сборки.
[] IO <=> эквивалентность имени файла. Обычно мы разрешаем передавать имена файлов в виде строк вместо объектов ввода-вывода, и стандартным поведением является открытие файла в соответствующем режиме, передача полученного объекта ввода-вывода той же функции с теми же аргументами, а затем обеспечение того, чтобы объект ввода-вывода после этого закрывается. Убедитесь, что все соответствующие функции приема-вывода следуют этому шаблону.
[] API редукторов. Убедитесь, что редукторы имеют последовательное поведение - все перед редукцией принимают функцию карты; аргументы конгруэнтной размерности и т. д.
[] Аргументы размеров. Последовательная обработка входных аргументов «вычислить по этому [этим] измерению [ам]», какие типы разрешены и т.д.
[] Мутирующие / не мутирующие пары. Убедитесь, что неизменяющие функции связаны с изменяющими функциями там, где это имеет смысл, и наоборот.
[] Кортеж против vararg. Убедитесь, что существует общая согласованность между тем, принимают ли функции кортеж в качестве последнего аргумента или vararg.
[] Объединения против значений NULL против ошибок. Согласованные правила относительно того, когда функции должны выдавать ошибки, а когда они должны возвращать значения Nullables или Unions (например, синтаксический анализ / анализ, сопоставление и т. Д.).
[] Поддерживайте генераторы как можно шире. Убедитесь, что любая функция, которая может разумно работать с генераторами, работает именно так. Мы уже неплохо разбираемся в этом, но я предполагаю, что мы упустили несколько.
[] Выбор типа вывода. Будьте последовательны в том, должны ли API "выходного типа" быть с точки зрения типа элемента или общего типа контейнера (ref # 11557 и # 16740).
[x] Выберите имя. Есть несколько функций / операторов с псевдонимами. Я думаю, что это нормально в тех случаях, когда одно из имен не является ASCII и предоставляется версия ASCII, поэтому люди все еще могут писать код в чистом ASCII, но есть также такие случаи, как <:
который является псевдонимом для issubtype
где оба имени - ASCII. Мы должны выбрать одно и исключить другое. Мы устарели is
в пользу ===
и должны поступить аналогичным образом.
[] Согласованность со структурами данных . Это несколько выходит за рамки Base Julia, но мы должны убедиться, что все коллекции в DataStructures имеют согласованные API с API, предоставляемые Base. Связь в другом направлении заключается в том, что некоторые из этих типов могут повлиять на то, как мы закончим разработку API в Base, поскольку мы хотим, чтобы они расширялись плавно и последовательно.
[] NaN против DomainErrors. См. Https://github.com/JuliaLang/julia/issues/5234 - разработайте политику, определяющую, когда что делать, и убедитесь, что она соблюдается последовательно.
[] Сборник <=> генератор. Иногда вам нужна коллекция, иногда вам нужен генератор. Мы должны пройти через все наши API и убедиться, что есть вариант для обоих, где это имеет смысл. Давным-давно существовало соглашение использовать имя в верхнем регистре для версии генератора и имя в нижнем регистре для версии, которая стремится и возвращает новую коллекцию. Но никто никогда не обращал на это внимания, так что, возможно, нам нужна новая конвенция.
[] Функции высшего порядка на ассоциативах. В настоящее время некоторые функции высшего порядка перебирают ассоциативные коллекции с сигнатурой (k,v)
- например, map
, filter
. Другие перебирают пары, то есть с сигнатурой kv
, требуя, чтобы тело явно деструктурировало пару на k
и v
- например, all
, any
. Это следует пересмотреть и согласовать.
[x] Преобразование против построения. При необходимости разрешите преобразование. Например, было несколько проблем / вопросов по поводу convert(String, 'x')
. В общем, преобразование подходит, когда есть одно каноническое преобразование. Преобразование строк в числа в общем случае нецелесообразно, потому что существует множество текстовых способов представления чисел, поэтому вместо этого нам нужно выполнять синтаксический анализ с параметрами. Однако существует единственный канонический способ представления номеров версий в виде строк, поэтому мы можем их преобразовать. Мы должны применять эту логику осторожно и повсеместно.
[] Проверить полноту API коллекций. Нам следует взглянуть на стандартные библиотечные функции для коллекций, предоставляемых другими языками, и убедиться, что у нас есть способ выразить общие операции, которые они выполняют. Например, у нас нет функции flatten
или concat
. Наверное, стоит.
[] Нижний аудит.
Приносим извинения, если это не подходящее место для упоминания об этом, но было бы неплохо, чтобы в будущем в именах функций были более согласованы символы подчеркивания.
Нет, это хорошее место для этого. И да, мы должны стремиться исключить все имена, в которых необходимо подчеркивание :)
Для второго пункта @tkelman см. Https://github.com/JuliaLang/julia/issues/19150
Также недавно был Джулеп относительно API для find
и связанных функций: https://github.com/JuliaLang/Juleps/blob/master/Find.md
Должны ли мы отказаться от put!
и take!
на каналах (и, возможно, сделать то же самое для фьючерсов), поскольку на них есть push!
и shift!
? Просто предлагаю удалить 2 лишних слова в API.
Я подозреваю, что shift!
удобен для пользователя. Кандидат fetch!
у нас уже есть fetch
который является неизменяемой версией take!
исх # 13538 # 12469
@amitmurthy @malmaud
Изменить: имеет смысл даже повторно использовать send
и recv
на каналах. (Я удивлен, что на данный момент они используются только для UDPSockets)
+1 за замену put!
/ take!
на push!
/ fetch!
Я добавлю переименование @inferred
в @test_inferred
.
Еще раз проверьте, соответствуют ли специализации более универсальным функциям, т.е. не что-то вроде # 20233.
Просмотрите все экспортированные функции, чтобы проверить, можно ли исключить какие-либо из них, заменив их множественной отправкой, например print_with_color
Типичное сочетание push!
и shift!
при работе со структурой данных, подобной очереди.
Если мы не собираемся использовать типичное сочетание имен для такой структуры данных, потому что мы обеспокоены тем, что операция влечет за собой накладные расходы на связь, которые неадекватно передаются этими именами, тогда я не думаю, что push!
тоже имеет смысл. send
и recv
действительно могли бы быть лучше.
Возможно, еще раз проверьте, есть ли общая согласованность между тем, принимают ли функции кортеж в качестве последнего аргумента или vararg.
Возможно, слишком велик для этой проблемы, но было бы хорошо иметь последовательные правила, определяющие, когда функции должны выдавать ошибки и когда они должны возвращать Nullable
s или Union
s (например, parse
/ tryparse
, match
и т. Д.)
Нет проблем, @simonbyrne - это список для стирки.
Кстати: это не совсем для конкретных изменений (например, переименование определенных функций) - это больше о том, что мы можем проверить. Для конкретных предлагаемых изменений просто откройте вопрос, предлагающий это изменение.
У нас есть много инструментов, таких как @code_xxx, которые связаны с базовыми функциями, такими как code_xxx
Не уверен, что вы об этом говорите, но посмотрите CreateMacrosFrom.jl
Документируйте все экспортированные функции (включая тесты)
Если это часть этого, то, возможно, также: не забудьте пометить свои тесты номером проблемы / PR. Так становится намного проще понять, зачем нужен этот тест. Я знаю, как работает git blame, но при добавлении тестовых наборов (просто для примера) иногда остается загадкой, что именно тестируется, и было бы здорово, если бы всегда был номер проблемы / PR.
@dpsanders : и экспортированные макросы! например, @fastmath
не имеет строки документации.
Это очень незначительно, но функции string
и Symbol
делают почти одно и то же и имеют разные заглавные буквы. Я думаю, что symbol
будет иметь больше смысла.
@amellnik Разница в том, что Symbol
- это конструктор типа, а string
- обычная функция. IIRC у нас был symbol
но он устарел в пользу конструктора типа. Я не уверен, что для этого необходимы изменения, но я думаю, что мы должны использовать конструктор String
вместо string
.
во всяком случае, я думаю, мы должны использовать конструктор String вместо строки.
Нет, это разные функции, и их не следует объединять
julia> String(UInt8[])
""
julia> string(UInt8[])
"UInt8[]"
Нет, это разные функции, и их не следует объединять
Это похоже на ситуацию, когда string(args...)
следует просто устареть в пользу sprint(print, args...)
, тогда - наличие string
и String
сбивает с толку. Мы могли бы специализироваться на sprint(::typeof(print), args...)
чтобы восстановить любую потерянную производительность. В этой связи также может иметь смысл отказаться от repr(x)
для sprint(showall, args...)
.
Звучит нормально, хотя вызов string
для преобразования чего-либо в строку кажется довольно стандартным ....
вызов строки для преобразования чего-либо в строку кажется довольно стандартным
Да, но именно здесь возникает разрыв между String
и string
.
sprint(print, ...)
кажется лишним. Если мы избавимся от string
, мы можем переименовать sprint
в string
чтобы получить string(print, foo)
и string(showall, foo)
что, на мой взгляд, хорошо читается. .
Это может быть тот случай, когда согласованность переоценена. Я думаю, что это нормально, если string(x)
означает «просто дайте мне строковое представление x». Если это будет сложнее, например, требуется указать, какую функцию печати использовать, тогда имеет смысл использовать другое имя, например sprint
.
Также было бы нормально переименовать String(UInt8[])
во что-нибудь другое и использовать String
вместо string
. string
дает нам немного больше гибкости в будущем, чтобы изменить тип возвращаемой строки, но это маловероятно.
Имеет ли смысл reinterpret(String, ::Vector{UInt8}
вообще, или это каламбур на reinterpret
?
В этом есть смысл.
Проблема в том, что эта функция иногда копирует, поэтому это название вводит в заблуждение.
Верно, но предполагается, что строки должны быть неизменяемыми, так что нам, вероятно, это сойдет с рук.
Существует также метод String(::IOBuffer)
, но похоже, что он может быть устаревшим до readstring
.
Я тоже думал о предлагаемом вами изменении API, но интерфейс string(a, b...)
заключается в том, что он структурирует и объединяет свои аргументы, и это приведет к раздражающему исключению ошибок для вызываемых первых аргументов. Если мы удалим конкатенацию из string
тогда она может заработать.
Да, согласен; последовательность и избегание ошибок является наиболее важным.
Обратите внимание на проблемы № 18326 и № 3893 в категории «аргументы измерения».
Если я могу заняться другим вопросом: убедиться, что поведение контейнеров изменяемых файлов задокументировано и согласовано.
@ JaredCrean2 : не могли бы вы
Я конечно надеюсь, что это не связано с созданием множества «защитных копий».
Например, если у меня есть массив изменяемых типов и я вызываю на нем sort
, указывает ли возвращаемый массив на те же объекты, что и входной массив, или он копирует объекты и делает возвращаемый массив точкой на их?
Те же объекты. Я почти уверен, что все наши методы сортировки коллекций, getindex, фильтрации, поиска и т. Д. Следуют этому правилу, не так ли?
Я не думаю, что в этом вопросе есть недостаток ясности или последовательности - это всегда одни и те же объекты.
Фактически, я думаю, что единственной стандартной функцией, где это не так, является deepcopy
где все дело в том, что вы получаете все новые объекты.
Это где-то задокументировано?
Нет, мы могли бы, но я не уверен, где лучше всего это задокументировать. Зачем функциям делать копии без надобности? Откуда у вас создалось впечатление, что они могут?
Здравствуйте. Я не встречал никаких замечаний по поводу сериализации данных.
Рано или поздно программы julia будут написаны и запущены публично, данные начнут иногда расслаиваться на долгие годы. Сериализация данных, например. цепочка: объект в байты, управляемая типом (возможно, через json или ...), должна быть построена, чтобы быть устойчивой по времени. Подумайте о семантическом управлении версиями и веб-API.
Можно ли ожидать, что сериализация пользовательских данных останется близкой к https://github.com/JuliaLang/julia/blob/v0.5.1/base/serialize.jl ?
Зачем функциям делать копии без надобности? Откуда у вас создалось впечатление, что они могут?
Не знаю, знают они или нет. Насколько я могу судить, поведение не определено. Из комментария @JeffBezanson видно , что есть люди, которые выступают за создание защитных копий, а он выступает против. Так что документация должна где-то касаться вопроса защитных копий.
Кажется, вы подразумеваете какой-то принцип наименьшего действия, но в зависимости от деталей алгоритма, что такое наименьшее действие, становится неоднозначным. Я думаю, что для обеспечения единообразия API требуется более конкретное руководство.
@ o314 : это проблема проверки согласованности API, я не уверен, как связана сериализация.
@ JaredCrean2 : необходимо
Я говорю о том, что более глубокие объекты никогда не копируются, кроме как методом deepcopy (очевидно).
Недавно это обсуждалось в контексте copy
для некоторых оболочек массива, например SubArray
и SparseMatrixCSC
но также Symmetric
, LowerTriangular
. Мне кажется, что в соответствии с вышеупомянутой политикой copy
не будет для таких типов оболочки. Правильный ли уровень абстракции здесь упоминается в политике? Например, я думаю, это подразумевает, что если Array
s были реализованы в Julia (упаковка буфера), поведение copy
на Array
s должно измениться на noop.
Если существует соглашение, что более глубокие объекты никогда не копируются, то остается только задокументировать это. Документация - действительно важная часть API. Такое поведение может показаться вам очевидным (возможно, потому, что вы написали часть кода), но со стороны это не так очевидно.
Изменить: не видел сообщение Андреаса. Это интересное соображение.
@StefanKarpinski Я согласен с вашей точкой зрения.
И все основные темы, затронутые здесь, очень хорошие и умные.
Но иногда я немного опасаюсь балансировки между процессом и данными в Julia:
Мы можем легко позвонить в fortran или c,
Но будет ли код так же легко развернут в современном центре обработки данных, например. aws лямбда с его функцией как шаблон службы. будет ли код легко вызываться через Интернет, откройте API?
Иногда нужно снизить функциональную нагрузку до масштабирования (без общих, без vaargs в сигнатуре функции, без высокого порядка в общедоступном API) и более систематически связывать данные позади (схема json / openapi).
Я видел, как вот так тонет очень хорошая библиотека Python, и это очень жаль.
Я считаю, что для языка 1.0 крайне важно сохранять сбалансированность и модульность данных и функций, чтобы их можно было легко развертывать в Интернете. И для этой функции интерфейс должен быть меньше ориентирован на домашних животных и больше ориентирован на скот, когда это необходимо.
Может быть, суть не в этом.
@StefanKarpinski Возможно, я неправильно понял ваш пост. Когда ты сказал
копируется ли объект верхнего уровня или нет, безусловно, необходимо задокументировать
что означает «объект верхнего уровня»? Если у меня есть x::Vector{MyMutableType}
, это объект верхнего уровня x
или элементы x
?
Объект верхнего уровня относится к самому x
, а не к элементам x
.
@andreasnoack Понятие объекта верхнего уровня должно относиться к реализованной абстрактной структуре, а не к деталям реализации.
может быть, добавить float
и другую аналогичную функцию, которая действует как на типы, так и на значения?
Если заглянуть в примечания к выпуску 0.6, то кажется странным, что добавлено iszero(A::Array{T})
, в то время как многие другие функции (например, sumabs
, isinteger
, isnumber
) над массивами устарело в пользу all(f,A)
.
Есть нулевые массивы, и они являются нулевыми элементами в своем векторном пространстве. iszero
общем случае проверяет, является ли что-то аддитивным обратным, каковыми являются нулевые массивы.
Re. согласованность символов подчеркивания в именах функций, вот навигационная цепочка к count_ones
и count_zeros
.
Мне кажется, что если вы хотите, чтобы Julia API была согласованной, вам понадобится какое-то программное обеспечение, которое позволит вам (а) указать правила / соглашения API, (б) выполнить статический анализ кода Julia для обнаружения отклонения от этих правил / соглашений и (c) предложения. Такой инструмент принесет пользу как Julia Base, так и всем Julia Packages. Новый пакет Julia может помочь. (Язык в щеку: первое, что должен сделать этот пакет, - это предложить свое собственное имя; APICheck.jl, ApiCheck.jl, API_Check.jl, APIChecker.jl, JuliaAPIChecker.jl и т. Д.) Я новичок в Джулии, так что не хочу брать на себя инициативу в таких вещах. Однако я не прочь внести свой вклад. Есть предложения, как это сделать?
Нам бы очень хотелось, чтобы это было в Lint.jl!
num2hex
и hex2num
(# 22031 и # 22088)
Я тоже считаю, что Lint.jl - правильный пакет для проверки согласованности API Julia. Но если мы пойдем по этому пути, первоначальный список Стефана должен быть намного точнее. Например, когда он пишет «мы должны убедиться, что все коллекции в DataStructures имеют согласованные API», на ум приходят следующие вопросы:
Чтобы управлять такими инвентаризацией и анализом, мы могли бы добавить проект в репозиторий Julia (проект № 8), или в репозиторий JuliaPraxis (предложенный TotalVerb в автономном режиме), или в репозиторий Lint. В этом случае нам нужно будет разобраться, кому будет принадлежать такой проект, какие люди должны быть задействованы с самого начала и кто должен принимать окончательные решения о том, каковы на самом деле соглашения Джулии (для целей линтинга).
Но прежде чем продолжить в этом направлении, я хотел бы спросить
Я согласен с тем, что конкретное указание на это - хорошая идея. Выяснение того, каким должен быть этот список, является частью работы здесь - если вы хотите взломать его, это было бы здорово.
Действительно ли нам нужны Base.datatype_module и Base.function_module?
Унифицированный функциональный «модуль» (возможно, getmodule), рассылающий по типу данных и функции, мне кажется более последовательным.
А как насчет подчеркивания в @code_typed
и друзьях?
Это хорошая возможность для рефакторинга (указанная причина запрета подчеркивания). У вас может быть макрос @code
с первым аргументом, который является типом кода, который вы хотите.
( @bramtayl , пожалуйста, не забудьте поставить обратные кавычки вокруг макросов, так как это пингует "код" пользователя github, если нет; @code
)
FWIW, завершение табуляции работает только с именами функций. Уметь делать @code_<TAB>
- это хорошо ....
Если рефакторинг рассматривается, но отклоняется, то вопрос о том, есть ли символы подчеркивания или нет, заключается в том, что единственный пункт запрета подчеркивания - это поощрение рефакторинга. На самом деле, в этом случае, похоже, следует поощрять подчеркивание, чтобы сделать язык более понятным.
Недостаточный аудит.
Контрпредложение: мы по-прежнему проверяем эти имена, но вместо этого добавляем дополнительные подчеркивания там, где это упростит чтение кода (codetyped vs code_typed, isos2 vs is_os2).
Я не сторонник абсолютизма. Я думаю, что code_typed
в порядке, полезно использовать табуляцию, как указывает @KristofferC , и на самом деле нет ничего очевидного, что можно было бы передать в качестве аргумента для выбора, какой результат вы хотите.
Мне кажется, что корабль поплыл с добавлением дополнительных подчеркиваний, так как нам пришлось бы отказаться от почти половины Base. Например, есть 74 функции-предиката, которые начинаются с is
и только 6 начинаются с is_
. Что имеет больше смысла, отказаться от 6 или 74?
Хорошо, здесь несколько противоречивых целей:
1) Делаем имена более читабельными
2) Уменьшение оттока кода
3) Поощрение рефакторинга
Устранение подчеркивания путем объединения слов не удается на всех трех фронтах.
То, что методы show
принимающие поток, не являются !
-завершенными, кажется несовместимым с обычным соглашением? Ref. https://github.com/JuliaLang/julia/pull/22604/commit/db9d70a279763ded5088016d9c3d4439a49e3fca#r125115063. Лучший! (Изменить: я полагаю, это соответствует write
методам, принимающим поток.)
Несоответствия с API трейтов. Некоторые черты вычисляются путем вызова такой черты, как
TypeArithmetic(Float64)
в то время как другие эту функцию нужно писать в нижнем регистре:
iteratorsize(Vector{Float64})
Попробуйте переименовать size
-> shape
(xref # 22665)
Array{T,1}()
вероятно, тоже следует устареть:
julia> Array{Int,1}()
0-element Array{Int64,1}
julia> Array{Int,2}()
WARNING: Matrix{T}() is deprecated, use Matrix{T}(0, 0) instead.
Долго думали о коллекциях. В основном у нас есть три вида:
k=>v
.Я стал скептически относиться к диктатному поведению. Канарейка в угольной шахте - это map
, где работа с парами "ключ-значение" неестественна, поскольку обычно вы не хотите менять набор ключей. Для массивов и dicts также возможно реализовать один и тот же интерфейс:
keys
соответствует eachindex
mapindexed
и filterindexed
будут полезны как для словарей, так и для массивов. Они похожи на map и filter, за исключением того, что также передают вашей функции индекс рассматриваемого элемента.pairs
, который в основном является ярлыком для zip(keys(c), values(c))
.Подумайте о переименовании ind2sub
и sub2ind
, которые, по-видимому, являются матлабизмами и имеют не-юлианское и странное имя для пользователя, не использующего Matlab. Возможные имена: indice
и linearindice
соответственно. Я не решился делать пиар, потому что не уверен, что люди об этом думают, но сделаю, если будет поддержка.
То же самое с rad2deg
и deg2rad
.
Ref. # 22791 ( select
-> partialsort
). Лучший!
Я не видел здесь одного: идут ли необязательные позиционные аргументы первыми или последними? Иногда необязательные позиционные аргументы идут первыми, как в sum(f, itr)
и rand([rng,] ..)
. Но в других местах они идут последними, например, в median(v[, region])
или split(s::AbstractString[, chars])
. Иногда они могут идти первым или последним, но не одновременно! (Например, mean
может первой принимать функцию или последнее измерение, но не оба сразу.)
Текущая семантика языка заставляет необязательные аргументы идти последними: вы можете написать f(a, b=1)
но не f(b=1, a)
. Но если все необязательные аргументы идут последними, что происходит с удобными блоками do?
По крайней мере, небольшая проблема в том, что язык должен определять такие методы, как rand.jl
: shuffle!(a::AbstractVector) = shuffle!(GLOBAL_RNG, a)
. Синтаксис необязательного позиционного аргумента должен учитывать именно этот вариант использования.
Может быть, стоит выделить отдельную тему, но кажется возможным переместить необязательные аргументы куда угодно. Так, например, f(a = 1, b, c = 2)
будет определять f(x) = f(1, x, 2)
и f(x, y) = f(x, y, 2)
xref # 22460 для (непопулярной) попытки включить аргументы по умолчанию в любой позиции.
Возможно, переименуйте warn
в warning
(Matlab также использует это), не имеет большого значения, но подумал, что упомянул?
Мне нравится warn
потому что это глагол, например throw
.
Меня это очень смутило:
julia> f(;a=1,b=1) = a+b
f (generic function with 1 method)
julia> f(a=4,5) # I intended to write f(a=4,b=5)
ERROR: MethodError: no method matching f(::Int64; a=4)
Closest candidates are:
f(; a, b) at REPL[13]:1
Я предлагаю разрешать только ключевые слова последними при вызове функций, аналогично определению функций ключевых слов.
Я предлагаю разрешать только ключевые слова последними при вызове функций, аналогично определению функций ключевых слов.
Существует множество API-интерфейсов, в которых передача ключевых слов в другие позиции одновременно полезна и эргономична.
Из любопытства, существует ли определенный порядок оценки для позиционных аргументов и аргументов ключевых слов? Я видел несколько более старых проблем, и https://docs.julialang.org/en/latest/manual/functions/#Evaluation -Scope-of-Default-Values-1 говорит об объемах, но ничего из того, что я нашел, не указывает, например, аргументы оцениваются слева направо, или все позиционные аргументы оцениваются перед всеми аргументами ключевого слова, или если нет определенного порядка оценки (или что-то еще).
@yurivish , ключевые слова см. в документации (также https://github.com/JuliaLang/julia/issues/23926). Для необязательных история немного сложнее, может быть, почитайте здесь . (Обратите внимание, что вопросы лучше задавать на https://discourse.julialang.org/)
Кажется, это не стоит того, но мне всегда кажется странным, что bits(1)
возвращает String
, похоже, это должно быть BitVector
или Vector{Bool}
.
Я хотел бы предложить обзор таблиц методов, которые отправляются по Function
или Callable
. Давайте попробуем убедиться, что эти API-интерфейсы являются такими, какими мы их хотим… и что мы не упускаем возможности разрешить реструктуризацию таблиц таким образом, чтобы мы могли позволить утиный вызов любого объекта.
Что касается all
и any
, их кажется несложным для устаревания до all(f(x) for x in xs)
, которое уже сокращено до all(Generator(f, xs))
и поэтому не должно иметь накладных расходов.
Не уверен , если это то , что вы имели в виду , но я понял , что стоит о том , на всякий случай: я хардкорный против протестующий любые API - интерфейсы функционального стиля для генераторов. У нас есть any(f, x)
и all(f, x)
и они широко используются; -10000000 за удаление тех (или каких-либо подобных методов, правда).
Я про генератор. Похоже на фундаментальный строительный блок ленивого программирования, и его следует экспортировать. all(Generator(f, xs))
иногда удобнее для определенных функций, чем all(f(x) for x in xs)
. Также +10000000 для восстановления баланса
Я предпочитаю использовать здесь меньше синтаксиса, если это возможно. Если легко, легко и эффективно выразить идею «взять xs, применить f ко всему и вернуть истину, если все это истинно», то почему мы должны объединить ее в один глагол?
Если вас беспокоит ненужное существительное x
в f(x) for x in xs
, тогда предложение @bramtayl об экспорте Generator
(возможно, с использованием лучшего имени, например Map
?) имеет смысл.
Такие вещи, как all(isnull, x)
, намного проще, чем all(isnull(v) for v in x)
. Мы исключили функцию allnull
из NullableArrays в пользу all(isnull, x)
; если бы этот синтаксис исчез, нам, вероятно, пришлось бы его снова ввести.
Как насчет переименования strwidth
в stringwidth
(я думаю, что это единственная экспортируемая функция манипулирования строкой, которая имеет сокращенную строку до str)
На самом деле он был переименован в textwidth
(https://github.com/JuliaLang/julia/pull/23667).
ИМО, эта проблема слишком обширна, чтобы включать в себя отметку 1.0, учитывая, что мы хотим в ближайшее время заморозить функцию. Нам может потребоваться несколько владельцев и назначить для проверки наборы функций, если мы захотим это сделать.
Кроме того, это еще одно место, где FemtoCleaner может автоматически обновлять многие вещи после версии 1.0, хотя было бы неплохо все исправить.
просто комментарий по ширине текста:
INFO: Testing Cairo
Test Summary: | Pass Total
Image Surface | 7 7
Test Summary: | Pass Total
Conversions | 4 4
Test Summary: | Pass Total
TexLexer | 1 1
WARNING: both Compat and Cairo export "textwidth"; uses of it in module Main must be qualified
Samples : Error During Test
Got an exception of type LoadError outside of a <strong i="6">@test</strong>
LoadError: UndefVarError: textwidth not defined
Stacktrace:
[1] include_from_node1(::String) at .\loading.jl:576
[2] include(::String) at .\sysimg.jl:14
[3] macro expansion at C:\Users\appveyor\.julia\v0.6\Cairo\test\runtests.jl:86 [inlined]
[4] macro expansion at .\test.jl:860 [inlined]
[5] anonymous at .\<missing>:?
[6] include_from_node1(::String) at .\loading.jl:576
[7] include(::String) at .\sysimg.jl:14
[8] process_options(::Base.JLOptions) at .\client.jl:305
[9] _start() at .\client.jl:371
while loading C:\Users\appveyor\.julia\v0.6\Cairo\samples\sample_pango_text.jl, in expression starting on line 28
Сообщение об ошибке кажется довольно ясным, в чем проблема? Cairo
нужно расширить базовый метод.
help?> Base.textwidth
No documentation found.
Binding Base.textwidth does not exist.
julia> versioninfo()
Julia Version 0.6.0
julia> Compat.textwidth
textwidth (generic function with 2 methods)
Я не сомневался, что сообщение (которое я получил через Travis) в порядке, но почему Compat экспортирует ширину текста, если его нет в 0.6?
Потому что в этом смысл Compat? Тем не менее, это обсуждение очень сильно выходит за рамки, поэтому я предлагаю продолжить его на дискурсе или расслаблении.
Я предлагаю заменить copy
на shallowcopy
и deepcopy
на copy
поскольку недавно мне потребовалось довольно много времени, чтобы понять, что копия является «поверхностной» копией, а Функция, которую я написал, изменяла массив массивов. Думаю, было бы гораздо более интуитивно понятным, если бы copy
выполнял бы "глубокую" копию, а что-то вроде shallowcopy
использовалось для мелких копий? Теперь я знаю. когда использовать deepcopy
, но я думаю, что многие другие пользователи столкнутся с той же проблемой.
Давайте постараемся сохранить эту проблему для согласованности API, а не для сбора «конкретных вещей, которые мне не нравятся».
Associative
имя кажется совершенно несовместимым со всеми другими именами типов в Julia.
Во-первых, типы обычно не являются прилагательными. Существительное Association
используется, по крайней мере, в некоторых найденных мною документах по системе Mathematica.
Я думаю, что AbstractDict
будет гораздо более согласованным с другими типами, такими как AbstractArray
, AbstractRange
, AbstractSet
и AbstractString
, каждый из которых имеет прототипы конкретных типов Dict
, Array
, Range
, Set
и String
.
Наши типы исключений встречаются повсюду: одни называются FooError
, другие называются BarException
; некоторые из них экспортируются, большинство - нет. Для единообразия можно использовать сквозной проход.
Итак, что было бы предпочтительнее, FooError
или BarException
? Экспортируется или нет?
Для меня BarException
подразумевает какую-то схему рейза / ловли.
Я предпочитаю многое, и некоторые другие в функциональном мире тоже используют шаблон Some
/ None
(*), где поток управления более прямой и предсказуемый.
Итак, +1 за FooError
(*) Some
/ Void
ex Optional
в julia # 23642.
Эти вещи все еще находятся на столе после того, как функция зависла? Я особенно хотел бы заняться необязательными аргументами и аргументами ключевого слова, но список функций с несколькими необязательными аргументами (самый ясный случай использования вместо них аргументов ключевого слова) довольно длинный.
Пожалуйста, взгляните! У меня не было возможности систематически рассматривать эти вопросы.
Кстати, я заметил непоследовательность в именовании признаков: у нас есть iteratorsize
, iteratoreltype
, но IndexStyle
, TypeRangeStep
, TypeArithmetic
и TypeOrder
. Похоже, что варианты CamelCase более многочисленны и более свежие, так что, может быть, нам следует принять это соглашение повсюду?
Их обязательно нужно сделать последовательными. Хотите устроить пиар?
Я думаю, это следует исправить в рамках https://github.com/JuliaLang/julia/pull/25356.
РЕДАКТИРОВАТЬ: см. Также https://github.com/JuliaLang/julia/issues/25440
В основном это делается или может быть сделано в версиях 1.x. Я могу обновить флажки, но мы просто просмотрели их при вызове сортировки, и все, кроме # 25395 и аудита подчеркивания, выполнено.
Ниже приводится анализ всех символов, экспортированных из Base, которые содержат подчеркивания, не являются устаревшими и не являются строковыми макросами. Здесь главное отметить, что это только экспортированные имена; сюда не входят неэкспортированные имена, которые мы говорим людям называть квалифицированными.
Я разделил вещи по категориям. Надеюсь, это больше полезно, чем раздражает.
У нас есть следующие макросы с соответствующими функциями:
@code_llvm
, code_llvm
@code_lowered
, code_lowered
@code_native
, code_native
@code_typed
, code_typed
@code_warntype
, code_warntype
Любое изменение, примененное к макросам, если оно есть, должно аналогичным образом применяться к функциям.
module_name
-> nameof
(# 25622)module_parent
-> parentmodule
(# 25629, см. # 25436 для предыдущей попытки переименования)method_exists
-> hasmethod
(# 25615)object_id
-> objectid
(# 25615)pointer_from_objref
pointer_from_objref
возможно, можно было бы использовать с более описательным именем, может быть, что-то вроде address
?
Псевдонимы типов, содержащие символы подчеркивания: C_NULL
, Cintmax_t
, Cptrdiff_t
, Csize_t
, Cssize_t
, Cuintmax_t
и Cwchar_t
. Те, которые заканчиваются на _t
должны остаться, так как они названы в соответствии с их соответствующими типами C.
C_NULL
здесь необычный, поскольку это единственный псевдоним C, содержащий подчеркивание, которое не отражается в C (поскольку в C это всего лишь NULL
). Мы могли бы назвать это CNULL
.
C_NULL
count_ones
count_zeros
trailing_ones
trailing_zeros
leading_ones
leading_zeros
Обсуждение их переименования см. # 23531. Я очень поддерживаю удаление подчеркиваний для них, а также некоторые из предлагаемых замен в этом PR. Я думаю, это нужно пересмотреть.
unsafe_copyto!
unsafe_load
unsafe_pointer_to_objref
unsafe_read
unsafe_store!
unsafe_string
unsafe_trunc
unsafe_wrap
unsafe_write
Вероятно, это нормально - оставить все как есть; уродство подчеркивания еще больше подчеркивает их небезопасность.
broadcast_getindex
broadcast_setindex!
to_indices
Судя по всему, существуют broadcast_getindex
и broadcast_setindex!
. Я не понимаю, что они делают. Может быть, они могли бы использовать более описательное имя?
Интересно, что версия с одним индексом to_indices
, Base.to_index
не экспортируется.
catch_backtrace
catch_stacktrace
-> stacktrace(catch_backtrace())
(# 25615)Предположительно, это catch
блочные эквиваленты backtrace
и stacktrace
соответственно.
current_task
task_local_storage
disable_sigint
reenable_sigint
process_exited
process_running
redirect_stderr
redirect_stdin
redirect_stdout
nb_available
-> bytesavailable
(# 25634)Было бы неплохо иметь более общую функцию перенаправления IO
-> IO
в которой все это можно было бы объединить, например, redirect(STDOUT, io)
, тем самым удалив как подчеркивания, так и экспорт.
promote_rule
promote_shape
promote_type
См. # 23999 для соответствующего обсуждения promote_rule
.
print_with_color
-> printstyled
(см. # 25522)print_shortest
(см. № 25745)escape_string
(см. # 25620)unescape_string
escape_string
и unescape_string
немного странны в том смысле, что они могут печатать в поток или возвращать строку. См. # 25620 для предложения переместить / переименовать их.
include_dependency
include_string
include_dependency
. Используется ли это вообще вне базы? Я не могу представить себе ситуацию, когда вы бы хотели это вместо include
в любом типичном сценарии.
include_string
. Разве это не просто официально санкционированная версия eval(parse())
?
gc_enable
-> GC.enable
(# 25616)get_zero_subnormals
set_zero_subnormals
time_ns
get_zero_subnormals
и set_zero_subnormals
можно использовать с более информативными именами. Их нужно экспортировать?
+1 за method_exists => methodexists
и object_id => objectid
. Также глупо, что catch_stacktrace
вообще существует. Его можно объявить устаревшим согласно его определению, stacktrace(catch_backtrace())
.
Как мы относимся к уменьшению подчеркивания C_NULL
? Я уже привык к этому, но я также согласен с аргументом, что ни одно из других имен C*
не имеет подчеркивания.
Остальные имена C - это типы, а C_NULL
- константа. Я думаю, что это хорошо, и следует соблюдать правила именования.
и следует правилам именования.
Как же так?
Константы часто заключаются в заглавные буквы с подчеркиванием - за ними следует C_NULL
. Как сказал @ iamed2 , это значение, а не тип, поэтому соглашение об именах Cfoo
не обязательно применяется.
Я ошибочно думал, что https://github.com/JuliaLang/julia/blob/master/doc/src/manual/variables.md#stylistic -conventions ссылается на константы, но это не так. Вероятно, так и должно быть.
Я предлагаю последовательный, математически обоснованный интерфейс для общих гильбертовых пространств, в которых векторы не являются массивами Жюлиа. Имена функций, такие как vecdot
, vecnorm
и т. Д., Вполне могут быть заменены общими концепциями inner
и norm
как описано в https: // github. com / JuliaLang / julia / issues / 25565.
Как я уже говорил несколько раз, это не общая проблема для вещей, которые нужно изменить.
Я считаю, что единственные элементы, оставшиеся под этим зонтиком для версии 1.0, - это № 25501 и № 25717.
Я бы хотел что-нибудь сделать с (get|set)_zero_subnormals
но, возможно, лучшее краткосрочное решение - просто их не экспортировать.
Вероятно, следует рассмотреть то, как числа обрабатываются в контексте операций сбора, таких как map
и collect
. Было указано, что первый возвращает скаляр, а второй возвращает массив 0D.
Самый полезный комментарий
Нижний аудит
Ниже приводится анализ всех символов, экспортированных из Base, которые содержат подчеркивания, не являются устаревшими и не являются строковыми макросами. Здесь главное отметить, что это только экспортированные имена; сюда не входят неэкспортированные имена, которые мы говорим людям называть квалифицированными.
Я разделил вещи по категориям. Надеюсь, это больше полезно, чем раздражает.
Отражение
У нас есть следующие макросы с соответствующими функциями:
@code_llvm
,code_llvm
@code_lowered
,code_lowered
@code_native
,code_native
@code_typed
,code_typed
@code_warntype
,code_warntype
Любое изменение, примененное к макросам, если оно есть, должно аналогичным образом применяться к функциям.
module_name
->nameof
(# 25622)module_parent
->parentmodule
(# 25629, см. # 25436 для предыдущей попытки переименования)method_exists
->hasmethod
(# 25615)object_id
->objectid
(# 25615)pointer_from_objref
pointer_from_objref
возможно, можно было бы использовать с более описательным именем, может быть, что-то вродеaddress
?Псевдонимы для взаимодействия с C
Псевдонимы типов, содержащие символы подчеркивания:
C_NULL
,Cintmax_t
,Cptrdiff_t
,Csize_t
,Cssize_t
,Cuintmax_t
иCwchar_t
. Те, которые заканчиваются на_t
должны остаться, так как они названы в соответствии с их соответствующими типами C.C_NULL
здесь необычный, поскольку это единственный псевдоним C, содержащий подчеркивание, которое не отражается в C (поскольку в C это всего лишьNULL
). Мы могли бы назвать этоCNULL
.C_NULL
Подсчет бит
count_ones
count_zeros
trailing_ones
trailing_zeros
leading_ones
leading_zeros
Обсуждение их переименования см. # 23531. Я очень поддерживаю удаление подчеркиваний для них, а также некоторые из предлагаемых замен в этом PR. Я думаю, это нужно пересмотреть.
Небезопасные операции
unsafe_copyto!
unsafe_load
unsafe_pointer_to_objref
unsafe_read
unsafe_store!
unsafe_string
unsafe_trunc
unsafe_wrap
unsafe_write
Вероятно, это нормально - оставить все как есть; уродство подчеркивания еще больше подчеркивает их небезопасность.
Индексирование
broadcast_getindex
broadcast_setindex!
to_indices
Судя по всему, существуют
broadcast_getindex
иbroadcast_setindex!
. Я не понимаю, что они делают. Может быть, они могли бы использовать более описательное имя?Интересно, что версия с одним индексом
to_indices
,Base.to_index
не экспортируется.Следы
catch_backtrace
catch_stacktrace
->stacktrace(catch_backtrace())
(# 25615)Предположительно, это
catch
блочные эквивалентыbacktrace
иstacktrace
соответственно.Задачи, процессы и сигналы
current_task
task_local_storage
disable_sigint
reenable_sigint
process_exited
process_running
Потоки
redirect_stderr
redirect_stdin
redirect_stdout
nb_available
->bytesavailable
(# 25634)Было бы неплохо иметь более общую функцию перенаправления
IO
->IO
в которой все это можно было бы объединить, например,redirect(STDOUT, io)
, тем самым удалив как подчеркивания, так и экспорт.Продвижение
promote_rule
promote_shape
promote_type
См. # 23999 для соответствующего обсуждения
promote_rule
.Печать
print_with_color
->printstyled
(см. # 25522)print_shortest
(см. № 25745)escape_string
(см. # 25620)unescape_string
escape_string
иunescape_string
немного странны в том смысле, что они могут печатать в поток или возвращать строку. См. # 25620 для предложения переместить / переименовать их.Загрузка кода
include_dependency
include_string
include_dependency
. Используется ли это вообще вне базы? Я не могу представить себе ситуацию, когда вы бы хотели это вместоinclude
в любом типичном сценарии.include_string
. Разве это не просто официально санкционированная версияeval(parse())
?То, что я не стал категоризировать
gc_enable
->GC.enable
(# 25616)get_zero_subnormals
set_zero_subnormals
time_ns
get_zero_subnormals
иset_zero_subnormals
можно использовать с более информативными именами. Их нужно экспортировать?