Здравствуйте, Shmj, Вы писали:
S>Вот стандартная практика — как бы по порядку. Т.е. через запятую последовательно.
S>А ведь есть более умные решения: именованные аргументы функции. Если порядок аргументов изменился, то не нужно по всему коду выискивать и исправлять.
S>Какой вариант вам удобнее?
Так, как сделано в Swift. Во всех более-менее сложных случаях есть возможность задать имена аргументам, как принудительно, так и опционально, по желанию составителя декларации функции, и порядок записывания именованных уже не важен. Обрати внимание, что можно задавать другое имя переменной для аргумента уже внутри функции, если внешне видимое неудобно.
Если я сподвигнусь на создание своего языка, такие возможности там будут обязательно присутствовать, вместе с полиморфизмом по таким именам (например, jump(meters: ) и jump(feet: ) могут быть разными функциями).
Тут самое сложное — как задавать уникальные сигнатуры на уровне линкера. Добавлять хэш от описания как-то не хочется.
Здравствуйте, Sinclair, Вы писали:
S>Здравствуйте, Shmj, Вы писали:
S>>Какой вариант вам удобнее? S>Если в функции — сорок параметров, из которых 38 необязательные, то именованные удобнее. Если в функции — два параметра, и оба обязательные, то удобнее позиционные. S>Ваш К.О.
Если в функции 40 параметров, то
во-первых, с функцией явные проблемы
во-вторых, для передачи параметров используют один объект с 40 полями
- Слава России!
— Героям СВО Слава!
Re[3]: Передача аргументов в функцию - позиционные vs именов
Здравствуйте, netch80, Вы писали: N>(голосом удава) А три — это куча?
Опять же, всё зависит от того, насколько очевидно их применение.
N>Я в одном проекте нашёл три или четыре места, где у memset() перепутали длину и заполнитель, а так в C++ это параметры оба целые, никакого плача от компилятора не было.
Вот, это прямо отличный аргумент в пользу именованных параметров в конкретном сценарии. Да ещё и такой, где очевидные альтернативные решения (например, развести типы аргументов) не работают.
N>В итоге я выдвинул правку — сделать хелпер типа
N>
N>class MemsetCaller {
N> void *mAddress;
N> size_t mLength;
N>public:
N> MemsetCaller(void *address, size_t length) : mAddress(address), mLength(length) {}
N> void fillWith(char c) { ::memset(mAddress, c, mLength); // сам проверял по ману когда это сейчас писал
N> }
N>};
N>
Да, отличное решение. Которое показывает, что и в языке с позиционными аргументами можно подстелить соломки в тех немногих местах, где хочется потребовать именованности. N>Это отличный пример, где принудительно именованные аргументы точно пригодились бы.
Не факт, что принудительно именованные аргументы привели бы к такому хорошему решению.
Обратите внимание, что вы фактически изобрели структуру Span<sbyte>, которая сама по себе архитектурно в разы лучше голых указателей.
Пригодна она далеко не только для того, чтобы вызывать fill(). А, например, и для безопасных методов вроде .slice(offset, len).
Получилось бы у вас это в языке с "принудительно именованными аргументами"? Вряд ли: вы бы просто продолжали писать
a fill: len with: '\xA5'
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: Передача аргументов в функцию - позиционные vs именов
Здравствуйте, Sinclair, Вы писали:
S>Пригодна она далеко не только для того, чтобы вызывать fill(). А, например, и для безопасных методов вроде .slice(offset, len). S>Получилось бы у вас это в языке с "принудительно именованными аргументами"?
С локальным выводом я согласен, а вот общего не понимаю.
Если тут в конкретном случае сработало "чем хуже, тем лучше", то постоянно принуждать к этому мне как-то не нравится, польза от явного именования будет точно больше.
The God is real, unless declared integer.
Re[3]: Передача аргументов в функцию - позиционные vs именов
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, Sinclair, Вы писали:
S>>Пригодна она далеко не только для того, чтобы вызывать fill(). А, например, и для безопасных методов вроде .slice(offset, len). S>>Получилось бы у вас это в языке с "принудительно именованными аргументами"?
N>С локальным выводом я согласен, а вот общего не понимаю. N>Если тут в конкретном случае сработало "чем хуже, тем лучше", то постоянно принуждать к этому мне как-то не нравится, польза от явного именования будет точно больше.
На 100000 мест, где позиционные параметры вполне Ок и не вызывают ошибок применения (например, потому что у нас вменяемая система типов, и указатель отличается от инта, инт — от енума, и енумы друг от друга тоже отличаются), находится 50 мест, где вызываются вредительские функции типа memset, из которых 4 или 5 содержат ошибку.
Заставлять писать код в стиле https://rsdn.org/forum/flame.comp/8912507.1
только ради отлова этих 4 или 5 мест — оверкилл. Особенно когда это можно точечно исправить.
В шарпе, например, нет именованных параметров, есть только именованные аргументы. То есть тот, кто опасается не угадать с порядком, может написать подразумеваемые имена аргументов.
И тогда компилятор его предупредит, что порядок не соответствует ожидаемому. Но ошибки-то делают не те, кто сомневается, а кто фигачит ::memset(a, len, '\xA5').
В этом смысле свифт поступает лучше всех — он позволяет сомнения высказать на стороне разработчика функции, а не потребителя.
(А для шарпа остаётся делать стилистические правила в инспекторах кода — типа "давайте убедимся, что все вызовы memset оборудованы именами аргументов, потому что если нет — то пользователь мог ошибиться").
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re: Передача аргументов в функцию - позиционные vs именованные
Здравствуйте, Shmj, Вы писали:
S>А ведь есть более умные решения: именованные аргументы функции. Если порядок аргументов изменился, то не нужно по всему коду выискивать и исправлять.
Ну и передай туда структуру с именованными полями.
S>Какой вариант вам удобнее?
Позиционный.
Re[2]: Передача аргументов в функцию - позиционные vs именованные
Здравствуйте, Sinclair, Вы писали:
S>Если в функции — сорок параметров, из которых 38 необязательные, то именованные удобнее. Если в функции — два параметра, и оба обязательные, то удобнее позиционные. S>Ваш К.О.
Если в функции — сорок параметров, то эту функцию надо бы порефакторить...
Re[5]: Передача аргументов в функцию - позиционные vs именов
Здравствуйте, Doom100500, Вы писали:
P>>Лично мне после передачи полутора десятков аргументов на фортране именованные параметры не очень и нужны.
D>И тут, вдруг, ты узнал, что твоим кодом пользуются люди, и делают ошибки. Не, нуачё, пусть внимательнее будут .
Люди находили в моём коде приватную фукнцию, которая деляет (на первый взгляд) то, что им понадобилось, превращали ее в публичную, не задумываясь о том, что пока она приватная, это моя забота, звать ее в правильный момент и на правильном контексте, а публичную функцию могут в любой момент позвать, а когда я им вежливо пытался сказать, что не надо так делать, еще и через начальство на меня давили.
Ну их, этих людей...
Re[3]: Передача аргументов в функцию - позиционные vs именованные
Здравствуйте, netch80, Вы писали:
N>Это отличный пример, где принудительно именованные аргументы точно пригодились бы.
Согласен.
Для С++ есть, кстати, разные трюки для именования аргументов. Вот тут один из.
Здравствуйте, netch80, Вы писали:
N>и все вызовы перекинул на MemsetCaller(a, len).fillWith('\xA5') и в таком же духе.
N>Это отличный пример, где принудительно именованные аргументы точно пригодились бы.
Ну или strong types:
enum class Size : std::size_t {};
enum class Fill : std::uint8_t {};
void MemSet(void* ptr, Size size, Fill fill) {
memset(ptr, std::to_underlying(fill), std::to_underlying(size));
}
int main() {
int x[10];
MemSet(x, Size{10}, Fill{11});
}
Здравствуйте, Shmj, Вы писали: S>...Если порядок аргументов изменился, то не нужно по всему коду выискивать и исправлять.
Менять порядок аргументов нужно только вот так, с помощью вот таких инструментов:
Resharper Change signature
Это тебе гарантирует, что ты размо поменяешь вызовы везде и ничего не пропустишь. В ином случе, ты рискуешь что-нибудь забыть или перепутать. А ещё очень полезны юнит-тесты: они должны быть прежде чем ты начнёшь рефакторить. В случае, если ты что-нибудь забудешь в процессе или перепутаешь, они должны ломаться.
Публичные методы библиотек лучше вообще не менять — этим ты почти гарантированно испортишь жизнь своим пользователям: не везде есть стопроцентное покрытие тестами. И упаси тебя бог менять семантику параметров! Тут лучше заранее думать, что твои пользователи — неуравновешенные психи, вооружённые топорами.
Всё сказанное выше — личное мнение, если не указано обратное.
Здравствуйте, Enomay, Вы писали:
E>Если в функции 40 параметров, то E>во-первых, с функцией явные проблемы E>во-вторых, для передачи параметров используют один объект с 40 полями
ага, а объект иммутабл нужен, упс у нас конструктор с 40 параметрами )
функции с 40 параметрами по опыту и делают часто объект с 40 полями
и там еще у большинства дефолтные значения.
вполне норм, больших проблем с этим нет.
WBR, Igor Evgrafov
Re[2]: Передача аргументов в функцию - позиционные vs именованные
Здравствуйте, Буравчик, Вы писали:
Б>Там есть и позиционные аргументы, и именованные, и дефолтные. Б>При это в вызове ты сам решаешь как их указывать — с именами или без.
там в декларации можно форсить вызов с именами. тоже полезно бывает.
WBR, Igor Evgrafov
Re[2]: Передача аргументов в функцию - позиционные vs именованн