Re[14]: Использование tuple
От: Andrei N.Sobchuck Украина www.smalltalk.ru
Дата: 15.10.09 10:21
Оценка:
Здравствуйте, nikov, Вы писали:

N>Да, есть такая проблема. Я даже как-то открывал ticket по этому поводу. Кажется, в 2.8beta появились более совершенные механизмы (через continuations).


Хм. Так в jvm нет continuations. Или оно как то хитро код преобразует? Но тогда /возможно/ потеряется интероперабельность с java.
Я ненавижу Hibernate
Автор: Andrei N.Sobchuck
Дата: 08.01.08
!
Re[15]: Использование tuple
От: nikov США http://www.linkedin.com/in/nikov
Дата: 15.10.09 10:28
Оценка:
Здравствуйте, Andrei N.Sobchuck, Вы писали:

ANS>Хм. Так в jvm нет continuations. Или оно как то хитро код преобразует?


Да, хитро преобразует. Но я пока не вникал во внутренюю механику.
Причем эти continuations сериализуемые, что позволяет переносить вычисления с одной машины на другую.
Re[11]: Использование tuple
От: Sinclair Россия https://github.com/evilguest/
Дата: 15.10.09 11:59
Оценка:
Здравствуйте, VladD2, Вы писали:
VD>Ты пишешь код один раз. А читаешь много, много раз. Так что при выборе синтаксиса нужно исходить в первую очередь из соображений простоты чтения и привычности для окружающих (принцип — не удивляй).
Ну, при чтении совершенно неважно, объявлены ли имена полей у результата функции. Кроме случая явного именования типа
def (a = x, b = y) = GetSomePoint(c, d);


VD>Ну, дык присвоил локальной переменной, а от нее через точку.

Ну, это как раз boilerplate.
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[11]: Использование tuple
От: _FRED_ Черногория
Дата: 15.10.09 12:15
Оценка:
Здравствуйте, Undying, Вы писали:

U>Чем:

U>interface ITest
U>{
U>  Tuple<string FirstName, string LastName> Name { get; }
U>}

U>хуже, чем
U>class Name
U>{
U>  string FirstName;
U>  string LastName;
U>}

U>inteface ITest
U>{
U>  Name Name { get; }
U>}

U>Первый случай как бы не более понятен…

Лучше тем, что, во-первых, позволяет добавить документацию\метаинформацию(аттрибуты) и т.д. Во-вторых, позволяет выбрать, значимый или ссылочный тип отдаётся наружу. В-третьих, позволяет расширять (без _изменения_ самого типа! только _расширением_ его) функциональность возвращаемого значения: добавлять события, реализацию интерфейсов и т.п.

ИМХО, в бизнес-сущностях несомненно следует не лениться и не экономить на спичках и выписать (читай: явно обозначить) используемый тип. Делать же это (специальный тип) для "приватных" расчётов — там, где не требуется поддержка совместимости, документация, соблюдение протокола — таплы самое оно. всё, что им не хватает в шарпе: синтаксического сахара — если не ударяться в маразм (с использованием восмиарных таплов) всё будет прекрасно.

Именованные записи способны ещё более улучшить кейс использования таплов _в приватных частях_, но не надо стремиться заместить ими бизнес-сущности: сидеть на двух табуретах будет очень не комфортно.

U>(как, к примеру, Func<T, T, int> на практике оказывается понятнее Comparison<T>) и при этом кода требует в разы меньше.


Не согласен: ИМХО наоборот, использование Comparison, Predicate и прочего подобного удобнее и _очевиднее_ в использовании.
Help will always be given at Hogwarts to those who ask for it.
Re[12]: Использование tuple
От: _FRED_ Черногория
Дата: 15.10.09 12:45
Оценка:
Здравствуйте, _FRED_, Вы писали:

U>>Чем:


U>>хуже, чем

U>>Первый случай как бы не более понятен…

_FR>Лучше тем, что, во-первых, …


Имелось в виду, что второй способ с явным объявлением типа лучше (по моему мнению).
Help will always be given at Hogwarts to those who ask for it.
Re[11]: Использование tuple
От: FR  
Дата: 15.10.09 13:41
Оценка:
Здравствуйте, Undying, Вы писали:

U>Т.е. ни для чего кроме базовых стандартов ФВП (вроде Filter и Partition) туплы использовать нельзя? А зачем они тогда вообще нужны?


