- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
отгадай язык и что делает эта процедура
[code]
template<class T, class U>
auto add(T t, U u) -> decltype(t + u)
{
return t + u;
}
[/code]
Нашли или выдавили из себя код, который нельзя назвать нормальным, на который без улыбки не взглянешь? Не торопитесь его удалять или рефакторить, — запостите его на говнокод.ру, посмеёмся вместе!
−16
отгадай язык и что делает эта процедура
[code]
template<class T, class U>
auto add(T t, U u) -> decltype(t + u)
{
return t + u;
}
[/code]
Недавно об этом срач был на кабре
Главное не забывать, что это не замыкания.
"нововведения нам нужны для удобства, а удобства, - что бы запутывать"
... функцию абстрактного сложения двух аргументов*
тормозное малофункциональное синтаксически-избыточное говно из 80х
в нем как раз и не хватает темплейтов и приходится вымораживаться через execute immediate
первое позволяет сэкономить те самые связи, т.к. обобщенное программирование позволяет писать код один раз, а использовать - много
если программист не может написать шаблонную функцию так, чтобы она не была очевидной, либо хотя бы её не приходилось переписывать другому программисту - ну тут не инструмент виноват, например
а уж о преимуществах инкапсуляции (модульности, изоляции кода и приватных данных), "контракта" (в виде интерфейсов/классов), позднего связывания (полиморфизма) в больших проектах и спорить не стоит
> по 2 месяца нихрена не понимают
не всем можно в эту сложную профессию, пусть идут работать по инструкции
не, программисты очень опытные, но проект такой, что бывают нервные срывы.
что за проект такой, что ни логики, ни комментариев?
но сейчас толпа заминусует, конечно
Иногда гибкость вредна, мне известно много таких случаев. Программисты и пользователи начинают что-то предполагать, потом делать на основе предположений, потом запутываются сами и еще сильнее запутываются после смены требований.
потом бросают все и делаю так
if(old_version){ 10 тыс строк кода}
if(new_version){ Control-C Control-V 10 тыс строк кода c небольшими правками}
имо есть пара изъянов, связанных с объявлением типов, но они вообще в других местах.
Указатели на функцию: я хочу вводить *int(int,int) func_ptr; вместо int(*funct_ptr)(int,int);
Или, например:
int A[10][10];
int (*B)[10][10];
что здесь массив указателей, а что - указатель на массив? Почему бы не сделать
*[10]int A; - указатель на массив из 10 элементов типа int
[10]*int A; - массив из десяти указателей на int.
И эти недочеты не уйдут от смены типа объявления переменной
Где я такое говорил? Я лишь говорил, что Стиль (Способ) Объявления Переменных Рулит. Он появился ещё до сишки, но K&R почему-то решили его не использовать. Во многих нормально спроектированных языках используется именно такой подход (SML, Ocaml, Haskell, Scala, Rust, Nemerle, Go, ...)
> не значит, что язык плохо спроектирован
Кмк, то, что нужно вводить второй синтаксис для указания типа, означает как раз это. Вроде бы всем очевидно, что с точки зрения априорного дизайна C++ - полное УГ. Другое дело, что текущий дизайн является в некотором роде локальным оптимумом - движение в любую сторону только навредило бы развитию языка, это становится очевидно из единственной читабельной книжки Страуструпа - "The Design and Evolution of C++".
> И эти недочеты не уйдут от смены типа объявления переменной
Эти недочёты фиксятся тривиально, достаточно ввести один регулярный синтаксис построения типа:
Проблемы, которые сейчас есть у синтаксиса c++, не решить введением var и перенесением типа переменной правее названия.
По нотации, которую вы предлагаете:
var main : Func[argc : int, argv : Ptr[Array[char]]] ...
точно проще читать?
Начнём с того, что проблемы синтаксиса C++ вообще уже ничем не решить - любые изменения будут только добавлять проблем. Речь идёт о том, что проблем можно было бы избежать, если бы K&R 50 лет назад сделали синтаксис объявления переменных как в Pascal, а не как в Fortran.
> точно проще читать?
Синтаксис должен быть скорее таким:
Func[X, Y, R] нужен для ссылок на фукнции, fn - для объявления/определения функций.
А можно пример? Что-то я не вижу, откуда берётся такой синтаксический оверхед. Ну разве что заменили звезду на Ptr, скобки с числом - на Array.
Сырые указатели в крестах я использую очень редко, а массивы с размерностью передавать параметром функции в сишке/крестах - нонсенс.
В вашем же примере:
fn main(argc: Int, argv : Ptr[Ptr[Char]]]): Int // 47 символов
вместо
int main(int argc, char** argv) // 31 символ
И где же оверхед?
В tuple, например, вполне можно засунуть, например, двумерный массив комплексных чисел (как удобно, так и десериализую). И мне совершенно не нужна пара десятков лишних символов в объявлении такой конструкции.
> пара десятков лишних символов
Не вяжется как-то.
> совершенно не нужна пара десятков лишних символов в объявлении такой конструкции
Тайпдефы в помощь.
Затайпдефать я могу хоть любой тип, который использую, и причина, по которой я этого не делаю - генерируются много бестолковых строк кода там, где они совсем не нужны. И говорить "лучше писать больше кода чтобы делать больше тайпдефов чтобы в итоге всё стало как было + объявление тайпдефа" глупо.
И да, если вам так нравятся паскалевские нотации, флаг в руки:
typedef auto fn;
fn someFunc(int a, int b) -> int { return a+b; }
Но почему то же вы так не делаете
Так это для переменных тоже нужно, не только для функций.
Ну и мой текстовый редактор от этого не начнёт лучше понимать долбанутые крестовые конструкции.
> Затайпдефать я могу хоть любой тип... я этого не делаю
А вот я очень активно использую тайпдефы. Они позволяют создавать бесплатные абстрации и делают код более читабельным. Кусок кода из реального проекта:
> глупо
А мне вот кажется, что экономить на символах в ущерб понятности и читаемости - глупо.
Мб дело не в крестах, а в текстовом редакторе?
> Кусок кода из реального проекта:
Приведенный пример хорош, но я не с этим спорю. Мне не нравится идея использовать тайпдефы там, где их необходимость обусловлена ТОЛЬКО громоздкостью конструкции.
> А мне вот кажется, что экономить на символах в ущерб понятности и читаемости - глупо.
Малое количество смысла в большом куске текста тоже затрудняет восприятие.
Громоздкость конструкции означает, что где-то потерялась абстракция.
> Мб дело не в крестах, а в текстовом редакторе?
Текстовый редактор отличный, из двух десятков языков у него только с крестами проблемы :) Не у него одного, кстати. Без привязки к компилятору кресты вообще подкрашивать очень сложно, регулярками не обойтись.
У меня есть строка в 20-30 символов, которая понятна и без абстракций. По вашему, надо её расписать на 40 символов, и то, что она при этом станет громоздкой, вызвано тем, что в ней "потерялась абстракция". Не путайте причины и следствия, пожалуйста
> громоздкой
У вас какие-то странные представления о громоздкости. Вот это громоздко, и тут никакие тайпдефы не помогут :)
Речь не о символах языка/фреймворков
Нет, мне что-то не очень нравятся имена объектов вперемешку с именами типов без дополнительных конструкций вроде какого-нибудь TypeOf Правда, в Ocaml этому есть применение: там имена аргументов могут быть частью контракта функции, так работают именованные и опциональные аргументы, их можно передавать в различном порядке.
template<class T, int N> using Array<T, N> = T[N];
template<class T, class... Arg> using Func<T, Arg> = T()(Arg...);
и прочее в myproject.h -- и на плохом языке можно писать хороший код.
За синтаксис в последней строке не отвечаю.
получится как тут
>> var a : Ptr[Array[Int, 10]]
> точно проще читать?
Точно проще читать.
1. По умолчанию с типами творится какая-то странная каша. Типы-слова (int, float), типы-символы (*,[]), типы-функции (std::vector) - не сведено к общему знаменателю, запутывает.
2. Типы в общем случае принимают более одного аргумента и представляют собой какое-то выражение.
У Вас тип - линейная питушня, которая не расширяется на общий случай.
У Романа - симметричная система записи без странных исключений.
Предположим, существует язык, в котором эквивалентом строки
std::string (*makeHash)(const char *string, int32_t seed);
является
declare variable makeHash as pointer_to function taking pointer_to const char and unsigned int32 returning type string from std;
Это гиперболизация, офк, но, исходя из ваших комментариев выше, такой язык является чуть ли не идеалом, к которому надо стремиться. И я повторю вопрос: удобно читать?
Зачастую скорость восприятия обусловлена только скоростью чтения.
std::string (*makeHash)(const char *string, int32_t seed);
является
№!::~~ [[*make#]](!! ~ *~~, @32 seed);
Любую запись можно гиперболизировать.
> Зачастую скорость восприятия обусловлена только скоростью чтения.
Да, в частном случае char* читается легче, чем ref<char>
Да, значки часто удобнее в программировании и математике. Несколько раз я участвовал в обсуждениях на эту тему, где стоял за значки именно из-за скорости восприятия компактных выражений.
Но здесь в чуть более сложных случаях, чем char* начинается какая-то фигня с *, [], const, volatile, функций. Становится проще запомнить, как описывается указатель массив, чем пытаться вычислять.
Но от сложных структур чаще всего отказываются, из-за чего они встречаются гораздо реже, чем более простые. А значит фиг тут что выучишь, фиг что посчитаешь, т.к. в следующий раз встретишь этот набор скобок и звёзд не так скоро.
В итоге, начиная где-то с измерения 2-3, запись Романа уже проще, чем обычная сишная из-за того, что прочитать длинную понятную строчку легче, чем раздумывать над короткой и менее понятной.
Но вообще, самая лучшая, самая короткая и самая понятная запись типа - в JSON. Видим значение - видим его тип. Без посредников:
В сишном стиле это было бы что-то вроде object x{char*}[]{char*}.
В C++ - map<string, vector<map<string, object>>> x.
В JSON: нет записи - нет проблем.
> Любую запись можно гиперболизировать.
Вывод: регулярки придумал сам дьявол
Я пытаюсь оспорить утверждение, что "вот так лучше, чем в плюсах", а не доказать, что "спецсимволы лучше слов потому что короче".
хорошая идея
Скорее - нет (известного на этапе трансляции) типа - не нужно писать тип.
В таких случаях помогает вывод типов - писать не надо, а компилятор осведомлён.
using CString = const char*;
using Int32 = int32_t;
using String = std::string;
> using CString = const char*;
Не забыл, а предположил, что стандартная библиотека делает очевидный тайпдеф для такого частого кейса.
> using Int32 = int32_t;
Это даже не смешно
> using String = std::string;
Лол, ну пусть будет Std.String
Нет уж, мне некогда этим заниматься. Люди пытались запилить годноту в Clay, но он, кажется, помер
Как однажды заявил Страуструп: "есть два типа языков программирования: те, которые все критикуют, и те, которыми никто не пользуется"
2 отловить всех крестоблядей и сжечь
3 ???
4 PROFIT
ты сам это сказал
на сях
Потому что я предлгаю сахарок: последний параметр можно указывать в конце после слова of. Только последний, чтоб не было путаницы
А вообще, частичное применение и каррирование типов нужно обязательно предусмотреть. Ну и другие типопреобразователи вроде хаскелевского flip, а то и вовсе какой-нибудь функциональный язык использовать для описания типов.
Скажем,
Крестовикам не привыкать. Когда добавили шаблоны, пришлось ради шаблонов изобретать новый язык.
Вот pure-сишникам будет тяжелее.
Из-за чего? Они не смогут смириться из-за того, что пон*ятн*ые[] царские звёздочки и скобочки заменят на длинные попсовые слова? Или из-за конфликта императивного подхода кода с новой функциональной типарадигмой?
Раньше только ТруСишник мог с ходу написать сигнатуру функции которая возвращает указатель на массив константных указателей на структуру. А теперь каждый лох сможет.
c++?
> громоздкой
У вас какие-то странная каша. Типы-слова (int, float), типы-функции внутри другие типов - писать сигнатуру функции которая понятная запись Романа уже проще, чем обычная сишная из-за скоростью чтения. Когда добавили шаблонов изобретать новый язык.
Раньше только скоростью чтения. Когда не понимать долбанутые крестовые конструкции.
> А мне вот кажется, что это опошляет язык, в которому надо стремиться. И я повторю вопрос: удобно, так и десериализую). И мне совершенно не нужно