Re[5]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: gbear Россия  
Дата: 21.05.04 04:42
Оценка:
Здравствуйте, INTP_mihoshi, Вы писали:

INT>Здравствуйте, SWW, Вы писали:


SWW>>С одной стороны, математическая нотация не так уж однозначна: достаточно сказать, что в одних странах в качестве десятичного разделителя используется точка, в других — запятая. Если в таком простом вопросе нет единства, что уж говорить о более сложных вещах.


INT>ИМХО любая текстовая или графическая нотация либо неоднозначна, либо громоздка. Но в математике есть точная семантическая нотация, т.е. совокупность однозначно интерпретируемых понятий. Например, поле, или там, целое число — имеют однозначный смысл. А вот в программировании такие, скажем, базовые понятия, как класс и функция понимаются в каждом языке по разному.


Дело не только и не столько в семантике — хотя это тоже проблема.

Но, что за смысл Вы вкладываете в понятие "текстовая или графическая нотация" — ИМХО, любая нотация либо то, либо другое

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

Но опять же... повторюсь... в этом вопросе мы напоминаем мне филогов с их определением ямба и хрея С их точки зрения, наверное, оно тоже "достаточно формализованно"... покрайней мере моя жена так и не поняла почему я долго над этим определением смеялся... Рискну процетировать (не пинать за оффтоп, пожалуйста, ИМХО, оно весьма поучительно).

Упрощённо это выглядит так:

Ямб — это когда ударение на четных слогах. Но может быть и на нечетных.
Хорей — это когда ударение на нечетных слогах. Но может быть и на четных.


Ничего не напоминает?

Тем не менее, они (филологи) с легкостью различают ямб и хорей... вот только объяснить другим, для большинства из них проблема... Т.к. четкое определение данное (кем бы вы думали...) — Колмогоровым (угу, тем самым) — воспринимается ими с трудом, и расценивается как усложнение.

Так и мы — вполне можем понимать друг друга... невзирая даже на отсутсвие четкой терминологии... но вот "объяснить другим"... и смотрим на введение формализации, как на излишнее усложнение
---
С уважением, Сиваков Константин.
Re[7]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.05.04 08:39
Оценка: -2
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Kh_Oleg, Вы писали:


K_O>>Не надо впадать в крайности. "+" — это символ сложения. В повседеневной жизни мы обычно складываем числа.

K_O>>А вот "++" — это операция инкремента. Еще нужно объяснять, что это за операция такая, и что для чисел она означает увеличение на единицу. Ну а перегрузка операторов — это вообще из серии "некоторое действие, которое выглядит как сложение, но делает то, что знаю только я!"
WH>Ну если тебе так хочется то ты можешь продолжать писать на языках которые ни чего не умеют, а я буду использовать язык который позволяет мне выражать свои мысли так как я хочу.
WH>Например на С++ можно написать шаблон такого массива что... короче пример
WH>
WH>int size=10000;
WH>array_t<float> a(size);
WH>array_t<float> b(size);
WH>array_t<float> c(size);
WH>array_t<float> d(size);
WH>array_t<float> e(size);
WH>array_t<float> f(size);
WH>float x;
WH>float y;
WH>float z;
WH>//тут инициализация
WH>f*=(a/x+5)*b-(y*c-d/5)/e-z;
WH>//что эквивалентно (без перегрузки операторов)
WH>for(int i=0;i<size;++i)
WH>    f.at(i)*=(a.at(i)/x+5)*b.at(i)-(y*c.at(i)-d.at(i)/5)/e.at(i)-z;
WH>

WH>те не будет создано ни одного временного массива.
WH>подробности в книге "Шаблоны С++. Стравочник разработчика" Вандевурд и Джосаттис
Два замечания:
Во-первых, в выражении использованы значения всех переменных, кроме массива f. Причем использованы без инициализации. Понятно, что в реальном проекте ты уж наверняка все бы проинициализировал. Только это как-то... неаккуратненько. А потом на форуме и всплывают вопросы, а почему это у меня в Debug все работает, а в Release — нет.
Второе, в твоем "кратком" выражении, за которое ты ратуешь, ни фига не понятно, где переменная типа double, а где — элемент массива. Упаси Бог, когда-нибудь отлаживать ошибку в таком выражении. Зачем нужна такая краткость в ущерб читабельности?
Но и это не главное.
Цитирую сам себя:

некоторое действие, которое выглядит как сложение, но делает то, что знаю только я!

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

WH>Тоже со строками

WH>
WH>string s1;
WH>string s2;
WH>string s3;
WH>string s4;
WH>string s5;
WH>//тут инициализация
WH>string s6=s1+s2+s3+s4+s5;
WH>//что эквивалентно (без перегрузки операторов)
WH>string s6=string_cat(s1, string_cat(s2, string_cat(s3, string_cat(s4, s5))));
WH>