Странный вывод

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

Кроме того кортежи весьма интенсивно используются в вариантных типах данных, например:

type 'a btree = Empty | Node of 'a * 'a btree * 'a btree;;
Re[12]: Использование tuple
От: vdimas Россия  
Дата: 15.10.09 20:50
Оценка: 2 (1) +1
Здравствуйте, IT, Вы писали:


IT>В параметрах лябды тоже тушим свет? Да и вообще при вызове любого метода при передаче параметров легко запутаться. Ага.


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

Например (как бы это могло в C# выглядеть):
class SomeMap<TKey, TValue> {
    public {TKey key, TValue value}[] ToArray() {...}
}

foreach(var pair in someMap.ToArray()) 
    Console.WriteLine("{0}:{1}", pair.key, pair.value);


Пусть имена полей тупла "key" и "value" существуют только как метаинформация и используются компилятором как синонимы. Без расширения системы метаинформации .Net это можно было сделать на аттрибутах, чтобы реально компилировалось в нечто вроде:

class SomeMap<TKey, TValue> {
  [return: TupleField(0, "key"), return:TupleField(1, "value")]
    public Tuple<TKey, TValue>[] ToArray() {...}
}

foreach(Tuple<TKey, TValue> pair in someMap.ToArray()) 
    Console.WriteLine("{0}:{1}", pair._0, pair._1);
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[9]: Использование tuple
От: vdimas Россия  
Дата: 15.10.09 21:09
Оценка:
Здравствуйте, Mystic, Вы писали:


M>Это зависит от предметной области. В MATLAB таких функций много.


Насколько я помню, в матлабе кортежи используются только для возвращаемых значений ф-ий и подачи их как параметров. И самое главное: поля этого кортежа имеют вполне осмысленные имена, а не безликие типы (ибо тип данных у матлаба всего один — матрица).
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[8]: Использование tuple
От: vdimas Россия  
Дата: 15.10.09 21:09
Оценка:
Здравствуйте, Sinclair, Вы писали:

S>Я бы тут постарался развернуть вызов задом наперёд. Так, чтобы code completion мне помогал. Что-то типа

S>
S>GetPersonInfo(123) => (name, _, age);
S>


Да, не первый раз это высказывается и сновной аргумент "против" — сам вызов с длинным перечнем параметров отодвинет далеко по тексту результат, а внимание обычно надо фокусировать именно на результате. Хотя, для коротких вызовов, типа приведенного — очень даже ничего.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[12]: Использование tuple
От: Undying Россия  
Дата: 16.10.09 06:18
Оценка: 1 (1)
Здравствуйте, FR, Вы писали:

U>>Т.е. ни для чего кроме базовых стандартов ФВП (вроде Filter и Partition) туплы использовать нельзя? А зачем они тогда вообще нужны?


FR>Странный вывод


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


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

maxkar же говорил о том, что даже при правильно поставленной задаче функции и удачно подобранном названии контекст ясен далеко не всегда и допускает неоднозначность возвращаемого значения. Именованные возвращаемые значения позволяет эту неоднозначность снизить очень значительно, неименнованные туплы неоднозначность сохраняют.
Re[13]: Использование tuple
От: FR  
Дата: 16.10.09 15:20
Оценка: +2
Здравствуйте, Undying, Вы писали:


U>И к чему тогда было твое замечание про Filter и Partition? У этих функций не контекст ясен, а знание механизма их работы вбито в головы функциональщиков. Но на практике даже при работе со своим кодом механизм работы большинства функций забывается очень быстро, в случае же с чужим кодом механизм работы зачастую просто неизвестен.


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

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


Да для языка без паттерн матчинга он совершенно прав. Для языков с паттерн матчингом, необходимости в именах я не вижу.
Re[13]: Использование tuple
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.10.09 19:23
Оценка: :)
Здравствуйте, Undying, Вы писали:

U>И к чему тогда было твое замечание про Filter и Partition? У этих функций не контекст ясен, а знание механизма их работы вбито в головы функциональщиков. Но на практике даже при работе со своим кодом механизм работы большинства функций забывается очень быстро, в случае же с чужим кодом механизм работы зачастую просто неизвестен.



