LINUX.ORG.RU

Что нужно добавить в C?

 


0

5

Расскажите, что бы вы хотели добавить в си? Только то, что реально можно добавить, не делая при этом новый язык. Просто фичи, которых не хватает.

Или покритикуйте мой список.

  • Константы. #define - препроцессор, const не работает полноценно в compile-time, enum только для целых и вообще для другого .
  • Лямбды (анонимные функции) - для удобства коллбеков. Можно без замыканий, т. к. они много скрывают.
  • Модули, если возможно. Для изоляции единиц трансляции.
  • Интроспекция (typeof, хотя бы) - для обобщенного программирования.
  • Более развитая макросистема - для того же. Например, возможность макросы раскрывать в директивы препроцессора.
  • Пространства имен, чистые функции, switch по составным типам, case с диапазоном - для сокращения кода.
  • Аналоги volatile и restrict с более точным контролем - для микрооптимизации.
  • Доступ к стеку вызовов, goto между функциями - для трюков типа трамплинов.
  • В стандартной библиотеке - строки, контейнеры, foreach, большие числа. Возможно, сокеты.
★★★★
Ответ на: комментарий от anonymous

Ну сравни с таким, например:

{int, int}
func(int in_arg_1, int in_arg_2)
{
    return {in_arg_1 + 1, in_arg_2 + 1};
}
anonymous
()
Ответ на: комментарий от ozkriff

А какая альтернатива?

Вообще, то что все эти вещи возвращают итераторы обусловлено тем, что иначе не получится продолжить работу с некоторого места без повторного обхода (Степанов критиковал подобные функции в некоторых других библиотеках коллекций — мол, возвращают тупо какую-нибудь bool или value), в случае std::map возвращается пара — итератор _и_ индикатор «вставили новый» / «есть старый», это позволяет коду использующему такой API делать разные хитрые вещи (с меньшим количеством работы / обходов), которые иначе сделать бы не получилось. operator* итератора тоже возвращает value_type, который пара (опять же — как иначе? могут быть нужны ключ _и_ значение).

quasimoto ★★★★
()

Корутины же.

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

Ещё из <algorithm>:

http://www.cplusplus.com/reference/algorithm/equal_range/

http://www.cplusplus.com/reference/algorithm/minmax/

http://www.cplusplus.com/reference/algorithm/minmax_element/

(поиск minmax эффективнее поиска min с последующим поиском max)

В Haskell:

http://www.haskell.org/hoogle/?hoogle=(a, b)&start=1000

И т.п. что он не нашёл:

http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.6.0.1/Data-List....

http://www.haskell.org/ghc/docs/latest/html/libraries/base-4.6.0.1/Control-Ar...

Функции с общим доменом объединяются в функцию из общего домена в кортеж:

newtype Lens a b = Lens { _lens :: a -> (b, b -> a) }
newtype Iterator c i e = Iterator { _iter :: c -> (i, i, i -> (Maybe e, i)) }

И даже

newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))

Так что, можно сказать, в хаскеле только и делаешь, что возвращаешь кортежи из функций, явно или нет :)

quasimoto ★★★★
()

Символьный тип данных забыл.

iZEN ★★★★★
()

Что нужно добавить в C?

Два плюса.

Или покритикуйте мой список

Посмотрел твой список, ну так это и есть два плюса.

no-such-file ★★★★★
()
Ответ на: комментарий от quasimoto

Вот ведь ты разошелся. Ок, ок, я не против разумного использования кортежей-пар)

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

Руки прочь от С! Только С89 без всяких gnu есть истинный Цэ!

аминь

wota ★★
()
Ответ на: комментарий от no-such-file

Чего конкретно из списка нет в C++?

Модулей, интроспекции, макросов, чистых функций, switch, case, volatile, restrict (вообще никакого), стека, goto. Блин, проще сказать, что там есть. Хотя что-то из этого рассматривает Комитет.

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

В нём нет fixed-width integer, тредов и прочих вкусных штук.

это все есть в библиотеках, например, в apr, glib и пр.

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

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

1) в стандарт все не впихнешь
2) ты видно C для написания кроссплатформенного кода не используешь, т.к. знал бы, что далеко не все даже популярные компиляторы умеют C11, т.е. для кроссплатформенного кода все-равно нужны библиотеки, а если ты хочешь писать только для linux - берешь тот же pthread и вперед, никакой С11 не нужен, и не будет ненужных проблем с icc или tcc

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

gcc 4.7+ clang 3.1+

~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-16ubuntu6' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-16ubuntu6) 
~$ cat 1.c
#include <threads.h>