Оператор сложения для строк, означающий конкатенацию — это, пожалуй, единственное применение перегрузки операторов, где оно действительно необходимо. А все потому, что в ЯП строка должна быть базовым типом! Таким как char, int, double. Так и string.
Вот для базовых (примитивных) типов операторы должны быть определены. Но не для составных типов, определяемых программистом!

WH>Тоже с векторами и матрицами

WH>
WH>vector v1;
WH>vector v2;
WH>matrix m;
WH>//тут инициализация
WH>vector v3=(v1-v2)*m;
WH>//что эквивалентно (без перегрузки операторов)
WH>vector v2=mul_vector_matrix(sub_vector_vector(v1, v2), m);
WH>

Умножение матриц — это целый алгоритм, к тому же, перемножение матриц, операция некоммутативная (A*B != B*A), а из текста этого не видно. Понятно, что часто хочется записать выражение в программе в виде, близком к виду формулы из книги. Но тогда, для того, чтобы понять, что здесь происходит надо будет эту самую книгу перечитать.

WH>Так на каком языке лучше писать? на том где есть шаблоны и перегрузка операторов или на том где их нет?

На том, на котором можно более кратно, точно и понятно выразить свою мысль. В этих примерах было кратко, не совсем точно (неинициализированные переменные) и непонятно.

WH>ЗЫ Судя по тому что ты говоришь для тебя лучший язык это ассемблер. Простой, понятный, нет неоднозначностей. Просто чудо, а не язык...

Точно, одна беда — слишком уж он низкоуровневый

WH>ЗЗЫ А тех кто перегружает операторы не интуетивным образом надо сжигать на костре и предавать анафиме...

Но почему язык позволяет таким индивидуумам так хулиганить?
Re[8]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 09:48
Оценка: 1 (1)
Здравствуйте, Kh_Oleg, Вы писали:

K_O>Два замечания:

K_O>Во-первых, в выражении использованы значения всех переменных, кроме массива f. Причем использованы без инициализации.
1)Во всех трех примерах написано //тут инициализация. Тебе что больше не кчему предратся?
2)Если ты посмотришь внимательно то значение массива f тоже использовано. Оператор *=
K_O>Понятно, что в реальном проекте ты уж наверняка все бы проинициализировал. Только это как-то... неаккуратненько.
А нахрена в примерах писать гору не относящегося к делу кода?
K_O>Второе, в твоем "кратком" выражении, за которое ты ратуешь, ни фига не понятно, где переменная типа double, а где — элемент массива. Упаси Бог, когда-нибудь отлаживать ошибку в таком выражении. Зачем нужна такая краткость в ущерб читабельности?
А что должно быть понятно в выражении которое писано от балды? В реальной программе будут вполне себе говорящие имена.

K_O>Не зная, как перегружены операторы для этих массивов абсолютно невозможно сказать, какой элемент массива учавствует в выражении!!!

Один раз читаем доку в которой написано что-то типа

Для типа array_t перегружены все арифметические операторы так что запись вида arr1*arr2 трактуется как поэлементное умножение массивов. А запись вида const*arr трактуется как поэлементное умножение массива на константу.

Я знаю что из меня плохой писатель хелпов. Но скажи что тебе после прочтения этого будет не понятно в выражении тапа
arr1=arr2*const1-arr3/const2;
Ы?
K_O>Оператор сложения для строк, означающий конкатенацию — это, пожалуй, единственное применение перегрузки операторов, где оно действительно необходимо. А все потому, что в ЯП строка должна быть базовым типом! Таким как char, int, double. Так и string.
На сччет того должны быть строки одним из базовых типов языка или нет это тема для отдельного флейма.
K_O>Вот для базовых (примитивных) типов операторы должны быть определены. Но не для составных типов, определяемых программистом!
Категорически не согласен. Допустим я реализовал библиотеку для работы с числами в несколько сотен быйт и что мне теперь для них нельзя операторы перегрузить?
А взят тотже boost::spirit когда надо быстро написать не сложный парсер то эта штука очень удобна. Но он небыл бы возможен без перегрузки операторов.

K_O>Умножение матриц — это целый алгоритм, к тому же, перемножение матриц, операция некоммутативная (A*B != B*A), а из текста этого не видно. Понятно, что часто хочется записать выражение в программе в виде, близком к виду формулы из книги. Но тогда, для того, чтобы понять, что здесь происходит надо будет эту самую книгу перечитать.

Я вобще не понимаю как можно писать программу для предметной области хотябы поверхностно не разобравшись в ней? И вобще С++ это Язык ВЫСОКОГО Уровня, а ЯВУ были созданы для того чтобы сложные действия можно было записать просто.

K_O>На том, на котором можно более кратно, точно и понятно выразить свою мысль.

Это на каком если не секрет?
K_O>В этих примерах было кратко,
K_O>не совсем точно (неинициализированные переменные)
Это не аргумент. см выше.
K_O>и непонятно.
Такой чувство что ты на принци пошол. Что тут не понятного?

K_O> Но почему язык позволяет таким индивидуумам так хулиганить?

А тут либо полный запрет на перегрузку и тогда нельзя писать интуитивно понятные бибииотеки. Либо есть шанс что один придурок из тысячи перегрузит операторы так что можно будет складывать метры с килограммами. Но так-как таких орлов практически нет то я предпочитаю чтобы была возможность перегружать операторы.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[9]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.05.04 10:00
Оценка:
Здравствуйте, WolfHound, Вы писали:


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

Перегрузка не всегда понятна и очевидна. Кроме того при поиске кода в исходниках по функции легче найти ее исходный код.
и чем Equals хуже == ????? И другие эквивалентные операторы. Дольше писать согласен (да и то при подсказке через точку нет проблем),
хуже читать — нет. Так думай перегружен метод для == или это ReferenceEquals.
Я лично предпочитаю единые по написанию функции четко определяющие вид операции вместо перегруженных операций.
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[9]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.05.04 10:31
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Kh_Oleg, Вы писали:


K_O>>Два замечания:

K_O>>Во-первых, в выражении использованы значения всех переменных, кроме массива f. Причем использованы без инициализации.
WH>1)Во всех трех примерах написано //тут инициализация. Тебе что больше не кчему предратся?
WH>2)Если ты посмотришь внимательно то значение массива f тоже использовано. Оператор *=
K_O>>Понятно, что в реальном проекте ты уж наверняка все бы проинициализировал. Только это как-то... неаккуратненько.
WH>А нахрена в примерах писать гору не относящегося к делу кода?
А что, для того, чтобы проинициализировать такой супер краткий шаблон надо "гору кода" писать? Так толку тогда с таких кратких выражений...

K_O>>Второе, в твоем "кратком" выражении, за которое ты ратуешь, ни фига не понятно, где переменная типа double, а где — элемент массива. Упаси Бог, когда-нибудь отлаживать ошибку в таком выражении. Зачем нужна такая краткость в ущерб читабельности?

WH>А что должно быть понятно в выражении которое писано от балды? В реальной программе будут вполне себе говорящие имена.
Я говорю не про имена переменных, а про то, что не понятно, где просто переменная, а где массив.

K_O>>Не зная, как перегружены операторы для этих массивов абсолютно невозможно сказать, какой элемент массива учавствует в выражении!!!

WH>Один раз читаем доку в которой написано что-то типа
WH>

WH>Для типа array_t перегружены все арифметические операторы так что запись вида arr1*arr2 трактуется как поэлементное умножение массивов. А запись вида const*arr трактуется как поэлементное умножение массива на константу.

WH>Я знаю что из меня плохой писатель хелпов. Но скажи что тебе после прочтения этого будет не понятно в выражении тапа
WH>arr1=arr2*const1-arr3/const2;
WH>Ы?
Я вообще-то не очень люблю доки читать. Если надо в чем-то разобраться — смотрю в исходники. Доки часто просто отстают от реализации или там не все нюансы отражены. Но дело не в этом. Для того, чтобы понять как работает приведенный тобой шаблон я должен смотреть либо в доки, либо в исходники. А вот если бы вместо "*" использовался метод, скажем, MultiplyItemByItem, то никуда не надо было лезть и в чем-то разбираться. Такой код читался бы проще.

K_O>>Вот для базовых (примитивных) типов операторы должны быть определены. Но не для составных типов, определяемых программистом!

WH>Категорически не согласен. Допустим я реализовал библиотеку для работы с числами в несколько сотен быйт и что мне теперь для них нельзя операторы перегрузить?
Я бы не стал так делать. Потому как работа с такими числами — это нетривиальные алгоритмы, которые, думается мне, потребуют особого порядка их использования и будут обладать некоторыми ограничениями. Все равно мне придется найти доп. инфу по ним, чтобы эффективно использовать твою библиотеку. Так пусть эта инфа находится прямо в тексте программы в виде имени метода.

WH>А взят тотже boost::spirit когда надо быстро написать не сложный парсер то эта штука очень удобна. Но он небыл бы возможен без перегрузки операторов.

Не видел, не знаю.

K_O>>Умножение матриц — это целый алгоритм, к тому же, перемножение матриц, операция некоммутативная (A*B != B*A), а из текста этого не видно. Понятно, что часто хочется записать выражение в программе в виде, близком к виду формулы из книги. Но тогда, для того, чтобы понять, что здесь происходит надо будет эту самую книгу перечитать.

WH>Я вобще не понимаю как можно писать программу для предметной области хотябы поверхностно не разобравшись в ней?
Да не об этом речь...
Я говорю о том, что разные по реализации алгоритмы должны и в тексте программы выглядеть по-разному, т.е. иметь разные имена.
Re[6]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: INTP_mihoshi Россия  
Дата: 21.05.04 10:42
Оценка:
Здравствуйте, gbear, Вы писали:

G>Дело не только и не столько в семантике — хотя это тоже проблема.


G>Но, что за смысл Вы вкладываете в понятие "текстовая или графическая нотация" — ИМХО, любая нотация либо то, либо другое


Текстовая нотация — это подмножество графической.

G>И мне видется очень важным, что бы ко всему прочему, "программисткой нотацией" можно было с легкость пользоваться вооружившись "карандашом и листком бумаги".


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

G>Но опять же... повторюсь... в этом вопросе мы напоминаем мне филогов с их определением ямба и хрея С их точки зрения, наверное, оно тоже "достаточно формализованно"... покрайней мере моя жена так и не поняла почему я долго над этим определением смеялся... Рискну процетировать (не пинать за оффтоп, пожалуйста, ИМХО, оно весьма поучительно).


На самом деле у нас ситуация гораздо серьезнее из за того, что в общении учавствуют не только люди. И требования к точности и объемы текстов у нас гораздо больше. Поэтому лично я чувствую необходимость не столько в какой-то письменной нотации удобной для понимания человеком, сколько в способе кодирования информации, позволяющим преобразования межу различными представлениями (языками, нотациями etc.) без потерь.

Подробнее сейчас описывать времени нет, но я как раз сейчас это направление исследую. Если интересно могу расписать подробнее. "Понятия" в моем посте о "минимальных контекстно-независимых решениях" как раз относится к этой теме.
Re[9]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: INTP_mihoshi Россия  
Дата: 21.05.04 11:46
Оценка:
Здравствуйте, WolfHound, Вы писали:

K_O>>Не зная, как перегружены операторы для этих массивов абсолютно невозможно сказать, какой элемент массива учавствует в выражении!!!

WH>Один раз читаем доку в которой написано что-то типа
WH>

WH>Для типа array_t перегружены все арифметические операторы так что запись вида arr1*arr2 трактуется как поэлементное умножение массивов. А запись вида const*arr трактуется как поэлементное умножение массива на константу.


Кстати, такие вещи вроде-бы принято через итераторы делать... Тогда ты не будешь привязан к представлению контейнера.
Re[10]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 12:00
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:

K_O>А что, для того, чтобы проинициализировать такой супер краткий шаблон надо "гору кода" писать? Так толку тогда с таких кратких выражений...

Зачем писать код который не относится к теме?

K_O>Я говорю не про имена переменных, а про то, что не понятно, где просто переменная, а где массив.

А я тебе говорю что из имен переменных ясно где что.

K_O>Я вообще-то не очень люблю доки читать. Если надо в чем-то разобраться — смотрю в исходники. Доки часто просто отстают от реализации или там не все нюансы отражены.

Плохой пожход. Если доки есть то их надо прочитать. Даже если они и отстали то всеравно будет легче разобратся с исходниками.
K_O>Но дело не в этом. Для того, чтобы понять как работает приведенный тобой шаблон я должен смотреть либо в доки, либо в исходники. А вот если бы вместо "*" использовался метод, скажем, MultiplyItemByItem, то никуда не надо было лезть и в чем-то разбираться. Такой код читался бы проще.

f*=(a/x+5)*b-(y*c-d/5)/e-z;
или
MultiplyAssignItemByItem(f, SubtractItemByScalar(SubtractItemByItem(MultiplyItemByItem(AddItemByScalar(DivideItemByScalar(a, x), 5), b)), DivideItemByItem(SubstractItemByItem(MSI(y, c), DivideItemByScalar(d, 5)), e), z));

Это не то что прочитать... это написать трудно
Человек просто запутается в такой записи.
даже если переписать так(пока переписывал исправил несколько ошибок)
    MultiplyAssignItemByItem
        (f
        ,SubtractItemByScalar
            (SubtractItemByItem
                (MultiplyItemByItem
                    (AddItemByScalar
                        (DivideItemByScalar
                            (a
                            ,x
                            )
                        ,5
                        )
                    ,b
                    )
                ,DivideItemByItem
                    (SubstractItemByItem
                        (MultiplyScalarByItem
                            (y
                            ,c
                            )
                        ,DivideItemByScalar
                            (d
                            ,5
                            )
                        ,e
                        )
                    ,z
                    )
                )
            )
        );

то всеравно до читабельности
f*=(a/x+5)*b-(y*c-d/5)/e-z;

ой как далеко.
WH>>А взят тотже boost::spirit когда надо быстро написать не сложный парсер то эта штука очень удобна. Но он небыл бы возможен без перегрузки операторов.
K_O>Не видел, не знаю.
А ты скачай boost да посмотри.
Например так задается грамматика калькулятора
struct calculator : public grammar<calculator>
{
    template <typename ScannerT>
    struct definition
    {
        definition(calculator const& /*self*/)
        {
            expression
                =   term
                    >> *(   ('+' >> term)[&do_add]
                        |   ('-' >> term)[&do_subt]
                        )
                ;

            term
                =   factor
                    >> *(   ('*' >> factor)[&do_mult]
                        |   ('/' >> factor)[&do_div]
                        )
                ;

            factor
                =   lexeme_d[(+digit_p)[&do_int]]
                |   '(' >> expression >> ')'
                |   ('-' >> factor)[&do_neg]
                |   ('+' >> factor)
                ;
        }

        rule<ScannerT> expression, term, factor;

        rule<ScannerT> const&
        start() const { return expression; }
    };
};

EBNF грамматика прямо на С++...
Да по исходникам ты в ней не разберешься... Их там очень много(1,433,069 байт)... Читайте доки. Они рулез.
Зато как клиентский код выглядит... просто прелесть.

K_O>Я говорю о том, что разные по реализации алгоритмы должны и в тексте программы выглядеть по-разному, т.е. иметь разные имена.

Зачем?
Какая разница что складывать два вектора или два числа? И то и другое сложение. Дык зачем для векторов вводить ужасную функцию типа AddVectorVector?
Я еще понимаю если ввести для векторов функции dot и cross ибо умножение векторов бывает скалярное и векторное.
Причем dot и cross можно и без всяких префиксов если поместить их в один неймспейс с вектором тогда будет работать ADL
namespace vectors
{
    template<class T>
    struct vector3
    {
        vector3()
            :x()
            ,y()
            ,z()
        {}
        vector3(T _x, T _y, T _z)
            :x(_x)
            ,y(_y)
            ,z(_z)
        {}
        T x;
        T y;
        T z;
        vector3<T>& operator+=(vector3<T> const& that)
        {
            x+=that.x;
            y+=that.y;
            z+=that.z;
            return *this;
        }
    };
    template<class T>
    vector3<T> operator+(vector3<T> const& l, vector3<T> const& r)
    {
        return vector3<T>(l)+=r;
    }
    template<class T>
    T dot(vector3<T> const& l, vector3<T> const& r)
    {
        return l.x*r.x+l.y*r.y+l.z*r.z;
    }
    template<class T>
    vector3<T> cross(vector3<T> const& l, vector3<T> const& r)
    {
        return vector3<T>
            (l.y*r.z-l.z*r.y
            ,l.z*r.x-l.x*r.z
            ,l.x*r.y-l.y*r.x
            );
    }
}
int main()
{
    vectors::vector3<float> v1;
    vectors::vector3<float> v2;
    vectors::vector3<float> v3;
    v1=v2+v3;
    float f=dot(v1+v2, v2+cross(v3, v1));
}

Argument Depended Lookup рулез
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 12:15
Оценка:
Здравствуйте, INTP_mihoshi, Вы писали:

WH>>

WH>>Для типа array_t перегружены все арифметические операторы так что запись вида arr1*arr2 трактуется как поэлементное умножение массивов. А запись вида const*arr трактуется как поэлементное умножение массива на константу.


INT>Кстати, такие вещи вроде-бы принято через итераторы делать... Тогда ты не будешь привязан к представлению контейнера.

В данном случае весь смысл этой библиотеки в том чтобы не писать циклы ручками. И уж темболие для случая
int size=10000;
array_t<float> a(size);
array_t<float> b(size);
array_t<float> c(size);
array_t<float> d(size);
array_t<float> e(size);
array_t<float> f(size);
float x;
float y;
float z;
//тут инициализация
f*=(a/x+5)*b-(y*c-d/5)/e-z;//Этот велосипед нужен только ради такой записи
//что эквивалентно (без перегрузки операторов)
for(int i=0;i<size;++i)
    f.at(i)*=(a.at(i)/x+5)*b.at(i)-(y*c.at(i)-d.at(i)/5)/e.at(i)-z;

не связоватся с итераторами ибо код будет не просто страшным, а очень страшным.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[10]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 12:15
Оценка: 1 (1)
Здравствуйте, Serginio1, Вы писали:

S> Перегрузка не всегда понятна и очевидна. Кроме того при поиске кода в исходниках по функции легче найти ее исходный код.

