Literate programming.

Ivan8209

Интересно, этим кто-нибудь пользуется?
---
...Bojite se viru?..

Dasar

Посмотрел, какая-то страшная вещь...
В реальной жизни чаще используется что-нибудь типа NDoc-а, когда перед классом, методами пишется комментарии, которые потом собираются и генерируется документация: какие классы, методы есть и что они делают.

Dasar

В принципе то, что делает NDoc похоже на то, что они называют книжным представлением.

durka82

А ссылку на описание можно?

Ivan8209

www.literateprogramming.com
Вообще-то, я попробовал, вроде даже что-то здоровое есть.
Пишешь объяснение, что, зачем и как ты делаешь, а код сам компонуется.
Пользуюсь noweb-ом.
Может, кто ещё что-нибудь скажет?
---
...Я работаю...

Ivan8209

Единственное, что непонятно, как этот NDoc выдаст мне в документации какую-нибудь формулу с
"\sum\limits_{k} \left(\frac{\frac{...}{...}}{...}\right)".
Этим и отличается Оно от комментариев.
---
...Bojite se viru?..

Dasar

Напиши такую фигню в комментариях и он тебе выгонить эту штуку в документацию.
зы
Счетные задачи сейчас составляют очень маленькую долю рынка...
А в прикладных программах и бизнес-логики таких страшных формул редко встречаются.
ззы
наконец, можно просто по строке LimitSum(....) - можно генерить красивую штуку как у тебя.
Данную строку можно просто copy/paste-ить в комментарии, либо разбирать, напрямую, код

Ivan8209

Не знаю, сталкивался ли ты, но я часто ощущаю, что расположение кусков программы не соответствует логике объяснения принципов работы.
Например, ты не можешь на Си объявить функцию и прототип в одном месте.
А по умолчанию, если до этого не встречался прототип, все функции --- "int f(...);".
Мало того, я могу прототип объявить вместе с функцией, а "tangle" разнесёт их по разным файлам, как и положено.
Это, конечно, больше относится к недостаткам Си, но это и немало.
Вряд ли я смогу нарисовать псевдокод и расширить его в дальнейших объяснениях при помощи NDoc.
А это лучше, чем комментарии к сплошному тексту программы.
---
...Bojite se viru?..

Dasar

Это как раз одна из основных причин, почему я сейчас почти не пишу на C++ и тем более на C.

Ivan8209

На чём?
...Я недавно осознал, что те математики, что изобретали Алгол-68, "рулят безусловно".
Эквивалентность (синтаксическая) массивов и функций, синтаксическая эквивалентность f(ab) и f(a, b)...
И создание локальных массивов переменной размерности в стеке...
---
...Bojite se viru?..

Dasar

C#

Ivan8209

Хрен редьки не слаще.
---
...Bojite se viru?..

Dasar

зато в .Net-е есть метаинформация, через которую многие вещи можно делать единообразным способом

Ivan8209

Удобство языка программирования определяется не возможностью доступа к информации и т.п.
---
...Bojite se viru?..

abrek

Давай, излагай уже свою концепцию.

valy37

Вот это - супер язык!
http://www.muppetlabs.com/~breadbox/bf/