int main() {
  call_once( 0, 0 );
  
  return 0;
}
~$ gcc -std=c11 1.c
1.c:1:21: fatal error: threads.h: Немає такого файла або каталогу
 #include <threads.h>
                     ^
compilation terminated.

ололо

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

ну да у gcc еще проблемы с тредами

вообще-то не у gcc, а у glibc, и там даже не чешутся, а ты говоришь - C11, треды, свободка, хотя стоп, это уже не то

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

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

еще раз повторю - в крестах libstdc++ (и то опционально, можно и libc++ взять), gcc же использует хедера glibc, так что ни в какой «сишный компилятор» ничего не добавляют, разве что нужны были TLS, но они были и раньше

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

gcc же использует хедера glibc

можно конечно и тоже не glibc, а какой-нибудь uclibc, но там <threads.h> тоже ес-но нет, да и не равноценны они

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

Модулей

Там есть классы, что гораздо гибче. И кстати, модули есть даже в Си.

интроспекции

Динамическая чушь. Кому надо, может запилить руками или взять Qt. Любители чистого Си могут взять glib.

макросов

Там есть шаблоны - те же яйца, вид сбоку.

чистых функций

Не понял что имеется в виду. В чем проблема писать на Си чистые функции?

switch, case

Сахарок. If else if else ничем не хуже. switch по целому типу имеет то преимущество, что может лучше оптимизироваться и можно реализовать в виде таблицы переходов, т.е. без применения сравнения вообще.

стека, goto

setjmp, longjmp есть даже в Си. В крестах есть сахарок в виде throw.

volatile, restrict

Вот непонял какой тебе нужен контроль. Классы + volatile недостаточный контроль?

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от geks

В нём нет fixed-width integer, тредов и прочих вкусных штук. Так что с11!

Приведи пример зачем это всё надо.

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

Модулей

Там есть классы, что гораздо гибче. И кстати, модули есть даже в Си.

В си есть единицы трансляции, а в модуле есть ещё метаданные о его содержимом, доступные самому языку. Как в java, python, pascal... Короче, практически везде. И модули предложены в стандарт C++, ведется их реализация в clang/llvm.

интроспекции

Динамическая чушь. Кому надо, может запилить руками или взять Qt. Любители чистого Си могут взять glib.

Речь о статической интроспекции. typeof, __func__ - примеры её огрызков, что есть в (гну) си.

макросов

Там есть шаблоны - те же яйца, вид сбоку.

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

чистых функций

Не понял что имеется в виду. В чем проблема писать на Си чистые функции?

Проблема сказать компилятору, что функция чистая. См. attribute((pure)) (и attribute((const))).

switch, case

Сахарок

Разумеется, сахар, как и foreach. Нужно для сокращения и читаемости кода.

стека, goto

setjmp, longjmp есть даже в Си. В крестах есть сахарок в виде throw.

Вот throw как раз не сахар, а новая часть семантики языка. Только вся эта компания не дает ни доступа к стеку, ни перехода в новую функцию (Что нужно добавить в C? (комментарий)).

volatile, restrict

Вот непонял какой тебе нужен контроль. Классы + volatile недостаточный контроль?

Мне нужна возможность сказать: «тут синхронизируй абстрактное значение переменной с реальным, а там кешируй как хочешь». На самом деле, лично мне это не было нужно, просто то как сделано сейчас - грубое, половинчатое решение.

unsigned ★★★★
() автор топика
Ответ на: комментарий от no-such-file

Там есть шаблоны - те же яйца, вид сбоку.

Увы, шаблоны до полноценных макросов не дотягивают.

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

Как в java, python, pascal...

Ах как в паскале... Спасибо, не надо.

Речь о статической интроспекции

Не бывает никакой статической интроспекции. Это называется метапрограммирование и для этого в крестах есть шаблоны.

Макросы легко читаются, легко реализуются, отлаживаются

Какие именно макросы? Сишные макросы вообще никак не отлаживаются и о легкости реализации речи не идет. Если ты имеешь в виду макросы как в лиспе, то их простота и т.п. это не особенность макросов, а особенность лиспа как языка. Шаблоны в крестах - вполне адекватный подход.

Проблема сказать компилятору, что функция чистая

Во-первых если компилятор не дурак, то может сам догадаться, а во вторых, есть как ты сказал атрибуты. Жаль, конечно, что на уровне стандарта тут ничего не предпринято. Кстати, я не в курсе, а яве, паскале и т.п. есть возможность сказать что ф-ця чистая?

Разумеется, сахар, как и foreach. Нужно для сокращения и читаемости кода

Я, лично не вижу где switch/case короче чем if else if else.

switch (a) {
   case 1: do1(); break;
   case 2: do2(); break;
   case 3: do3(); break;
}

if (a==1) do1();  
else if (a==2) do2(); 
else if (a==3) do3();

По-моему if-else-if-else даже короче. И понятнее, плюс нет возможности пропустить break;

Только вся эта компания не дает ни доступа к стеку, ни перехода в новую функцию

В какую новую? По стеку можно перемещаться, да собственно в этом суть longjmp/throw. Если ты имеешь в виду просто переход на метку внутри произвольной функции, то такого бреда нет ни в одном языке, где есть функции. ЕМНИП.

тут синхронизируй абстрактное значение переменной с реальным, а там кешируй как хочешь

А зачем это нужно? Навскидку - используй две переменных, одну volatile, другую обычную, кэширующую первую. Для доступа к переменным испольуй 2 геттера волатильный и простой (кэширующий). Зачем тянуть это в язык?

no-such-file ★★★★★
()

стандартная библиотека

ANSI, ISO, POSIX?

ubuntuawp ★★
()

В С нужно добавить объекты из smalltalk

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

Что есть полноценные макросы?

Тьюринг-полный макроязык с доступом ко всем возможностям целевого языка (как в том же Common Lisp). Чтобы, например, можно было открыть во время раскрутки макроса файл или соединение с базой данных.

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

switch, case

Сахарок. If else if else ничем не хуже

Так можно договориться до того, что while и for - это просто сахарок поверх goto.

tailgunner ★★★★★
()
Ответ на: комментарий от no-such-file

Ах как в паскале... Спасибо, не надо.

Я вообще не припомню навскидку другого популярного языка, где нет модулей. Что по-твоему с ними не так?

Это называется метапрограммирование и для этого в крестах есть шаблоны.

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

Какие именно макросы? Сишные макросы вообще никак не отлаживаются и о легкости реализации речи не идет.

Сишные. Реализуются препроцессором, отлаживаются им же (т. е. можно посмотреть, во что раскрываются).

Шаблоны в крестах - вполне адекватный подход.

Для крестов - приемлимый. На замену макросам пойдет с натяжкой - если поступиться простотой.

Во-первых если компилятор не дурак, то может сам догадаться

Да, если видит функцию.

Кстати, я не в курсе, а яве, паскале и т.п. есть возможность сказать что ф-ця чистая?

Нет, афаик.

По-моему if-else-if-else даже короче. И понятнее, плюс нет возможности пропустить break;

В тривиальном случае да, но я же говорил про составные типы.

switch(msg) {
  case { .type == T1, .cmd == C2 }:
  case { .type == T2, .cmd == C5 }:  return foo();
  case { T2, C2 }:                   return 0;
  case { .type == T1 }: return error();
}

Если ты имеешь в виду просто переход на метку внутри произвольной функции, то такого бреда нет ни в одном языке, где есть функции. ЕМНИП.

Примерно это, да. Такие трюки всё равно делают, только на ассемблере. Имхо, си должен (и может) это покрывать.

используй две переменных, одну volatile, другую обычную, кэширующую первую. Для доступа к переменным испольуй 2 геттера волатильный и простой (кэширующий). Зачем тянуть это в язык?

Читаемость похуже (а почему это тут две переменные?). А вообще вопрос больше принципиальный: раз уж ввели понятие абстрактной семантики, но абстракции при этом текут (а усложнять нельзя, потому что си) - дайте тогда уж механизм точечного отключения этих абстракций. Это предотвратило бы многие баги, вылезающие от того, что оптимизатор оказался умнее кодера - сейчас даже занулить пароль в памяти оказывается проблемой. Скажем, можно было бы распространить volatile для блоков кода (сейчас это по сути volatile asm). Можно было бы ввести барьеры, на которых происходит синхронизация (например, это нужно для setjmp). Тут лучше ядерщиков спрашивать, у них много таких приколов. И решается это только на уровне языка (сейчас решают другим языком, ассемблером).

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

Модули, макросы и чистые функции вроде как рассматривают для 14 стандарта.

14 стандарт уже по сути сформирован, там ничего существенно нового. Модули рассматривают для следующего, про остальное не слышал.

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

Что по-твоему с ними не так?

С модулями паскаля не так то, что они могут использоваться только в паскале.

Например, на них не напишешь обобщенную функцию сериализации. Разве что всю программу писать в шаблонах, но про это можно и не говорить.

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

Реализуются препроцессором, отлаживаются им же (т. е. можно посмотреть, во что раскрываются).

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