В кривой либе может быть. Но то что некоторые орлы криво используют перегрузку не повод от нее отказыватся.
S> и чем Equals хуже == ????? И другие эквивалентные операторы. Дольше писать согласен (да и то при подсказке через точку нет проблем),
Тем что писать дольше. И выразительность меньше.
S> хуже читать — нет. Так думай перегружен метод для == или это ReferenceEquals.
В С++ таких проблем нет. Ибо всегда сравниваются объекты. Указатели тоже объекты.
S> Я лично предпочитаю единые по написанию функции четко определяющие вид операции вместо перегруженных операций.
см соседнй пост
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[11]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.05.04 12:33
Оценка:
Здравствуйте, WolfHound, Вы писали:

W
WH>f*=(a/x+5)*b-(y*c-d/5)/e-z;
WH>или
WH>MultiplyAssignItemByItem(f, SubtractItemByScalar(SubtractItemByItem(MultiplyItemByItem(AddItemByScalar(DivideItemByScalar(a, x), 5), b)), DivideItemByItem(SubstractItemByItem(MSI(y, c), DivideItemByScalar(d, 5)), e), z));
Ну зачем так
f= a.div(x).add(5).mull(b).sub( y.mull(c).sub(d.div(5))).div(e).sub(z)
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[11]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.05.04 12:40
Оценка:
Здравствуйте, WolfHound, Вы писали:

K_O>>Я говорю не про имена переменных, а про то, что не понятно, где просто переменная, а где массив.

WH>А я тебе говорю что из имен переменных ясно где что.

K_O>>Я вообще-то не очень люблю доки читать. Если надо в чем-то разобраться — смотрю в исходники. Доки часто просто отстают от реализации или там не все нюансы отражены.

WH>Плохой пожход. Если доки есть то их надо прочитать. Даже если они и отстали то всеравно будет легче разобратся с исходниками.
Качественно оформленный исходный код — лучшая документация. И на 100% отражает суть реализации.

K_O>>Но дело не в этом. Для того, чтобы понять как работает приведенный тобой шаблон я должен смотреть либо в доки, либо в исходники. А вот если бы вместо "*" использовался метод, скажем, MultiplyItemByItem, то никуда не надо было лезть и в чем-то разбираться. Такой код читался бы проще.

WH>
WH>
WH>f*=(a/x+5)*b-(y*c-d/5)/e-z;
WH>или
WH>MultiplyAssignItemByItem(f, SubtractItemByScalar(SubtractItemByItem(MultiplyItemByItem(AddItemByScalar(DivideItemByScalar(a, x), 5), b)), DivideItemByItem(SubstractItemByItem(MSI(y, c), DivideItemByScalar(d, 5)), e), z));
WH>

WH>Это не то что прочитать... это написать трудно
WH>Человек просто запутается в такой записи.
Здесь так: если отстаивать свою точку зрения путем доведения до идиотизма доводов оппонента, то лучше сразу закончить дискуссию.
Я надеюсь, что разговариваю с человеком, умеющим аргументированно спорить.

А возражение по теме таково:
for (int i = 0; i < array_size; i++)
  f[i] *= (a[i] / x + 5) * b[i] - (y * c[i] - d[i] / 5) / e[i] - z;


WH>>>А взят тотже boost::spirit когда надо быстро написать не сложный парсер то эта штука очень удобна. Но он небыл бы возможен без перегрузки операторов.

K_O>>Не видел, не знаю.
WH>А ты скачай boost да посмотри.
Мне уже и STL'ного отстоя хватает, это время пригодится для более важных целей.

WH>Например так задается грамматика калькулятора

WH>
WH>   Skipped.
WH>

WH>EBNF грамматика прямо на С++...
Ты им часто пользуешься?

WH>Да по исходникам ты в ней не разберешься...

Это вообще приговор библиотеке и выговор разработчикам. Если я по исходникам не разберусь, то и сами разработчики этой либы через некоторое время отсутствия практики работы с boost перестанут понимать в чем дело.

K_O>>Я говорю о том, что разные по реализации алгоритмы должны и в тексте программы выглядеть по-разному, т.е. иметь разные имена.

WH>Зачем?
WH>Какая разница что складывать два вектора или два числа? И то и другое сложение.
Общего у них только название. Сложение чисел и сложение векторов — принципиально разные операции даже в математике.

WH>Дык зачем для векторов вводить ужасную функцию типа AddVectorVector?

Математический термин "сложение векторов" по-английски звучит так: composition of vectors.
Стало быть не AddVectorVector, а Compose.
WH>Я еще понимаю если ввести для векторов функции dot и cross ибо умножение векторов бывает скалярное и векторное.
И не dot и cross, а SclarProduct и CrossProduct.