Скажи, ты хоть раз в жизни забыл, что i в for (int i = 0; ...) — это индексер цикла?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Использование tuple
От: maxkar  
Дата: 18.10.09 17:54
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Это я к тому говорю, что "могут" не показатель. Важно насолько часто они случаются и сколь ощутимые последствия от этого.


Ну вот в двух первых сообщениях этой подветки Рысцов Денис и IDL поделились своим опытом. Каким-либо основаниям считать их опыт неподходящим указано не было. Причем Денис указал даже срок — 1 год, что характеризует класс проекта. Затем вы обвинили их в "не внятности ваших функций". Только вот дальше оказалось, что пример в том обвинении тоже "не очень". Сама по себе "в вакууме" приведенная функция оказалась тоже не слишком внятной. Пришлось применять аргументы вроде "это везде в ФП" и подобные, чтобы объяснить, почему же результат именно такой, как есть. Только вот аргумент этот не слишком универсальный. Не под все проекты подходит. Не всегда можно выделить четкую и неизменную предметную область, в которой ничего не меняется. Например, курсовая вполне может служить примером проекта с не слишком четкими требованиями. Вполне вероятно, какие-то требования менялись в процессе работы (в зависимости от полученных результатов, требований научного руководителя и т.п.). Там как раз можно наблюдать много эффектов "промышленного программирования" вроде необходимости много читать старый код и что-то менять. Их вывод был — tuples (неименнованные) в публичных интерфейсах на их проектах доставляют больше неудобств, чем дают преимуществ.

VD>Скажем вместо f(a, b) можно же писать f(arg1 = a, arg2 = b). Но многие будут даже против такой записи (хотя она и правда более информативна). Так что тут компромис. Проблема может быть, но она редка и не страшна. Так что многие предпочитают более краткий синтаксис.


Можно писать и длинно (с именованием). Можно писать коротко. С тем, что компромиссы нужны, согласен. В идеале нужно иметь возможность писать и так и так. Например, в ocaml'евском биндинге для gtk (lablgtk называется) большинство примеров, которые я видел, было с передачей именованных параметров. И в тех конкретных случаях оно повышало читаемость (много функций с опциональными аргументами). Большинство же примеров по caml'у да и программ, которые я писал на нем, используют неименованные (позиционные) аргументы. Что еще интересно — там же, в стандартной библиотеке, присутствуют наборы функций с именованными параметрами, являющимися аналогами функций без именованных парамтеров. Например, ArrayLabels, ListLabels, StdLabels, MoreLabels. В тех же ArrayLabels есть и функции с "несколькими" параметрами, которые не имеют именованных аргументов. Но практически во всех этих функциях параметры разных типов. В остальных обычно именована пара интов (позиция и длина), хотя есть и blit, в котором поименована также и пара массивов. Я не думаю, что такие функции появились "просто так", видимо, в определенных случаях они были нужны (хотя я их не использовал).

VD>Ну, и? Каков вывод? Отказываемся от передачи более чем одного параметра в функцию?


Да нет, компромиссы нужны... Хотя есть языки, где фактически все функции и являются функциями от одного аргумента. Как раз таки эти функции обычно в ФП и встречаются (хотя называется это вроде бы curring).

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


VD>А тебе не кажется, что ты обсасываешь не стоящую выеденного яйца, гипотетическую проблему теолько для того, чтобы не принимать ничего нового?


Нет, не кажется. Мне кажется, что для ряда проектов (с определенными характеристиками) эта проблема является далеко не гипотетической и стоит разбираться, в каких же случаях на нее стоит обращать внимание и как ее решать. Я же нигде не говорил, что кортежи вообще нельзя использовать, а всего лишь утверждал, что они в ряде случаев могут доставлять проблемы. В дальнейшем потенциальные проблемы с описанием причинм могут быть сформулированы в виде coding guidelines для начинающих программистов, например. Ну вот напишут junior'ы код и получат те же проблемы, что уже получили другие люди до них. А так глядишь — и задумаются.

VD>Может быть поступить более конструктивно, и попробовать это новое, и уже потом составить свое мнение?


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

M>>Теперь перейдем к математике.


VD>Уже не хочется, спасибо. Подумай над моими словами. А то у нас получается спор о вкусе устриц с теми, кто их не ел.

Да подумал вроде. Только вот вы IDL'у (и Денису) то возражали слишком категорично. Однозначных аргументов за кокнретные варианты там не было. Были отсылки к "традициями ФП" и т.п., которые очень плохо приводятся к "предметной области", где ситуация может быть совсем другая. Так что мне кажется, что вы просто не видели тех проектов и команд, на которых их рекомендации могут быть оправданы.
Re[14]: Использование tuple
От: maxkar  
Дата: 18.10.09 19:17
Оценка: +1
Здравствуйте, FR, Вы писали:

FR>К тому что судя по всему люди не понимали что это базовые вещи.


Не про меня, случайно? Я прекрасно понимаю, что это базовые вещи. И partition использовался потому, что был приведен примером в том сообщении, с которым я не согласился. Не видел особого смысла менять пример. Если же восстановить контекст того сообщения, на которое я в начале отвечал, получается, что в нем была аргументация в духе "вы не умеете писать внятные функции, вот чем не очевидна partition". И в результате получили, что "partition является одной из базовых функций ФП, и поэтому ее значение нужно знать". С последним утверждением я никогда не спорил. Но если использовать только его для аргументации исходного сообщения, мы получим "вы не умеете писать внятные функции, потому что есть вот базовая функция partition, по которой совершенно очевидно, что она делает". Слово "базовая" — ключевое. Без него все обвинения в "незнаинии ФП" не работают. А с ним не работает пример. Точнее, он "условно" работает — только в определенном контексте. Доказательств же того, что оно работает всегда я не увидел (хотя вроде бы пытался получить), утверждение же Влада было сформулировано в категорической форме (для вообще всех функций, не только базовых).
FR>Очень многие чужие и свои функции делаются по образу и подобию базовых, это хороший стиль.
Это если есть базовые функции. А если их нет? Или программист их не знает (бывает такое у junior'ов)? Последнее, правда, решается не средствами языка.
Еще более интересная ситуация, когда "базовых" вещей не одна. Вот совершенно недавний пример. Разбор SWF-файла. Вот в нем есть структура "прямоугольник". И кроме выборов для tuple для их хранения есть не только (x1, y1, x2, y2) и (x1, y1, width, height). В этих двух случаях можно было бы взять то, что используется в gui (том же gtk, например). Проблема в том, что в "предметной области" (SWF-файл) там вообще (x1, x2, y1, y2). И из-за этого отдать предпочтение ни одному из вариантов нельзя. Если взять базовый формат SWF нужно следить за новыми программистами и правильностью понимания прямоугольника. Если же взять понимание GUI (с шириной или второй координатой), то прямоугольник может неправильно трактовать программист, знающий формат файла. Это все решается guidelines не в коде, ревью и т.п. Если же вернуться к примеру, сформулируем так: "разве не очевидно, что возвращает функция"

readRectangle :: IO (Int, Int, Int, Int)
readRectangle = ...


Кстати, в зависимости от того, что разрабатывается, вероятности разных трактовок могут изменяться .

Ну, если хочется, можно назвать readSWFRectangle, сильно это не поможет (ну читает оно прямоугольник, а вот формат хранения или формат возвращаемых результатов закодирован в SWF — не понятно). Можно назвать readSWFRectangleInSWFFormat, но это уже длинно. Я выбрал "именованные поля" в типе Rectangle. Это устраняет указанные неоднозначности.

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

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


FR>Да для языка без паттерн матчинга он совершенно прав. Для языков с паттерн матчингом, необходимости в именах я не вижу.


Ну вот чуть выше был SWF'овский прямоугольник. А так я верю, что вам имена и были не нужны. Возможно, на это влиял стиль программирования и т.п. (ничего плохого не имею в виду) Но вот в Haskell (с pattern match'ингом) были введены таки именованные поля для алгебраических типов. Объявление выглядит примерно так:
data SomeData =
         SomeData {
             int1 :: Int,
             int2 :: Int
         }

И генерирует функции int1 :: SomeData -> Int и int2 :: SomeData -> Int. При правильном экспорте функций из модуля оно позволяет и внутреннюю структуру менять без изменения пользователей , например, еще поле добавить (что было бы более трудоемко в случае pattern-матчинга). Кстати, возможно именно такая возможность изменять структуру была причиной введения "именованных полей", а не читаемость. Ну тогда мы получиим почти утверждение Дениса "стараться не использовать кортежи в публичных функциях", но на случай функций, у которых возвращаемое значение еще не устоялось.
Re[10]: Использование tuple
От: maxkar  
Дата: 18.10.09 20:15
Оценка: +1
Здравствуйте, VladD2, Вы писали:

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