Brainfuck
An Eight-Instruction Turing-Complete Programming Language
Brainfuck is the ungodly creation of Urban Müller, whose goal was apparently to create a Turing-complete language for which he could write the smallest compiler ever, for the Amiga OS 2.0. His compiler was 240 bytes in size. (Though he improved upon this later -- he informed me at one point that he had managed to bring it under 200 bytes.)
I originally started playing around with Brainfuck because of my own interest in writing very small programs for x86 Linux. I also used it as a vehicle for writing a program that created ELF files. Eventually, however, I too succumbed to the Imp of the Perverse and wrote some actual Brainfuck programs of my own.
The Language
A Brainfuck program has an implicit byte pointer, called "the pointer", which is free to move around within an array of 30000 bytes, initially all set to zero. The pointer itself is initialized to point to the beginning of this array.
The Brainfuck programming language consists of eight commands, each of which is represented as a single character.
> Increment the pointer.
< Decrement the pointer.
+ Increment the byte at the pointer.
- Decrement the byte at the pointer.
. Output the byte at the pointer.
, Input a byte and store it in the byte at the pointer.
[ Jump past the matching ] if the byte at the pointer is zero.
] Jump to the matching [.
The semantics of the Brainfuck commands can also be succinctly expressed in terms of C, as follows (assuming that p has been previously defined as a char*):
> becomes ++p;
< becomes --p;
+ becomes ++*p;
- becomes --*p;
. becomes putchar(*p);
, becomes *p = getchar;
[ becomes while (*p) {
] becomes }

duantusova

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

Ivan8209

Не понял.
Что ты имеешь ввиду под "излагай коцепцию"?
---
...En Catala si us plau...

Ilya1974

!

Ivan8209

Для тех, кому интересно программирование встроенных систем, есть статейка "3 Instructions Forth" by F. Sergeant (ЕМНИП, www.eskimo.com/~pygmy/)
---
...Think Forth...

Dasar

Раз ты говоришь, что "Удобство языка программирования определяется не возможностью доступа к информации ", то излагай свою концепцию - чем по твоему, определяется удобство языка программирования?

Ivan8209

Если бы доступ к информации определял качество языка программирования, то все писали бы на (макро)ассемблере, ибо тогда доступно всё.
Удобство языка определяется общим временем его изучения и решения на нём доступных (требуемых) задач.
Как обычно, в общем.
---
...Я работаю дзен-позитивистом...

Dasar

Тогда скажу так:
C# (а конкретнее метаинформация) позволяет передать от программиста к программе тот же объем информации, через меньшее кол-во символов, а также в более структированном виде

Ivan8209

Может, тогда лучше взять CLOS?
---
...Bojite se viru?..

Dasar

Clos - это не если ошибаюсь, что-то из разряда lisp-о подобных?
отдельные функции удобнее записывать в процедурном стиле, чем в функциональном или лямбда-исчислении.

abrek

AFAIK Lisp поддерживает все распространённые парадигмы программирования без модификации синтаксиса
в частности, CLOS - это объектно-ориентированная система

Ivan8209

(PROG S-EXPR S-EXPR ...)
Common Lisp Object System
---
...Bojite se viru?..

Dasar

гвозди можно забивать и микроскопом...
вместо "процедурного" в предыдущем моем топике надо читать "операторного" (не знаю как точнее сказать).
но смысл в том, что вот такой код:
int q = GetSomeQFunction;
int qq = GetSomeAnotherQQFunction;
int value = 0;
foreach (Item item in Items)
{
if (item.index < q && item.index > qq)
value += item.Value;
}
приходится писать в функциональном или лямбда-исчислительном виде, что добавляет программе читабельности

abrek

обязательно это делать только в чисто функциональных языках, а лисп (повторяюсь!) поддерживает и другие парадигмы (процедурное программирование, ОО)
однако меня и контру тебе слушать, очевидно, не надо, мы ведь не девелоперы

Ivan8209

(PROG
(SETQ Q (GET-SOME-Q-FUNCTION
(SETQ QQ (GET-SOME-ANOTHER-QQ-FUNCTION
( ... (MAPCAR ITEMS ... ) ...
;; Ну, или какие там ещё MAP-ы есть...
Даже проще, ибо не надо заводить фиктивные переменные item, value.
---
...Bojite se viru?..

JERRY

Как раз такую функцию прекрасно можно записать в функциональном стиле, если под Item'ами понимать список. Разницы между твоим вариантом и функциональным не будет практически никакой, если не считать замены цикла рекурсией.

Ivan8209

Опять же, никто не мешает всё это записать через PROG, LOOP, GOTO...

Ivan8209

Для этого есть более оптимальные MAP, MAPCAR, MAPCDR и т.п.

Dasar

вот только среднему программисту надо долго объяснять, что разницы никакой нет.
Также сложно нормально объяснить, как можно посчитать сложность такой программы.

abrek

причём рекурсия (а фактически цикл) будет спрятана в функциях стандартной библиотеки

Ivan8209

"Средний программист" --- это "только Си(++)"?
---
non plus ultra

JERRY

Да, но я имел ввиду буквальный перевод. С map'ом становится еще проще, спора нет.

Dasar

больше всего программистов на бейсике...

abrek

алгоритмическую сложность любой программы, использующей динамическое распределение памяти, посчитать весьма нетривиально

Ivan8209

Скажем так, а оно надо?
---
...non plus ultra...

abrek

Тёмно-Серому надо, по его словам

Ivan8209

И что?
Это имеет какой-то практический смысл?
Тогда надо писать на статических языках a-la FORTRAN
---
...non plus ultra...

Dasar

ладно, скажем так:
я программировал на Lisp-е, даже успешно делал какие-то праки - мне не понравилось и я бы не рекомендовал бы для использования при написания прикладного ПО.
зы
хотя если бы я C/C++ и Pascal изучал бы только на праках в универе, мне бы они тоже не понравились...

Dasar

на практике под "оценкой сложности" понимают оценку O(f(n.
на такую оценку не сильно влияет ни наличие динамической памяти, ни своп, ни архитектура процессора.

Ivan8209

Ещё рекомендуют (O)Caml, ML, Haskell.
Говорят, что компилятор OCaml-а один из лучших по оптимизирующим способностям.
Я не проверял. Тебе, как профессионалу, это должно быть интереснее с т.з. трудозатрат.
---
...non plus ultra...

JERRY

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

Dasar

А Intellisence у них в среде есть?

JERRY

Кроме Лиспа, есть еще языки, у которых гораздо более user-friendly синтаксис. Я уже говорил, что на таком языке твой фрагмент будет выглядеть очень похоже.

Ivan8209

Я имею в виду: какую это имеет ценность?
Что от того?
У тебя ЯП нестатический, переменные создаются-уничтожаются.
Да там ты закопаешься в оценке сложности.
Тебе должно быть проще время засечь.
Это если бы ты писал что-то для СРВ или числедробительное, было бы другое дело.
А так, оно надо?
---
...non plus ultra...

Ivan8209

"Переведи!"

abrek

> на такую оценку не сильно влияет ни наличие динамической памяти
это зависит: O(n) вызовов malloc и free легко могут потребовать O(n^2) времени
кстати, всем читать http://www.joelonsoftware.com/printerFriendly/articles/fog0000000319.html и вообще http://www.joelonsoftware.com/
автор - крайне рюхливый чел, способен сформулировать словами то, что многие другие, вроде меня, могут только инстинктивно ощущать

Dasar

Конечно надо.
Есть, допустим, коллекция на 10 000 или 100000 элементов - надо по ней по бегать, что-нибудь поискать.
Вот объяснить, что вот так делать не хорошо (а надо головой думать):


for (int i = 0; i < 10000; ++i)
for (int j = 0; j < 10000; ++j)
{
if (items[i] == items[j])
return items[i];
}


довольно легко.
А вот то, что делать двойной map нехорошо, т.к. он приводит к n^2 действий уже намного сложнее.

Dasar

в системах со сборкой мусора и дефрагментацией памяти это проблема уменьшается.

Ivan8209

"В этом нет ничего нового,
Ибо вообще ничего нового нет."
www.colorforth.com
www.ultratechnology.com
Keywords and keyphrases: "MISC vs. RISC vs. CISC", "NOSC"
---
...Think Forth...

Dasar

Но одно дело поигратся с красивой игрушкой, а другое дело этой игрушкой пользоваться каждый день.
Во втором случае сразу хочется наличие большого кол-ва стандартных библиотек, легкость стыковки с legacy-кодом, удобная среда программирования (подсведка синтаксиса, подсказка имен и т.д. потенциальная багобезопасность языка, хороший (а лучше отличный) дебаггер и т.д.

Ivan8209

Это то же самое, что: почему "push bp; mov bp, sp", а не "enter".
Сложность операций задукоментировать и всё.

abrek

а в военное время значение "пи" может достигать четырёх
я бы сказал "увеличивается", так как проанализировать сложные алгоритмы труднее, чем простые, а хорошие алгоритмы сборки мусора и дефрагментации - сложные
для реального времени, например, нужны именно алгоритмы с верхней оценкой сложности, AFAIK в деле их постороения есть продвижения, но до идеала далеко

Ivan8209

Emacs в качестве IDE. (Всё уже украдено до нас!)
Багобезопасность упомянутых языков закладывалась при разработке.
Сообщение с другими программами такое же, как и везде: pipe, socket...

Dasar

> Сообщение с другими программами такое же, как и везде: pipe, socket...
а с чужими либами?

Dasar

> Emacs в качестве IDE.
Имена переменных/функций подсказывает?

Ivan8209

Это тоже есть.
Надо документацию читать. Этого я ещё не делал.

Ivan8209

Сначала надо узнать, понадобится ли тебе оно.
А так, вроде, всякие TAGS есть.
Либо должны быть. Здесь уже надо читать.

Dasar

Подсказка имен обязательно нужна, так как поощряет давать нормальные имена переменным/функциям, а не
имена вида ppx, ks1 и т.д.

JERRY

Добрые люди могли написать. А если еще не написали, можно самому заделаться благодетелем и накарябать что-нибудь на Emax'овском Lisp'е.

Ivan8209

Имеется в виду автодополнение? А.-д. есть.

Ivan8209

Боюсь, что "всё украдено..."

Dasar

а debugger?

Ivan8209

Там языки такие, что отладчик не требуется почти.
Хотя вроде даже и он есть.
Я уже, лично, и не помню, когда отладчиком по назначению пользовался.
Всё больше по распечатке, хотя и работаю в последнее время на Си.

JERRY

Из-за специфичности ФЯ, дебаггер там особо не нужен, хватает и print'a в нужном месте. Но вообще есть и дебаггеры, но я ими не пользовался, так что не могу сказать насколько они хороши.

Dasar

> Сложность операций задукоментировать и всё.
Сегодня как раз читал книжку "Типичные анти-патерны Java-ы"
Там как раз говорилось, что одна с самой распространенных ошибок является большое число коммуникаций через сеть, потому что EJB скрывает всю сложность работы с сетью под собой.
а ты говоришь задокументировать...

Ivan8209

Знаешь, как говорится, если руки "неоттуда" растут...
В смысле, как думаешь, так и работаешь.
Если это хорошо задокументировать, то никто не будет таким пользоваться просто так.
Либо, в противном случае, надо поступать по Бармину.

Dasar

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

Ivan8209

Как обломаются (с тормозами так и прочитают.
Java они как-то изучили? Не на глазок же.

Dasar

Такие вещи чаще на глазок и изучают. Несколько часовые курсы повыщения квалификация и вперед: работать, работать...
Продавцы той же Java-ы обещают, что если юзать Java-у, то все проблемы исчезнут - народ и ведется.
И экономит на обучении.

dberezhnoy

С шарп намного отличается от Java?

Ivan8209

Ну, так ты и должен отличаться от них, если ты профессионал.
Я, например, считаю, что ЯП должен быть легко расширяем до т.н. DSL, что отметает сразу всякие Си и Явы.
По-хорошему, мне вообще нужны только DSL. Остальное либо от бедности, либо от извращения.

Dasar

основа та жа, а фенек больше ,т.е. C# можно рассматривать как Java - 2.

dberezhnoy

А в C# тоже сборщик мусора есть? С# компилируемый или интерпритируемый?

Dasar

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

Dasar

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

Ivan8209

Это понятно и вполне очевидно.
Есть необходимая сложность, без которой ты не сможешь охватить задачу.
А есть излишняя сложность, которая мешает. Вместо того, чтобы решать поставленную задачу, ты занимаешься техническими трудностями.
Я не знаю, чему учат на вычмате или ещё где, я знаю, что там, где учился и учусь я, программированию не учат. Хотя зачатки должны бы прививать.
Те задачи, которые пытаются научить решать что в школе, что на первом курсе, не требуют таких сложных и опасных ЯП, как Си.
По большей части, надо было бы преподавать что-то вроде awk и обработку текста, а для численных методов использовать какой-нить Алгол или Фортран, хотя и тот же awk пойдёт.
Не надо человеку, по большей части, задумываться, почему надо писать a\[i\][j] для $a_{ij}$ вместо a(i,j особенно, когда в курсе анализа ему объясняют, что последовательность --- отображение натуральных чисел.
А тем более, что надо писать scanf("%lg",&a а не более естественное read(a). И непонятного назначения знак "&", который упустишь, а "а" ещё и окажется массивом. И даже про ошибку не узнаешь.
Указатели вредны.
---
for(ever; C - 4[ever] ; )

1234554321

Именно поэтому в подавляющем большинстве школ учат писать на Паскале.

Ivan8209

Хрен редьки не слаще.
1. Почему метки должны быть объявлены ещё и отдельно?
2. Почему нельзя переставлять разделы const и var?
3. "array [1..10] of real" бывают как совместимыми, так и несовместимыми?!
4. Почему нельзя "function f(n: integer; a: array[1..n] of integer):real"?
Что, собственно, мешает?
5.
var a: record a:real end;
...
with a do begin a:=...; p(a) end;
Вопросы. Есть ли совместимость? Где какое "а" использовано?
6. Какие написания синтаксически верны?
а) "begin p1; p2; end";
б) "begin p1; p2 end";
в) "begin p1; ; p2; end";
г) "begin p1; ; p2 end".
---
...Bojite se viru?..

1234554321

Не знаю, что такое Awk, но знаю, что в Фортране гораздо больше ограничений и нелепостей с точки зрения некого "здравого смысла".
А в целом, дискуссия неконтструктивна. Человек, освоивший плюсы на приличном уровне вполне разберётся в любом другом языке программирования, скажем в том же Хаскеле, очень быстро. Другое дело, что плюсы - максимально универсальный язык на данный момент, соответственно во многих областях он будет не оптимальным. Это вполне нормально. Новые знания можно(и ножно ) получать по мере возникновения соответствующих запросов .

Dasar

плюсы, не самый мощный язык. Даже зная плюсы, может быть большой проблемой переход на LISP или Smalltalk.

Ivan8209

Самый мощный, говоришь?
В них нет даже нормальной поддержки модульного программирования, только на уровне классов. Тяжёлое наследие Си.
Но ведь одним классом модуль может не исчерпываться.
Опять же, тот же самый вопрос:
const int n=100;
float a[n],b[n];
Наверняка не пройдёт.
Создание локальных массивов переменной размерности опять отсутствует?
float f(int n, float *a)
{ float b[n][n];
...
}
Для сравнения на Аду смотрел?
Куда более логичный язык по сравнению с Си++, при не меньшей мощности.
А уж на Лиспе можно такое навернуть в одной-двух строках, что приплюснутый насильник за месяц не разгребёт.
А по поводу awk (для справки: man awk можно задать простой естественный вопрос.
Ты таблички N на "много" чем обрабатываешь? В ёксель перегоняешь? Или просто не сталкивался?
Кстати, awk помощнее ёкселя будет в повседневной деятельности.
Я тут уже столкнулся с тем, что люди собирались легко выполняемую на авке работу проделывать вручную на ёкселе, только делать вот очень много.
Си++ по-хорошему, не только мало кому нужен, он вообще не нужен.
Простому пользователю он не нужен, потому что не даёт решать обыкновенные задачи, связанные с обработкой текста,
а другим нужен либо хороший полустатический или даже статический язык для расчётов,
либо куда более гибкий язык для всяких интерфейсов или логических программ.
Сравни, например, экспертные системы на Си(++) или Паскале с такими же, но на Лиспе, Прологе или другом более приличном ЯП.
---
...Bojite se viru?..

1234554321

самый мощный, говорю? перечитай. Говорю - универсальный.

1234554321

Про LISP не знаю, со SmallTalk-ом у меня было гораздо меньше проблем, чем у людей учивших его с нуля или после Фортрана. Но это только моё(ну и ещё нескольких моих знакомых, не суть) личное мнение.
P.S. Плюсы действительно НЕ самый мощный язык.

1234554321

Ещё раз, лично я не стремлюсь знать сотню(или больше? ) существующих языков программирования. Из мне известных(для интересующихся - С/C++ и клоны ака С# и Java, SmallTalk, Haskell, немножко - Fortran, Paskal, VB) на плюсах писать приятнее всего. Он не легче, не логичнее и не мощнее. Зачастую, он просто уродлив(плиз, не надо мне эти уродства перечислять, я с ними знаком...). НО дело в том, что в компьютерные языки приходится изучать и запоминать при помощи всё того же серого вещества, что и обычные языки. В лингвистике "плохие" особенности только ускоряют изучения языка, то же и здесь... Я хочу сказать, что это не "уродства" языка, а скорее особенности нашего строения.

freezer

В них нет даже нормальной поддержки модульного программирования, только на уровне классов. Тяжёлое наследие Си.
Но ведь одним классом модуль может не исчерпываться.



namespace Module
{
class A {};
class B{};
void F{}
}


или ты о чем?
Опять же, тот же самый вопрос:
const int n=100;
float a[n],b[n];

все корректно, будет работать

float f(int n, float *a)
{ float b[n][n];
...
}



float f(int n, float *a)
{
std::vector<float> b(n*n);;
...
}


А уж на Лиспе можно такое навернуть в одной-двух строках, что приплюснутый насильник за месяц не разгребёт.

- если насильник знаком с STL, то может и разгребет. Самая большая проблема при переходе на другой АЯП или компилятор - незнакомые сообщения об ошибках.
Си++ по-хорошему, не только мало кому нужен, он вообще не нужен.

если такие деньги платят за компиляторы, значит кому-то это нужно. Хотя, мне c# более удобным кажется... еще б шаблоны там были!
Сравни, например, экспертные системы на Си(++) или Паскале с такими же, но на Лиспе, Прологе или другом более приличном ЯП.

Сравни ядра осевые на асме и на бейсике!.. Главное достоинство СИ++ в том, что это универсальный язык, на нем при желании можно все что угодно сделать и почти под любой системой скомпилять.

freezer

Не надо человеку, по большей части, задумываться, почему надо писать a\[i\][j] для $a_{ij}$ вместо a(i,j особенно, когда в курсе анализа ему объясняют, что последовательность --- отображение натуральных чисел.

я для себя давно забацал класс (поверх std::vector) работающий с 2- и более мерными массивами, там обращаться можно и a(x,y).
Если надо, могу поделиться
А тем более, что надо писать scanf("%lg",&a а не более естественное read(a).

более естественно писать


std::cin >> a;


Вообще, прежде чем язык хаять, неплохо бы его сначала малость подучить...

JERRY


- если насильник знаком с STL, то может и разгребет. Самая большая проблема при переходе на другой АЯП или компилятор - незнакомые сообщения об ошибках.

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

Сравни ядра осевые на асме и на бейсике!.. Главное достоинство СИ++ в том, что это универсальный язык, на нем при желании можно все что угодно сделать и почти под любой системой скомпилять.

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

1234554321

>Вот только ядра пишут не на С++.
Это уже обсуждалось, сейчас происходит постепенное смещение в сторону доли плюсового кода. Во всяком случае в винде. Пока действительно основная часть - сишная.
>И С гораздо более универсален, чем С++.
Ты не правильно понимаешь универсальность. У С слишком многим пожертвовано ради скорости.

Ivan8209

"std::vector<float> b(n*n)" создаст матрицу n*n? В стеке?
И доступ к ней будет примерно того же времени, что и к "b[n][n]"?
Интерес весьма не праздный, ибо время тоже интересует.
Частичное раскрытие пространств имён есть?
Наподобие Ада: "use Module"?
Или всё время писать явную квалификацию?
m4 тоже равносильно марковским алгорифмам, а смысл?
А с зарешёченным си видишь? Сам признался, что шаблонов не хватает.
Вопрос по модулям.
Экспорт-импорт постоянных. Есть?
package Arch_dependent is
constant word_size: INTEGER := 8;
end;
/\/\/\/\/\/\/\/\
with Arch_dependent; procedure X(...) is type A is record v:array(0..Arch_dependent.word_size)of ...; ... end record; ... end;
Это тоже очень интересно.
У namespace-ов private-разделы есть?
Потом, "разгребёт" предполагает "напишет", а не "поймёт".
Опять же, могу я вызвать "F(float (*ffloat float *a)", передав ему функцию _литералом_. Например, как, примерно, "real (real f(real begin real x; ....; x end"?
Зачем мне определять ещё одно имя и вылезать куда-то там вверх по тексту?
В общем, завязываем с этим.
Мнения, как обычно, разделились, и возможно ещё непонимание друг друга.
---
...Я работаю...

freezer

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

ядра пишут на C/Asm, веб-странички на всяких Perl/Asp, формочки для работы с БД делают на Delphi/c#, ЧМЫ реализуют на Фортране, с COM-объектами (через IDispatch) проще работать в VBScript/JScript и т.д.
Но все это можно делать и на C++. В этом и универсальность. Си не менее универсален (но и не более однако Си++ непосредственно поддерживает практически все парадигмы программирования. Хочешь - загоняй все в функцию main и используй там метки с переходами, хочешь - пиши объектно-ориентированно, как учил дедушка Грейди Буч хочешь - вместо циклов юзай foreach... Полная свобода самовыражения.

1234554321

шаблоны скоро добавят (по меньшей мере обещают )

Ivan8209

Хорошо, а как он определит, что ему читать?
"а" это массив или указатель, если вдруг?
---
...Я работаю антинаучным аферистом...

Ivan8209

Функциональной ну никак не поддерживает.
Даже на уровне Алгола.
---
...Я работаю...

abrek

> Функциональной ну никак не поддерживает.
Преувеличение. Поддерживает в необходимом объёме: интерпретатор написать можно

freezer

"std::vector<float> b(n*n)" создаст матрицу n*n? В стеке?

нет, линейный массив n*n. Где она ее разместит - не важно (инкапсуляция, понимаешь но переменная будет автоматической, т.е. удалится по завершении функции
И доступ к ней будет примерно того же времени, что и к "b[n][n]"?

к сожалению в stdc++ нет нормального средства работы с многомерными массивами, поэтому программеры давно наваяли кучу своих классов, которые поддерживают в том числе и такой способ обращения к элементам.
Из стандартных средств стоит использовать valarray в соочетании с slice
Частичное раскрытие пространств имён есть?
Наподобие Ада: "use Module"?
Или всё время писать явную квалификацию?



using namespace Module;


RTFM, короче
У namespace-ов private-разделы есть?

у неймспейсов нет, есть у классов... если очень надо - используйте C#, там можно объявлять internal- и private-классы

freezer

Хорошо, а как он определит, что ему читать?
"а" это массив или указатель, если вдруг?

перегрузка операторов. RTFM

freezer

например?..

freezer

И доступ к ней будет примерно того же времени, что и к "b[n][n]"?

не углядел слово "времени". Да, доступ к элементам контейнеров vector и valarray происходит за время O(1) по определению. Нормальный компилятор в процессе оптимизиции последние две строчки:


int a[100];
vector<int> b(100);
a[10]=0;
b[10]=0;


переведет в одни и те же инструкции.

abrek

В Це с любыми знаками препинания AFAIK нет разумного способа сконструировать значение типа "функция", а значит, для функционального программирование оно как бы и не годится.
Про более экзотические парадигмы вспоминать не буду, ибо не рюхаю.

JERRY

Да, да соглашусь с предыдущим Анонимусом. Универсальность С++ во многих областях мнимая. Чем писать что-то на нем, гораздо проще написать интерпретатор/компилятор языка, на котором та проблема решается намного проще, на том же С++, а лучше на чем-нибудь предназначенном для написания компиляторов/интерпретаторов.
Кстати, написание компиляторов/интерпретаторов одна из таких задач. Как и те задачи, для которых предназначен Пролог или SQL.

abrek

тут всё дело в постановке задачи:
> гораздо проще написать интерпретатор/компилятор языка, на котором та проблема решается намного проще
написать проще, допустим
а как проще получить $$$ ?

freezer

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



std::transform(a.begin a.end b.begin c.begin std::plus<int>


std::plus<int> - чем не значение типа "функция"?..

1234554321

написать, на том же С++, прогу их печатающую?

1234554321

разница примерно как в:
рыба - селёдка, селёдка - рыба

freezer

задачи для который предназначены SQL, HTML, XML, FluentEnglish и задачи ЯП, как говорят у нас в Одессе, -- две большие разницы.

freezer



template<class InputIterator1, class InputIterator2, class OutputIterator,
class BinaryFunction>
OutputIterator transform(
InputIterator1 _First1,
InputIterator1 _Last1,
InputIterator2 _First2,
OutputIterator _Result,
BinaryFunction _Func
);


ну а _Func проканает?

JERRY

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

freezer

ЗЫ. Универсальность и удобство - вещи практически никогда не совместимые. Либо у тебя есть что-то универсальное, но в некоторыых случаях недостаточно удобное, либо узкоспециализированное, но очень удобное.

abrek

формальный параметр от значения не отличаем?
завтра с утра - марш в библиотеку

JERRY

Кстати хорошая идея заключалась в использовании специального языка. Правда язык был на основе XML, что, конечно, неприятно.

abrek

или это я слажал? плохо понимаю синтаксис C++
но _Func - по-любому не сконструированное значение

freezer

ок, персонально для Вас значением будет функционал std::plus<int> а для Корвина - формальный параметр в качестве которого передаются значения типа "функция". Вообще, тип "функция" можно было и в Си определить:


typedef int MyFunction(int);

JERRY

Т.е. ты считаешь, что задачи, которые решает SQL решить на С++ нельзя? SQL - это самый яркий пример, когда специализированный язык гораздо лучше якобы универсального. Также приведу в пример VoiceXML - специальный язык для обработки информации поступающей от абонента. Он на несколько порядков облегчает создание соответствующих программ.

1234554321

freezer

пра-ально! Надо все программы писать на специальном языке МатерныйРусский, а потом его транслировать в код на Си++
жалко пока еще такие трансляторы никто не сделал

JERRY

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

freezer

нет, на Си++ сформулировать запрос нельзя, на нем можно описать алгоритмы и структуры данных.
Разница как между задачей описать какое красивое солнце во время заката на МатерномРусском и нарисовать такую же картинку с помощью GDI32 на Си++.

abrek

тип определить можно, но вот все возможные значения его заданы на этапе компиляции, либо получаются динамическим связыванием с символами из библиотек
сконструированная же функция - это результат вычисления выражения, которое может быть нетривиальным
пример (по мотивам фрагмента от DG):


let sum_bounded lower upper = fun l -> (
let add_bounded acc v = if (v > lower) && (v < upper) then acc+v else acc
in
List.fold_left add_bounded 0 l
)


записано намеренно не самым красивым образом, чтобы проиллюстрировать идею
то, что после первого "=" -- то самое выражение

freezer

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

JERRY

Как это нельзя?
На любой запрос теоретически (если очень хорошо знать внутренне устройство базы данных) можно написать программу на С++, которая делает тоже самое. Только никто так делать не будет, поскольку дураков нет.

freezer

Все-таки у SQL другой смысл и назначение.... ладно, не буду флуд разводить
Только никто так делать не будет, поскольку дураков нет

угу, именно поэтому ко всяким MS SQL-ям и Ораклам прилагаются Си-шные библиотеки... Чтоб последние дураки вымерли от непомерного напряга.
Но и с их помощью все же не запросы описывают...

JERRY

Шаблоны не дают права работать топором там, где лучше применить бензопилу.
Если тебе не нравится SQL, есть для примера, как я уже говорил, VoiceXML - стандартизованный язык, который используется уже, я думаю, многими телекоммуникационными компаниями. Все, что он делает можно написать и на С++ (и раньше на нем и писалось только это гораздо менее эффективный подход, что на практике видно невооруженным глазом.

freezer

а по-русски, что там делается?..

1234554321

Хе, а я то думал один я не знаю шо це за хрень, даже стыдно стало(трохи-трохи)...

freezer

о чем мы спорим не понятно. Если Вы хотите доказать, что Си++ - не универсальный язык, нужно предложить задачу, которая с помощью Си++ не решается принципиально. То что векторную мультяху проще делать во Flash, веб-сайт проще делать с помощью ASP (а не ISAPI или CGI а файлы проще удалить из батничка (примеры можно приводить до бесконечности) - это никак не делает Ц++ менее универсальным языком.

freezer

кажись я понял,что это значит:


template<class T, class BinOp, class LogOp>
class CondOp
{
BinOp B;
LogOp L;
public:
CondOp(BinOp b, LogOp l): B(b L(l){}
T operatorT x, T y) { return L(y) ? x : B(x,y);}
};
// -------------------
template<class T>
class CheckInterval
{
T lower, upper;
public:
CheckInterval(T Lower, T Upper):lower(Lower upper(Upper) {}
bool operatorT x) { return x>lower && x<upper;}
};
// -------------------
template<Iterator It, class T>
T BoundedSum(It begin, It end, T lower, T upper)
{
return std::accumulate(begin, end, T CondOp<T, std::plus<T>, CheckInterval<T> >(std::plus<T> CheckInterval<T>(lower, upper;
}

abrek

следим за руками:
называем (let) именем sum_bounded функцию, зависящую от двух аргументов (lower и upper возвращающую то, что после знака "=", а именно:
функцию (fun) принимающую аргумент l (список целых чисел) и возвращаюшую сумму всех таких элементов v списка, для которых верно (v > lower) && (v < upper)
детали реализации: обход списка скрыт внутри библиотечной функции List.fold_left, которой передаётся функция add_bounded, обрабатывающая один элемент, и начальное значение счётчика (т.е. ноль).

JERRY

Point в том, что универсальность не является большим плюсом. Многие специализированные задачи можно решить более простыми методами.
VoiceXML позволяет вводить и распозновать информацию с телефона (звук и нажатые клавиши в зависимости от полученной информации принимать какие-то решения и выдавать информацию абоненту.
По виду похож на ECMA-Script (Java-Script). Только там нет функций, немного другое построение программ и облегчено решение основных задач - получить и отправить информацию на телефон.
Если необходимо, можно вызвать внешнюю функцию, чтобы сделать что-то, что в языке сделать нельзя - например, обратиться к базе данных.
Пример, чего он может, можете услышать позвонив на АССА'у в МТС. Там она пока на С++, но 100% будет рано или поздно работать на VoiceXML.

Dasar

все-таки замыкания ("closures") более наглядная штука...

freezer

шо цэ такэ?

freezer

как всегда: в чем-то плюсом, в чем-то - минусом.

abrek

да, вроде бы примерно то же самое, только нужно самому задавать представление частично вычисленных функций
реально писать в таком стиле мало кому захочется, естественно

freezer

если есть надежда что их повторно используют - то можно и написать.
фанктор CheckInterval я практически из своего действующего проекта выдрал Свинство, конечно, что ничего такого в STL нет: нужно многое самому делать.

abrek

Самое вкусное - это lexical scoping, который в варианте на C++ эмулируется переменными-членами класса и соотв. конструктором

abrek

тут вот в чём дело: фактически, при написании своего варианта ты немного поработал компилятором: перевёл фрагмент программы на ЯВУ в C++, который в данном случае был использован как язык низкого уровня. Если бы в функциональном стиле была написана большая программа (пусть даже не на настоящем языке, а на псевдокоде либо совсем в голове то переводить её на С++ таким же образом было бы невыгодно, а эффективней было бы написать собственно компилятор, чтобы дальше работала машина.

freezer

еще вариант:


template<class T>
class Accumulator
{
T acc;
T lower, upper;
public:
Accumulator(T L, T U): acc lower(L upper(U){}
void operator(T x) {acc+=(x>lower && x<upper ? x : T;}
operator T {return acc;}
};
//--------------------------
template<Iterator It, class T>
T BoundedSum(It begin, It end, T lower, T upper)
{
return std::for_each(begin, end, Accumulator<T>(lower, upper;
}

freezer

дело в том, что я написал не в каком-то извращенном (по отношении к Си++) стиле, а в стиле STL. Собственно вся STL (полностью входящая в стандарт языка) выполнена в точно таком же функциональном стиле.

abrek

Здесь функциональный стиль явно не выдерживается, за счёт чего и получается чуть более компактный код

freezer

зато вся прелесть в том, что объект "функция" может менять какие-то свои свойства в результате вычислений.

freezer

ладно. Спокойной ночи!
а то развели тут, понимаешь, Свящунную Войну на тему, можно ли считать С++ немного функциональным или нет...

abrek

именно громоздкость кода показывает, что функциональная парадигма не родная для C++
возможность сокращения кода через отказ от функционального стиля показывает это же

Dasar

В принципе, вот то, что Вы сейчас приводите - это и есть замыкание.
на C# будет что-то близкое к такому:
int n = sum(items, new Filter(a){lower < a && a < upper});

freezer

кстати, F# не смотрел?...
ладно, все, спать ушел

Dasar

А ты, правда, что ли шаблоны в C++ не знаешь/не юзаешь?
Это ты зря, может именно поэтому тебе "экзотика" нравится больше, чем c++.

Ivan8209

Здрасьте!
"Никогда не пей эту гадость!.."
"<type> a[N]" всегда эквивалентен "<type> *a", то есть указателю.
Выводы?
А по поводу "неважно, где, всё равно удалит", почитай, как работает куча. Это значительно медленнее.
Хочешь ещё засаду?
"cin >> a" --- это не свойство языка, а свойство штатных библиотек.
Свойство языка здесь только в перегрузке операции ">>", но как ты будешь разделять массивы и указатели?
---
...Я работаю антинаучным аферистом...

abrek

перечитал на свежую голову, и что-то не понял:
как, используя этот код, во время выполнения получить из пары чисел функцию(или что там вместо неё обрабатывающую список(или что там вместно него)?

Ivan8209

По моим данным, первый рабочий интерпретатор Лиспа был написан на Фортране.
Но это нисколько не означает, что Фортран поддерживает функциональное программирование, ибо в нём нет даже процедурного типа. Я имею в виду, тот Фортран, "IV" или подобный, на котором был написано тот самый Лисп.
---
...Я работаю...

abrek

Можно я попробую ответить? Спасибо
a[N] - нифига не массив, а только притворяется им, причём довольно плохо
в C нет настоящих массивов, в С++ есть соответствующие классы в STL, с указателем из никак не перепутать
по поводу времени доступа: доступ к одному элементу естественно медленнее (как мимимум один лишний indirection
а вот к миллиону эл-тов в одном фрагменте кода - так же, так как оптимизирующий компилятор вычислит нужный указатель один раз.
т.е., если матрицы корёжить, пофиг должно быть по-идее

Ivan8209

Вот в том-то и дело.
Ещё не надо забывать, что распределение памяти в стеке быстрее, чем в куче.
Ну, хорошо, я получил объект типа "массив-самопал" Си++, память где выделится?
Будет ли передаваться копия массива, если я объявлю, что он является только входным параметром и не изменяется?
Или опять будет выделение и освобождение памяти в куче?
А если создаётся несколько локальных массивов, то будет столько же действий выделения-освобождения?
А почему не одно? То, которое "sp+=sizeof(...)+sizeof(...)+...;".
Ещё вопрос по синтаксису.
Почему тогда надо объявлять массив отдельно как "dimension<int> a(n,m,k,l);", а не естественным поддерживаемым способом "int a[n][m][k][l];"?
Будет ли выполняться приведение типов, если что? Писать ещё одну приводящую операцию? Откуда брать размерности массива в последнем случае?
---
...Я работаю...

abrek

Слушай, дорогой, начинай уже RTFM.
Странно видеть вопросы про C++, на которые даже я могу ответить

Ivan8209

Риторический вопрос ответа, иногда, не подразумевает.

Ivan8209

Так, народ, все резко посмотрели на тему!
Прошу дальше говорить по существу.
---
...Я работаю...

abrek

А совместим ли сабж с зарабатыванием $$$? А $$$$$?
Принимаются ответы в виде ссылок на success stories.

Ivan8209

www.cornfed.com
---
...Bojite se viru?..

abrek

А где там про $?

Ivan8209

Это я в смысле, почему бы и нет?
Поддержка внутренней документации проще.
---
...Я работаю...

freezer

(извинете за оффтопик)
Использовать мой код надо примерно так:


int a[10]={1, 2, 3, 2, 5, 6, 7, 8, 9, 10};
cout << BoundedSum(a, a+10, 2, 8) << endl;
// ------------------------------
std::list<int> lst(a, a+10);
cout << BoundedSum(lst.begin lst.end 1, 5) << endl;


ЗЫ Естественно, эта функция будет работать с любыми итерируемыми контейнерами, не только со списками и массивами

abrek

это не то
надо что-то вроде:
some_func_type sum_func = BoundedSum(1, 5);
std::list<int> lst1, lst2;
/* ...... */
int sum1 = sum_func(lst1);
int sum2 = sum_func(lst2);

freezer

тогда так:


CondOp<int, std::plus<int>, CheckInterval<int> > bin_func(std::plus<int> CheckInterval<int>(lower, upper;
std::list<int> list1, list2;
int sum1= std::accumulate(list1.begin list1.end 0, bin_func);
int sum2= std::accumulate(list2.begin list2.end 0, bin_func);

abrek

Если не сложно, доведи до того, чтобы можно было только один параметр передавать - список, как в моём примере.
Подозреваю, что вместо функции получится объект с выделенным методом для вычисления функции.

freezer

ну да, естественно.
Только будет не совсем метод, а операция "круглые скобки"

abrek

понимаю
довести сложно, ч.т.д.
транслятор легко сгенерирует нужный код, а вот человека заломает
про это и говорится

freezer

довести несложно:


template<class T>
class BoundedSum
{
typedef CheckInterval<T> bin_check;
typedef CondOp<T, bin_check, std::plus<T> > bin_op;
bin_op op;
public:
BoundedSum(T lower, T upper): bin_op(std::puls<T> bin_check(lower, upper {}
template<class L>
T operator (const L& list)
{
return std::accumulate(list.begin list.end T bin_op);
}
};


usage:


BoundedSum<int> summa(1, 10);
std::list<int> a, b;
std::vector<int> c;
/* */
int A=summa(a B=summa(b C=summa(c);


(параметры мог местами перепутать)

Ivan8209

"Real programmer can program FORTRAN in any language."

freezer

спасибо за комплемент )
а еще я могу сделать полиморфизм на неприплюснутых сях
Real Programmers don't write in FORTRAN.
FORTRAN is for wimp engineers who wear white socks.
They get excited over finite state analysis
and nuclear reactor simulation.

natali20

А вышивать умеешь? Крестиком?

freezer

только на XML-е

Ivan8209

Я тоже могу. Только нафиг?
---
Universal Answer: "Do not do it!" (Михаил Гассаненко)

freezer

ну например, если хочешь front-end компилятор какого-нибудь ОО-языка сделать...

Ivan8209

Можно заколачивать гвозди и утюгом.
Только, если есть молоток, зачем это надо?
---
...Лень --- движитель прогресса!..

freezer

объясняю: есть у тебя утюг с микропроцессором. Си-шный компилятор для него сделали, а Си++ - не успели (конкуренты в затылок дышут, некогда компиляторы делать). Ты пишешь прогу на Си++, потом компиляешь front-end компилятором, потом запускаешь Си-компилятор утюга. И все, на нем кроме функции "глажка" появились игры, каталог тканей и т.д.

Ivan8209

Про кросс-компиляцию слышал?
Ладно, это всё так.
Ты по теме (наверх ^^туда^^ погляди, если забыл : ) скажи хоть что-нибудь, а то неприлично как-то.
---
...Bojite se viru?..

1234554321

>Интересно, этим кто-нибудь пользуется?
по теме: нет, этим никто не пользуется

mysha

Все правильно.Вроде как уже упоминалось длины записи программ в различных системах кодирования отличаются с математической точки несильно, важно только людям сколько символов набивать и/или рюхать, да и при наличии правильно написанных компиляторов эти программы транслируются примерно в равный код Ничего особо действительно нового с компиляторной точки зрения "новые" языки не приносят, а приносят только с культурной точки зрения. Процедурное программирование, объектно ореинтированное программирование, WYSIWYG etc. всего лишь попытки создать общечеловеческую культуру, для быстрого написания программ, когда нужна параллельная работа большого количества людей. А в таких проектах сейчас больше важна коммуникация человека с человеком, нежели человека с компьютером что и попытался в свое время сделать Кнут, скрестив тех с C.
Для того чтобы это начать использовать нужно другое воспитание, очень многие старики так и не перешли на объектно ореинтированное программирование.......
P.S. Ну конечно все зависит от выбранных ценностей - парадокс Linux никто не отменял, хотя по-моему все мы от него страдаем

freezer

а что это за парадокс?

mysha

А парадокс в том, что миф о том, что любую программу можно создать коллективом из одного-двух человек на коленке находит практическое подтверждение. Поэтому зачем корпорации и документации - двое всегда устно смогут договориться... и Linux не единственный пример
Оставить комментарий
Имя или ник:
Комментарий: