LINUX.ORG.RU

Основные варианты использования операций, определяемых пользователем

 ,


0

1

Здесь собираю случаи, в т.ч. предложенные в ходе дискуссии.

1. Алгебра чисел, алгебра бухгалтерских чисел, матрицы. Здесь мы, по сути, определяем арифметику.

2. Список прибавить элемент, список нарастить элементов.

3. В поток вывести а, б, в (С++ -шный классический оператор <<)

4. А влечёт Б (логика и доказательства)

5. А имеет тип Б.

6. А является подтипом Б.

7. Логические операции (а или б)

8. Битовый сдвиг и присваивание <<=

9. Осуществить действие в некоторых точках списка, а не во всех:

f = map (/ 2) $ (g $ k x $ y + d)

10. Индексация массивов пользовательскими типами ключа.

11. Операции со строками и последовательностями (поиск, замена, удаление, вставка и т.п.)

12. Величины с размерностью, например 500 миллисекунд.

Какие ещё есть полезные варианты использования операций? Меня особенно интересуют те случаи, где именно синтаксис операций даёт особое удобство. Ведь всё это можно выразить как функции, например: +(2,2), Нарастить(Список,Элемент), Влечёт(А,Б), Является(А,Б) и т.д.

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

★★★★★

Последнее исправление: den73 (всего исправлений: 4)

Вот, например, в Scala огромная свобода в плане определения операций (мне кажется, перебор со свободой). Идея связать приоритет с видимой записью операции хороша, но всё равно, неясно, зачем столько операций. Может быть, не перебор и всё ок, а просто я что-то недопонял?

den73 ★★★★★
() автор топика

Кроме своей арихметики и «умных» указателей/массивов и особого статуса оператора = в плюсах оно требует зубрёжки семантики для конкретного случая. Поэтому обычно нафиг не надо нигде и никогда.

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

var x = {} + [];

dzidzitop ★★
()
Последнее исправление: dzidzitop (всего исправлений: 1)

Индексация массивов с пользовательским типом ключа. Ассоциативных или bitset, например

Операторы для работы со строками и последовательностями

3. В поток вывести а, б, в (С++ -шный классический оператор <<)

Сейчас же это считается фичей сомнительной ценности?

Ведь всё это можно выразить как функции, например: +(2,2)

Ну так-то да

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

Если брать именно Haskell, то операции как раз удобны наличием приоритетов и возможностью (в Haskell) делать свёртку по второму аргументу.

f = map (/ 2) $ (g $ k x $ y + d)

Без операций было бы

f = map (flip div 2) (g (k x) (y + d))

Но в Haskell все функции от одного аргумента, поэтому специфический случай. А в Lisp, где (<< out x y z) читается гораздо лучше, чем out << x << y << z, от операций толку было бы мало. Вопрос привычки.

Единственная объективная польза — экономия на скобках.

monk ★★★★★
()

Основные варианты использования операций, определяемых пользователем

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

loz ★★★★★
()
Ответ на: комментарий от dzidzitop
в плюсах оно требует зубрёжки семантики для конкретного случая.

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

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

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

Операторы для работы со строками и последовательностями

Что, кроме конкатенации?

den73 ★★★★★
() автор топика
Ответ на: комментарий от loz
пользователь все равно сделает то что ему надо, только через костыли и хаки

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

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

в остальном это не так существенно, можно всё записать с помощью функции и получить нужный результат

И в арифметике и логике можно сделать то же самое. Вопрос в удобстве и простоте использования.

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

Операторы для работы со строками и последовательностями

Что, кроме конкатенации?

Сравнение, получение символа по индексу. Ну, это минимум для языка общего назначения. Видел строковые операторы в Перле, например? Не сказать что очень наглядно для новичков, но для тех кто много обрабатывает тексты удобно

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

Поиск, замена, транслитерация, заключение в кавычки. А было ли бы сильно менее удобно, если бы это были просто функции? Вот цитатка:

Как видите, присваиваемая (под)строка не обязана совпадать по длине с заменяемой подстрокой. Длина полученной строки изменяется в соответствии с длиной замены. А если и это не произвело на вас впечатление, оператор привязки (=~) позволяет ограничить операцию частью строки. В следующем примере подстрока fred заменяется подстрокой barney в пределах 20 последних символов:

substr($string, -20) =~ s/fred/barney/g;
По правде говоря, нам никогда не приходилось использовать эти возможности в своем коде. Скорее всего, вам они тоже не понадобятся. Но всегда приятно сознавать, что Perl может сделать больше, чем вам когда-либо понадобится, не так ли?

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

Когда как. CartesianBuilder через |@| мне кажется естественным, но >>= как-то не заходит, например. Очень субъективно, поэтому свобода - это нормально. Никто не заставляет.

Хотя если делать это последовательно и иметь команду сверхлюдей, можно и так делать: https://github.com/quasar-analytics/quasar/blob/master/foundation/src/main/sc...

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

С юникодом всё не так просто. Прежде всего, выбор шрифтов достаточно узок. Например, вообще говоря, трудно понять, где тут буквы, а где знак конъюнкции: V˅v . Особенно плохо обстоят дела с моноширинными шрифтами. Тут людям повезло, что им хватило тех индексов, к-рые есть в юникоде, но изображения типа `δ²` и ≟ вызывают у меня большие сомнения. Например, то, что над знаком равенства находится знак вопроса, я разглядел только тогда, когда скопировал этот значёк в ЛОР. Далее, я сделал раскладку с юникодом и выяснилось, что под офтопиком tk не умеет вводить многие юникодные значки с клавиатуры. И т.п.

Т.е. в какой-то момент кто-то внезапно обнаружит, что код нечитаем в его любимом редакторе/среде разработки и будет очень сильно материть авторов такого кода.

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

Операции над датами являются хорошим примером? Дата + число = дата, дата - дата = число, и др. Пасха, фазы луны, беременность и др. И всё это по выбору в григорианском, юлианском календаре, календаре Великой Французской революции и др. Или это частный случай твоего п.1 с алгебрами?

В некоторых предметных областях операции над датами могут как раз повысить понятность кода :)

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

А, хотя пардон, проглядел «определяемых пользователем». Тут операции-то как раз стандартные, нестандартны только операнды.

Ну тогда операции над множествами. Объединение, пересечение...

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

Операции над датами являются хорошим примером? Дата + число = дата

Это как раз плохой пример.

Приходится лезть в документацию и смотреть, что подразумевает здесь число. addSeconds(d, n), addDays(d, n) или даже addMonths или addYears (реже, но встречается).

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

Как я уже сказал, если собрать команду хороших программистов, а не теоретиков «Если-то, ну тут повезло, шрифтов не хватит».

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

Нет, если типизированные durations, то нормально:

scala> import scala.concurrent.duration._
import scala.concurrent.duration._

scala> 1.second + 500.millis
res0: scala.concurrent.duration.FiniteDuration = 1500 milliseconds
cdshines ★★★★★
()
Ответ на: комментарий от cdshines

Спасибо за наезд, видимо, ты имеешь в виду, что ты хороший программист, а я теоретик безполезный. «Хорошие программисты» в своё время придумали Perl, и где теперь Perl?

500.millis - а вот это в копилку: число с размерностью. Но идея применить для этого точку выглядит несколько... ммм... ну, как есть продукты из мусорного бака. Как бы Скалу не постигла судьба Перла.

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

Я, к сожалению, не вхожу в эту команду, но да, имею в виду, что ты слишком много теоретизируешь.

Ну можешь без точки писать. Например, конструктор, вроде Duration(500, TimeUnit.MILLIS). Но что не так-то с точкой? Ну и да, если писать просто (500 millis), тоже работает.

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

Узнай, сколько проходит времени от начала разработки до первого релиза в современных языках. У меня ещё и 2 лет не прошло, при том, что я работаю почти в одно лицо.

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

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

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

Точка нагружена слишком многими смыслами. Для начала, пусть у меня есть переменная М и я хочу её расценить как миллисекунды. Как это написать на Скале?

Второй вопрос: я хочу добавить миллисекунды, но в переменной М у меня на самом деле секунды. Как организовать преобразование?

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

Вы бы хоть нормальный архив с яром сделали. Решил посмотреть что там у вас есть, взял архив со страницы загрузки (как в README написано), а там половина файлов на русском в кодировке CP866 (это у вас такая рабочая кодировка?). У меня оно ни на десктопе с windows 10, ни на ноуте с линуксом не работает в таком виде. Плюс, в инструкции написано мол, запустите батник и всё, но ведь в архиве нет директории lp со всем содержимым, нет sbcl. Я что-то не так сделал? Ходил по ссылкам с главной страницы вроде.

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

Вот вам из repl пример:

scala> val m = 12                       
m: Int = 12

scala> val mil = m.millis
mil: scala.concurrent.duration.FiniteDuration = 12 milliseconds

scala> val sec = m.seconds
sec: scala.concurrent.duration.FiniteDuration = 12 seconds

scala> val sum = m.millis + m.seconds
sum: scala.concurrent.duration.FiniteDuration = 12012 milliseconds

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

было ли бы сильно менее удобно, если бы это были просто функции?

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

Deleted
()
Ответ на: комментарий от Weres

Ну я этого не хотел говорить, но на прямой вопрос - прямой ответ. Разработка Яра временно переведена в закрытый режим. Хотя там и смотреть нечего - идёт затянувшийся процесс переделки версии 0.000 в версию 0.4, т.е. работающих примеров сейчас нет. Будет что показать - открою обратно. Хотя могу тебе отправить какой-нибудь свежий архив - для этого пиши на почту.

Сильно менее удобно работать со строками в чистом С

В лиспе и tcl/tk то же самое достигается за счёт параметров-ключей. Это гораздо проще и понятнее, чем запись на Перле, к-рую я процитировал, букв не больше, удобства не меньше, результат не хуже. Так что тут не совсем про то ты сравниваешь.

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

Не ты написал, а Weres. Ты писал операции с литералами. Не из чего не следует, что такие же операции определены для переменных. Ну ладно. Допустим, в Scala есть размерные величины. Как насчёт единиц изменения теплоёмкости (кДж/(кг*К))? Есть ли возможность защититься от сложения килоджоулей и килокалорий или автоматически привести одни к другим? Ведь именно этим и хороши величины с размерностью. Можно очень долго жить с ошибками размерностей в расчётных программах и будут эти программы в корне неправильными.

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

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

Но в целом спасибо! Похоже, надо было более внимательно присмотреться к Scala в начале своего проекта.

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

Ладно, я что-то слишком резко разошелся. Суть в том, что ты не должен засорять стандарт языка (я отношусь к твоей поделке скептически, но это не суть) какими-то посторонними вещами. Определи какой-то базис, чтобы на нем можно было сделать все хотелки - и все. Например, ты хочешь размерные величины. Первое, что приходит в голову (помимо какой-то ерунды типа «называть функции по семантике») - прятать размерности в типы. Этого уже достаточно, потому что вся логика уходит из языка в библиотеку (конверсии и все остальное прилагается). Потом ты захочешь, например, чтобы это смотрелось ествественнее, чем Quantity(amount, unit), например, amount.unit, тогда придешь к мысли о том, что неплохо бы предоставить возможность расширять определения типов (если ты калека, сделаешь манки-патчинг, если нет - нормальные тайпклассы, например, или что-то такое).

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

Базис под все хотелки сделать нельзя («может ли Бог сделать камень, который он сам не в силах поднять», «common lisp is a hippie language which disallows disallowing» и т.п.). Но можно попробовать сделать базис под конкретный конечный набор хотелок. Например, «спрятать в типы» можно по-разному. Если для таких размерных вычислений потребуется boxing чисел, то ряд практически важных областей применения сразу отпдаёт из-за потери производительности.

В общем, похоже, что тема исчерпана, всем спасибо за участие!

den73 ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.