Здесь хочу сказать еще вот что: важность правильного именования идентификаторов трудно переоценить. Причем очень важно добиваться того, чтобы имя метода не примерно отражало реализацию, а в точности соответствовало ей. Порой добиться этого непросто. Но зато такая тщательность приводит к тому, что код становится читабельным и понятным.
Re[11]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Kh_Oleg  
Дата: 21.05.04 12:46
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>>>

WH>>>Для типа array_t перегружены все арифметические операторы так что запись вида arr1*arr2 трактуется как поэлементное умножение массивов. А запись вида const*arr трактуется как поэлементное умножение массива на константу.


INT>>Кстати, такие вещи вроде-бы принято через итераторы делать... Тогда ты не будешь привязан к представлению контейнера.


WH>f*=(a/x+5)*b-(y*c-d/5)/e-z;//Этот велосипед нужен только ради такой записи

WH>//что эквивалентно (без перегрузки операторов)
WH>for(int i=0;i<size;++i)
WH> f.at(i)*=(a.at(i)/x+5)*b.at(i)-(y*c.at(i)-d.at(i)/5)/e.at(i)-z;
WH>[/ccode]
WH> В данном случае весь смысл этой библиотеки в том чтобы не писать циклы ручками.

Так все эти перегрузки операторов нужны только для того, чтобы сэкономить ОДНУ (!!!!) строчку?

Я скажу еще вот что: без перегрузки мы имеем один цикл, а с перегрузкой — столько циклов, сколько использовано перегруженных операторов. Из-за сомнительной красоты кода мы еще жертвуем и производительностью.
Re[11]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.05.04 12:50
Оценка: -1
Здравствуйте, WolfHound, Вы писали:


WH> В С++ таких проблем нет. Ибо всегда сравниваются объекты. Указатели тоже объекты.

Согласно принципам ООП
f*=(a/x+5)*b-(y*c-d/5)/e-z;

Ну зачем так
f= f.mull( a.div(x).add(5).mull(b).sub( y.mull(c).sub(d.div(5)) ).div(e).sub(z) )

Чуть длинее, но понимание это уже дело привычки.
Кроме того, теже mull,add,sub могут быть сами перегружены, а если им давать нормальные имена то вполне.
Небольшой пример из C#. Свойства индексаторы могут быть только this (Items). И различаться только параметрами.
Но реально это могут быть различные свойства. Зачем там нужна перегрузка??? Кроме того разные свойства но с одинаковыми параметрами в этом случае не прокатывают.
Я во многом с тобой согласен, но к перегрузке операторов как и функций нужно подходить очень акуратно и выверенно.
Equals легко заменяет ==, и по читабельности ну ни коим образом не уступает.
А с точки зрения шаблонов будет проходить и тот и другой код.
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Re[11]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: SWW Россия  
Дата: 21.05.04 12:51
Оценка:
S>> и чем Equals хуже == ????? И другие эквивалентные операторы.

Тем что текст становится меньше похож на математическую формулу. (Только пожалуйста, не надо в сотый раз про паскалевское сравнение). Кстати, MOD вместо % хуже по той же причине.
Re[12]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 13:22
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:

K_O>Так все эти перегрузки операторов нужны только для того, чтобы сэкономить ОДНУ (!!!!) строчку?

Ну одну а столько сколько выражений есть в программе.
K_O>Я скажу еще вот что: без перегрузки мы имеем один цикл, а с перегрузкой — столько циклов, сколько использовано перегруженных операторов. Из-за сомнительной красоты кода мы еще жертвуем и производительностью.
Ты недооцениваешь С++. Цикл будет один.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 13:22
Оценка:
Здравствуйте, Kh_Oleg, Вы писали:

WH>>Плохой пожход. Если доки есть то их надо прочитать. Даже если они и отстали то всеравно будет легче разобратся с исходниками.

K_O>Качественно оформленный исходный код — лучшая документация. И на 100% отражает суть реализации.
А кто спорит? Просто если есть дока то из нее гораздо проще понять общию идеологию системы. И тогда разобратся с исходниками будет на порядок проще. Как бы они небыли хорошо оформлунны.
K_O>>>Но дело не в этом. Для того, чтобы понять как работает приведенный тобой шаблон я должен смотреть либо в доки, либо в исходники. А вот если бы вместо "*" использовался метод, скажем, MultiplyItemByItem, то никуда не надо было лезть и в чем-то разбираться. Такой код читался бы проще.
K_O>Здесь так: если отстаивать свою точку зрения путем доведения до идиотизма доводов оппонента, то лучше сразу закончить дискуссию.
Это была лишь демонстрация предложеного тобой метода.

K_O>А возражение по теме таково:

K_O>
K_O>for (int i = 0; i < array_size; i++)
K_O>  f[i] *= (a[i] / x + 5) * b[i] - (y * c[i] - d[i] / 5) / e[i] - z;
K_O>