M>>Не может программист знать, что функция делает.


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

VD>Да, ну?


VD>Далее раговаривать нам с тобой не о чем. У нас диаметрально противоположенная база.


Ну у меня не то, чтобы такая незыблемая база. На самом деле очень хорошо работать с программистом, который отлично знает все API, которое используется. Только это, во-первых, долго (база самописного кода в организации может быть большой), а во-вторых, далеко не всем может быть интересно. Есть программисты, которым достаточно сделать "чтобы работало", которые не изучают используемые классы, например, а пишут код на базе примеров из интернета и существующего кода, а также ищут методы для использования через подсказку в IDE. И это тоже существующая реальность. Ее не только я наблюдал, например в "Practical API Design. Confession of a Java Framework Architect" автор тоже пишет, что есть такие программисты (ну и еще развивает мысль clueless programming, когда не нужно тратить много времени на обучение, чтобы выполнять задачи). Сама по себе ориентация на программиста, не читающего документацию, имеет свои преимущества — его можно на 2-3 день сажать решать реальные задачи. Если захочет — выучит API подробнее, не захочет — вомзожно, найдет более интересную подсистему и т.п. Да, такое не везде применимо, нужно смотреть конкретные случаи.

M>>Для библиотек еще можно такого требовать, но для кода организации — нет.


VD>Я не знаю кто такая "кода организации". Но знаю точно, что минимальная еденица абстракции в программировании на любом языке окромя ассемблера — это функция (метод/процедура). Оспоривать это глупо.


"Код организации" — это то, что написали и не удалили программисты организации за время существования этой организации (плюс купленный код и т.п.). В небольшом проекте на 200-300 классов и порядка 5 методов/полей на класс мы получим 1000 "единиц абстракции". Одному человеку их знать тяжело (а если проект большой, то получаем вообще огромную проблему), абстракции забываются. Уровни абстракций спасают (это если их не забыли на определенном этапе ввести, иначе получится спагетти на те же 1000 "произвольно связанных" абстракций, что гораздо хуже). Но при подходе "сначала изучи систему, затем что-то меняй", у архитекторов/тим-лидов возникнут проблемы — чтобы залезть куда-то на нижнии уровни абстракций, нужно учить подсистему (или сразу все знать). В моем же подходе — может. Да, это будет медленнее, чем у ответственного за соответствующую подсистему, но все равно возможно. Ему не нужно досконально знать, что делают 10 функций, вызываемых из другой (при поисках багов детали реализации все равно приходится читать). С большой вероятностью он не зная деталей все равно найдет вероятное место ошибки (хотя может и не повезти). Обычно то он туда лазить не должен, но проекты (бюджет, количество программистов и их квалификация) бывают разные. На некоторых проектах подобная необходимость бывает оправданной.

M>> Иначе ценность программиста в компании сильно определяется тем, что же из ее кода он знает.


VD>Причем тут код? Надо чеотко понимать, что знать что делает функция, и знать как она реализована — это не одно и то же.

VD>Я не даром говорил об абстракции.

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

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


VD>А. Это теория по которой 1000 обезьян должны написать "Войну и мир"? Я с ней не согласен.


Ну на теорию это не тянет, скорее вопрос личных предпочтений. Вышесказанное — личное мнение (даже не мною впервые сформулированно). Я пока не видел работ, в которых исследуется влияние подобных акцентов (акцент на знание систем или ориентация на незнание) на проекты. Мне нравятся проекты, где можно акцентироваться и на возможности "легко и просто" отдать компонент/систему/разработку другим разработчикам. Фактически, снизить риски при необходимости замены программиста другим (не сделать из программистов винтики, не получается, остается много простора для творчества), меня в том числе. При получении же программиста в команду достаточно быстро начать получать от него пользу (вне зависимости от квалификации). Если я правильно понял вашу позицию, вы утверждаете, что перед постановкой программисту задач ему нужно "прочитать лекцию" по подсистеме (дать время на обучение необходимому набору абстракций). Такая позиция тоже имеет право на жизнь. В ряде случаев она вполне может быть идеальной для разработки. Но в большинстве случаев применимы оба подхода, каждый имеет свои достоинства и недостатки и на практике получается их смесь в различных пропорциях. Поэтому "не согласиться" с вашей позицией я тоже не могу. Могу только признать, что нам нравятся разные подходы к разработке. И даже не смотря на это приходится наблюдать за другими подходами — в них бывают интересные идеи, которые можно "утащить себе". Да и может так оказаться, что окажусь в ситуации, когда мне понравится противоположный подход. В этом смысле обсуждения различных достоинств и недостатков различных подходов как раз очень и очень полезны.
Re[15]: Использование tuple
От: FR  
Дата: 19.10.09 12:33
Оценка:
Здравствуйте, maxkar, Вы писали:

