давайте сделаем С++ expression-first языком. Для этого нужно добавить в язык несколько фич
1) добавить для функции и лямбды синтаксис возрата экспрешена как сахар над return, то есть конструкция "[]() => <expr>" будет сахаром для конструкции "[](){ return <expr>; }"
2) добавить возможность объявлять переменные внутри конструкции скобок. Это уже позволит писать такой код
auto someFunc = []() => (
auto someVar = 123,
someFunc(someVar),
...
someVar
);
Прошу заметить что здесь вместо точки с запятой я использую просто запятую и это валидный синтаксис поскольку в языке уже есть возможность выполнить несколько экспрешенов подряд внутри одного statement например
return (
someFunc(),
anotherFunc(),
someVar = someExpr,
someResult
);
3) добавить возможность использовать конструкцию if-else в выражениях
auto someFunc = []() => (
auto someVar = 123,
if(someCond) someCall(),
auto someResult = if(someCond) (
someVar = someVal,
someFunc()
) else (
anotherFunc()
),
...
someResult
);
либо добавить возможность не указывать вторую часть тенарного оператора
auto someFunc = []() => (
auto someVar = 123,
someCond ? someCall(), //тенарка без двоеточия
someResult
);
4) добавить возможность использовать в выражениях операторы return, break, continue, подобно оператору throw (кстати а вы знали что оператор throw в плюсах можно юзать внутри выражения например "auto obj = flag ? someValue : throw someError" ?) и также добавить возможность использовать в выражениях конструкции for, for-range, while, do-while, switch, try-catch которые будут возвращать значение последнего выражения из своего блока или если был ранних выход оператором break то чтобы можно было вернуть значения используя "break <expr>"
Кому нравится такая идея сделать из C++ красивый функциональный expression-first язык?
тут нет ничего из того чего нельзя реализовать в С++20 или даже 17
кроме тенарки пожалуй, и пару стилистических фич
Интересно. Только почти всё из этого - breaking changes
а в чем заключается breaking change?
int a = 5, b - это уже валидная запись, предлагается поменять её семантику на (int a = 5), (b)? Тернарник без третьего аргумента должен привести к неоднозначности синтаксиса в битфилдах, но я не могу придумать пример.
мне кажется, что пример не придумывается из-за ограничений грамматики http://eel.is/c++draft/class.bit#1
Да, int a = 5, b будет раскрываться в (int a = 5), (b) то есть запрещаем использовать несколько переменных с одним декларатором внутри скобок. Но это не будет breaking-change потому что сейчас вообще нельзя объявлять переменные внутри конструкции круглых скобок
Кстати с этой фичей когда операторы включая try-catch будут экспрешенами вот такая неудобная конструкция которую приходится писать сейчас auto someResult = [](){ try { return someFunc(); } catch(SomeErr err){ return someDefault(); } }() можно будет удобно записывать вот так auto someResult = try someFunc() catch(SomeErr err) someDefault()
Это где так пишут
не знаю)
Ну отличная идея
Кстати сейчас действительно есть какая-то странность с try-catch-конструкцией - почему-то она выбивается из синтаксиса остальных операторов в С++ - например с if-оператором можно писать экспрешен сразу без фигурных скобок, то есть такая конструкция работает if(someFlag) x = someFunc(); else x = someDefault(); а вот с try-catch так нельзя try x = someFunc(); catch(SomeErr) x = someDefault();
Это не операторы вообще
Итак, в С++ есть тысяча синтаксических способов сделать одно и то же действие, давайте добавим еще тысячу способов, я правильно прочитал?
Я понимаю прелесть унификации, если это не абьюзить bool success = a.find(auto outVar) if (success && auto handle = outVar.get()) { }
Никто не заставляет их все использовать
Нечитаемый ужас родом из С
но это в урезанном варианте уже существует в C++ if (auto pointer_like = get_something()) { // safe to do *pointer_like }
И так писать не нужно, особенно после 17
Наоборот, это нововведение
это всё хорошо, но почему бы не взять готовый?
Нововведение - это if (auto p = expr(); p)
Это еще сильнее повышает комплексность языка. На мой взгляд, язык должен продвигать какую-то одну концепцию написания идиоматического кода, а не множить сущее без необходимости. Бесконечное засирание языка новыми конструкциями приводит к тому, что код, решающий задачу, написанный на одном языке, но разными людьми, сильно отличается от человека к человеку, что повышает сложность чтения чужого кода и приводит к замедлению разработки. В итоге суммарное приложение, может к примеру состоять из библиотеки в си стиле, старом коде в c++11 стиле, новом коде в скобочном-запятом стиле. Такими пропоузами язык превращается просто в помойку из конструкций, из которых непонятно, а как, собственно, правильно писать. Мое личное мнение.
Причина добавления новых фитч не то чтобы "язык раздуть", а чтобы поддержать старые версии кода и к тому же ввести новые фитчи, меняя язык но не нарушая обратной совместимости
Вот только из того что я понял, автор не предлагает ввести какие-то фичи, а просто добавить новый вариант написания кода, который можно было прекрасно написать и раньше.
Я согласен с фактом что эта папира бессмысленна Но я не согласен что "это и раньше можно было написать" должно останавливать прогресс языка
На мой взгляд, язык должен продвигать какую-то одну концепцию написания идиоматического кода, а не множить сущее без необходимости на мой взгляд, язык в первую очередь должен предоставлять средства для выражения намерений пользователя, а не превращаться в молоток для забивания всего, что похоже на гвоздь
Я согласен, я имел ввиду что нет смысла менять одну конструкцию на другую аналогичную, но есть смысл менять более сложную конструкцию на более простую.
Обсуждают сегодня