А теперь добавь сюда дебужную проверку того что размер всех массивов в выражении одинаковый.

WH>>А ты скачай boost да посмотри.

K_O>Мне уже и STL'ного отстоя хватает, это время пригодится для более важных целей.
А слабо аргументировано обосновать отстойность STL?
Я надеюсь, что разговариваю с человеком, умеющим аргументированно спорить.(С) Ты.

WH>>EBNF грамматика прямо на С++...

K_O>Ты им часто пользуешься?
Не очень. Но иногда бывает.

WH>>Да по исходникам ты в ней не разберешься...

K_O>Это вообще приговор библиотеке и выговор разработчикам. Если я по исходникам не разберусь, то и сами разработчики этой либы через некоторое время отсутствия практики работы с boost перестанут понимать в чем дело.
Для того чтобы разобратся в полутра метрах исходников даже учитывая что они очень качественно написаны, да еще и не прочитав предварительно доки Не реально.
А прочитав доку к спириту исходники изучать уже не обязательно.
А написана она очень качественно.

K_O>Общего у них только название. Сложение чисел и сложение векторов — принципиально разные операции даже в математике.

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

K_O>И не dot и cross, а SclarProduct и CrossProduct.

А в D3DX они называются D3DXVec3Dot и D3DXVec3Cross соответственно.
Я взял терминологию от туда.

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

Говоришь то ты правильно но твом методы добится этого мягко говоря сомнительны.
Не плодите сущьности без необходимости (С) Не помню.
Зачем вводить сущьность ComposeVectorVector когда есть всем понятная сущьность + ? Не понимаю.
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[12]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: WolfHound  
Дата: 21.05.04 13:22
Оценка: :)
Здравствуйте, Serginio1, Вы писали:

S> f= a.div(x).add(5).mull(b).sub( y.mull(c).sub(d.div(5))).div(e).sub(z)

А y это float...
... << RSDN@Home 1.1.3 beta 1 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[8]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: folk Россия  
Дата: 21.05.04 13:23
Оценка: +1
Здравствуйте, Kh_Oleg, Вы писали:

[]

K_O>Оператор сложения для строк, означающий конкатенацию — это, пожалуй, единственное применение перегрузки операторов, где оно действительно необходимо. А все потому, что в ЯП строка должна быть базовым типом! Таким как char, int, double. Так и string.

K_O>Вот для базовых (примитивных) типов операторы должны быть определены. Но не для составных типов, определяемых программистом!

Я практически не вижу разницы между перегрузкой операторов и перегрузкой функций. Функция "divide" не имеет никаких преимуществ перед оператором "/" для пользовательского типа. Как раз наоборот.

Перегрузка функций (операторов) может быть проявлением статическго полиморфизма. Такой полиморфизм подразумевает поддержку операций над объектами различного типа с использованием общего синтаксиса (соответствующие функции/операторы имеют одинаковые имена, кол-во аргументов).

Представим класс-тип BigNumber, для которого перегружены мат. операторы "+", "/", etc, вместо того чтобы определять функции "add", "divide", etc. Таким образом BigNumber поддерживает статический интерфейс встроенных числовых типов. Что это дает:

1. Пользователь может использовать привычный интуитивно понятный синтаксис для выражений с объектами BigNumber.

2. Достаточно совсем небольших изменений, чтобы код, использующий BigNumber стал работать с int или с VeryBigNumber. И не надо лазить по всему коду и править "divide" на "/".

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

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

[]

WH>>ЗЗЫ А тех кто перегружает операторы не интуетивным образом надо сжигать на костре и предавать анафиме...

K_O> Но почему язык позволяет таким индивидуумам так хулиганить?

Язык позволяет хулиганить с функциями ничуть не меншье.

ЗЫ И мне непонятно, чего ты стал придираться к неинициализированным переменным у WH. Если бы он использовал функции вместо операторов, то эти переменные инициализировались бы сами собой?
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re[13]: Читать всем!!!! ОБЯЗАТЕЛЬНО!!!!
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.05.04 13:50
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Serginio1, Вы писали:


S>> f= a.div(x).add(5).mull(b).sub( y.mull(c).sub(d.div(5))).div(e).sub(z)

WH>А y это float...
А вот еще и перегрузка методов
Тады
f= a.div(x).add(5).mull(b).sub( c.mull(y).sub(d.div(5))).div(e).sub(z)
Но лучше тогда
f= a.VectorDiv(x).IntAdd(5).VectorMull(b).VectorSub( c.FloatMull(y).VectorSub(d.IntDiv(5))).VectorDiv(e).VectorSub(z)
... << RSDN@Home 1.1.0 stable >>
и солнце б утром не вставало, когда бы не было меня
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.