На замену макросам пойдет с натяжкой - если поступиться простотой.

Каким именно макросам? Сферическим в вакууме?

В тривиальном случае да, но я же говорил про составные типы.

Из твоего примера неочевидно, что именно там происходит. А если написать тоже с использованием if else if else, то понять сможет даже паскалист.

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

Такие трюки всё равно делают, только на ассемблере. Имхо, си должен (и может) это покрывать

Кто и где это делает? На асме так делают, но там и нет функции как языковой единицы, а весь код виден как он есть, т.е. можно определить все эффекты от такого кульбита. В Си ты не видишь ассемблерный код и не можешь знать какие будут эффекты, не говоря уж о том, что не известно как это отразиться на стеке. В Си стек чистит вызывающая сторона, и если зайти в функцию через jmp то на стеке не будет параметров и после возврата будет жопа. Я ещё не вспоминаю о том, как отследить переменные выделенные на стеке в самой функции.

Читаемость похуже (а почему это тут две переменные?).

Я тебе русским языком сказал, что доступ через геттеры. getVolatileValue, getCachedValue, по-моему все просто и понятно.

Скажем, можно было бы распространить volatile для блоков кода (сейчас это по сути volatile asm).

И чтобы этот volatile делал бы? Отключал оптимизацию? Для этого нужно просто вынести код в отдельный модуль и собрать его без оптимизации. Делов-то.

Можно было бы ввести барьеры, на которых происходит синхронизация

Синхронизация чего?

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

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

no-such-file ★★★★★
()
Ответ на: комментарий от tailgunner

Так можно договориться до того, что while и for - это просто сахарок поверх goto.

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

А теперь скажи мне, чем обобщенный switch лучше if else if else? Switch по целому типу, как я уже сказал - особый случай, который можно соптимизировать, а вот switch , как обобщенный оператор нафиг не нужен, т.к. технически ничего не дает, но взамен требует усложнения компилятора и увеличения времени компиляции.

no-such-file ★★★★★
()
Ответ на: комментарий от derlafff

выкинуть си и юзать какой-нибудь go

Перепишем ядро на go?

splinter ★★★★★
()
Ответ на: комментарий от no-such-file

А теперь скажи мне, чем обобщенный switch лучше if else if else?

У switch (как он реализован в Си и Си++) семантика другая - не проверка шашлыка условий, а _исчерпывающий_ выбор варианта действия в зависимости от значения _одной_ переменной.

While и for позволяют компилятору определить структуру цикла, т.е. ему уже не надо догадываться где условие выхода, где тело, где счетчик

Какая трогательная забота о компиляторах. Не стоит - они в своем деле давно уже умнее 99% программистов.

switch , как обобщенный оператор нафиг не нужен

Кстати, если ты не заметил... unsigned называет «обобщенным switch» нечто, очень похожее на pattern matching. Если pattern matching тебе не нужен - окей, оставайся в 70-х.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от no-such-file

С модулями паскаля не так то, что они могут использоваться только в паскале.

это далеко не так - у Била Джоя ( это который vi и Sun ) есть буклет про Паскаль - и там с интеграцией модулей Паскаля с окружающим bsd? всё хорошо.

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

нечто, очень похожее на pattern matching

Но не паттерн матчинг. А тупо if-else записаный по-другому.

Не стоит - они в своем деле давно уже умнее 99% программистов.

Да именно это я и сказал. Но тебе лишь бы вякнуть.

У switch (как он реализован в Си и Си++) семантика другая

Да именно это я и сказал. Но тебе лишь бы вякнуть ещё раз.

no-such-file ★★★★★
()
Ответ на: комментарий от qulinxao

там с интеграцией модулей Паскаля с окружающим bsd? всё хорошо

Дай почитать.

Вообще моя претензия к модулям как в паскале или яве в том, что они не переносимы в том смысле, что формируют вместе с языком некоторую закрытую платформу, язык+модули. Си сейчас можно использовать безотносительно платформы, как метаассемблер. Если в стандарт внести модули, то это сильно сузит применимость языка и вызовет необходимость его дробления на версии. В итоге мы будем иметь 100500 разных вариантов си с той или иной глубиной поддержки модулей, в зависимости от платформы. Зачем? Только потому, что кому-то показалось хорошей идеей объединить объектные и заголовочные файлы в один «модуль»? В сегодняшнем положении вещей с модулями в си нет никакой технической проблемы, только организационная, которая решается сейчас уровнем выше - не языковым, а системным. И правильно, т.к. это системоспецифичная область.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.