M>Не про меня, случайно? Я прекрасно понимаю, что это базовые вещи. И partition использовался потому, что был приведен примером в том сообщении, с которым я не согласился. Не видел особого смысла менять пример. Если же восстановить контекст того сообщения, на которое я в начале отвечал, получается, что в нем была аргументация в духе "вы не умеете писать внятные функции, вот чем не очевидна partition". И в результате получили, что "partition является одной из базовых функций ФП, и поэтому ее значение нужно знать". С последним утверждением я никогда не спорил. Но если использовать только его для аргументации исходного сообщения, мы получим "вы не умеете писать внятные функции, потому что есть вот базовая функция partition, по которой совершенно очевидно, что она делает". Слово "базовая" — ключевое. Без него все обвинения в "незнаинии ФП" не работают. А с ним не работает пример. Точнее, он "условно" работает — только в определенном контексте. Доказательств же того, что оно работает всегда я не увидел (хотя вроде бы пытался получить), утверждение же Влада было сформулировано в категорической форме (для вообще всех функций, не только базовых).


Я никого ни в чем ни обвиняю
И мне лень разбираться с контекстами


M>Это если есть базовые функции. А если их нет? Или программист их не знает (бывает такое у junior'ов)? Последнее, правда, решается не средствами языка.


Где это их нет?
Если не знает пусть учит.

M>Еще более интересная ситуация, когда "базовых" вещей не одна. Вот совершенно недавний пример. Разбор SWF-файла. Вот в нем есть структура "прямоугольник". И кроме выборов для tuple для их хранения есть не только (x1, y1, x2, y2) и (x1, y1, width, height). В этих двух случаях можно было бы взять то, что используется в gui (том же gtk, например). Проблема в том, что в "предметной области" (SWF-файл) там вообще (x1, x2, y1, y2). И из-за этого отдать предпочтение ни одному из вариантов нельзя. Если взять базовый формат SWF нужно следить за новыми программистами и правильностью понимания прямоугольника. Если же взять понимание GUI (с шириной или второй координатой), то прямоугольник может неправильно трактовать программист, знающий формат файла. Это все решается guidelines не в коде, ревью и т.п. Если же вернуться к примеру, сформулируем так: "разве не очевидно, что возвращает функция"


Не используй тут кортежи используй структуры.

M>Т.е. хорошо, когда есть какая-та база (причем единственная и не допускающая однозначностей). А вот если этого нет (новая область и т.п.), можно собрать много граблей на разных пониманиях разными программистами и т.п.


Но это не повод не знать базу.

M>Ну вот чуть выше был SWF'овский прямоугольник. А так я верю, что вам имена и были не нужны. Возможно, на это влиял стиль программирования и т.п. (ничего плохого не имею в виду) Но вот в Haskell (с pattern match'ингом) были введены таки именованные поля для алгебраических типов. Объявление выглядит примерно так:

M>
M>data SomeData =
M>         SomeData {
M>             int1 :: Int,
M>             int2 :: Int
M>         }
M>


