Inline records
От: VladD2 Российская Империя www.nemerle.org
Дата: 10.10.09 13:23
Оценка: 48 (5) +4 :)
Идея инспирирована вот этой темой
Автор: IDL
Дата: 05.10.09
, анонимными типами C# и списком аргументов.

Для начала пояснения.

Как рассматриваются кортежи (tuple-ы) в функциональных языках (ФЯ)? Не скажу за все языки (хотя почти уверен, что в других ФЯ все обстоит сходным образом), но в Nemerle кортеж — это не просто структура данных. Кортеж — это часть дизайна языка. Дело в том, что в немерле (далее, для понимания, можно смело мысленно заменять немерле на ФЯ) функция является очень важным объектом. А раз функция — это объект, то у нее должен быть тип. Так вот, тип функции описывается как "X -> Y" (без кавычек), где X и Y — это типы. X — это тип аргументов, а Y — возвращаемого значения. Заметьте, в этом описании нет списка аргументов! Аргумент один! Это не случайно. Под этим есть не хилая теоретическая основа лямбда-исчесления Чёрча. Но язык тем не менее поддерживает функции с более чем одним аргументом. Как же это возможно?

Наличие функций с более чем одним параметром возможно благодаря кортежам. Если функция принимает два параметра один из которых строка, а второй целое, то такая функция записывается как "string * int -> Y". Таким образом типом параметров такой функции является кортеж "string * int". Логично, что и возвращаемое значение может быть так же кортежем, например, "string * int -> string * int".

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

Теперь, собственно предложение.

А почему бы не рассматривать возвращаемое значение функции так же как набор параметров? При этом синтаксис может быть совершенно разрообразным. Например, мы можем объявлять функцию так:
Гипотетический язык:
/*in parameters*/(string param1, int param2) FuncName /*out parameters*/(string ret1, int ret2)
{
}

/*in parameters*/(string param1) FuncName /*out parameters*/(int ret2)
{
}

Расширение C#:
(string ret1, int ret2) FuncName(string param1, int param2)
{
}

(string ret1) FuncName(int param2)
{
}


Кроме того в шарпе можно использовать следующее соглашение. Функцию описанную так:
string FuncName(string param1, inout int param2)
{
}

можно рассматривать как функцию с типом: string * int -> string * int и соответственно применять без передачи параметра по ссылке.
А функцию:
string FuncName(string param1, out int param2)
{
}

можно рассматривать как функцию с типом: string -> string * int и соответственно применять:
var (str, num) = FuncName("abc");

Расширение немерле:
FuncName(param1 : string, param2 : int) -> (ret1 : string, ret2 : int)
{
}

(string ret1, int ret2) FuncName (string param1, int param2)
{
}
[/c#]

Так как в таких сигнатурах имеются имена "полей", то конструкция декомпозиции (опять же обращаемся к немерле):
def (var1, var2, var3) = f();

можно обеспечить дополнительный контроль и поддержку IDE.
Кроме того можно будет будет использовать следующий синтаксис:
def x = f();
... = x.var1 + x.var2;
... x.var3

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

Сам тип при этом остается совместимым с кортежем и может передаваться всюду где используется обычные кортежи (с не именованными полями).

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