Это не кортеж, а структура (в OCaml и F# есть аналогичный тип — record)
Re[11]: Использование tuple
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.10.09 17:10
Оценка:
Здравствуйте, maxkar, Вы писали:

M>Ну вот в двух первых сообщениях этой подветки Рысцов Денис и IDL поделились своим опытом. Каким-либо основаниям считать их опыт неподходящим указано не было. Причем Денис указал даже срок — 1 год, что характеризует класс проекта. Затем вы обвинили их в "не внятности ваших функций". Только вот дальше оказалось, что пример в том обвинении тоже "не очень". Сама по себе "в вакууме" приведенная функция оказалась тоже не слишком внятной. Пришлось применять аргументы вроде "это везде в ФП" и подобные, чтобы объяснить, почему же результат именно такой, как есть. Только вот аргумент этот не слишком универсальный. Не под все проекты подходит. Не всегда можно выделить четкую и неизменную предметную область, в которой ничего не меняется. Например, курсовая вполне может служить примером проекта с не слишком четкими требованиями. Вполне вероятно, какие-то требования менялись в процессе работы (в зависимости от полученных результатов, требований научного руководителя и т.п.). Там как раз можно наблюдать много эффектов "промышленного программирования" вроде необходимости много читать старый код и что-то менять. Их вывод был — tuples (неименнованные) в публичных интерфейсах на их проектах доставляют больше неудобств, чем дают преимуществ.


Не надо инсинуаций. IDL просто никогда в жизни не использовал кортежи, так что озвучивал всего лишь свои предрассудки.

Рысцов же описывал свою практику. Собственно похожая практика есть у всех приличных программистов.
Слова "стараться не использовать" не означает, что ни в коем случае не использовать. В очевидных случаях их очень даже можно использовать. Ну, и в некоторых случаях удобнее написать коментарий, а не лепить лишние типы.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Использование tuple
От: jenyavb  
Дата: 20.10.09 12:57
Оценка:
Здравствуйте, IDL, Вы писали:

IDL>В FW 4 появился новый тип tuple, перенятый с функциональных языков.


Вот интересно, нафига сделали Tuple<T>? Зачем кортеж с одним значением?
... << RSDN@Home 1.2.0 alpha 4 rev. 1253>>
Re[2]: Использование tuple
От: Sinclair Россия https://github.com/evilguest/
Дата: 20.10.09 13:41
Оценка: +3
Здравствуйте, jenyavb, Вы писали:

J>Вот интересно, нафига сделали Tuple<T>? Зачем кортеж с одним значением?

Лично меня больше интересует другой вопрос: где Tuple? Т.е. кортеж с нулём значений?
... << RSDN@Home 1.2.0 alpha rev. 677>>
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[9]: Использование tuple
От: Gaperton http://gaperton.livejournal.com
Дата: 20.10.09 15:08
Оценка:
Здравствуйте, Sinclair, Вы писали:

G>>А мне достаточно. Возвращаясь к примеру — нет, у меня имена параметров всегда настолько информативны, что понятно, что в них лежит. Что и тебе советую. Это совсем не сложно — давать локальным переменным осмысленные имена.

S>Так, еще раз поясни — ты сейчас про имена параметров или про имена переменных?

Сейчас — про имена переменных, а не параметров.

G>>Вопросы по пониманию — есть? С чем спорим?

S>В этой сигнатуре компоненты тупла именованные. С чем спорим?

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

G>>В настоящем дизайне я напишу по другому. С туплами, разумеется — заводить для этой фигни типы — overkill. Я напишу так:


G>>
G>>-type point() :: { X::integer(), Y::integer() }.
G>>-type rectangle() :: { Left::point(), Right::point() }.

G>>-spec get_rect( ... ) -> rectangle().
G>>

G>>И верну тупл, да не один, а цельных три. Вопросы, что вернет get_rect — есть? Или опять остается что-то понять?
S>Опять у туплов компоненты именованные. Конечно, в таком варианте вопросов не будет. Но ты же вроде как утверждал, что туплам достаточно анонимных компонентов. Вот у тебя и будет

Да, именно так — я утверждал что это в большинстве случаев minor issue. Мой пример с именами не отменяет
этого тезиса.

S>
S>-type point() :: { integer(), integer() }.
S>-type rectangle() :: { point(), point() }.

S>-spec get_rect( ... ) -> rectangle().
S>


Не совсем так грустно. В вызывающем коде у меня будет:

{ { X, Y } = LeftPoint, RightPoint } = get_rect( ... )

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

G>>А если входные аргументы функции перепутали?

S>Еще раз поясняю: у входных аргументов, помимо типов, есть имена. Отсюда желание завести имена и у выходных аргументов, и по той же причине.

Достаточно заглянуть в онлайн-документацию к любой функции Эрланга, чтобы понять, насколько это на самом деле критично. Это почти пофигу на практике. По опыту говорю. Хотя — да, приятно, я предпочитаю инлайнить имена в декларациях типов сомнительных случаях.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.