Именованные туплы и более типизированные массивы
От: hi_octane Беларусь  
Дата: 14.02.11 14:32
Оценка: 20 (2) +1
Для хардкорной математики очень нужны странные фичи

1. Именованные туплы, а лучше именование параметров Generic'ов:

func() : (a:int * b:int * color:int)
{
  def x = new { a = 5, b = 20, color=30 };//тут по пальцам если вместо a и b указаны x и y, идеально если ещё и порядок не важен
  x;
}

//использование
def r = func();

Console.WriteLine(r.a);
Console.WriteLine(r.b);
Console.WriteLine(r.color);

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

2. Сильная типизация алиасов, с типизацией индексов массивов:
type Idx = int;
type Idy = int;
type Idz = int;

//объявление двумерного ступенчатого массива, с индексаторами Idx, Idy и типом значения Idz
def a : array[(dimension1 : Idx) array[(dimension2 : Idy) Idz]];

//тут компилятор даст по пальцам, т.к. у массива типы не int
a[5][10] = 20; 
//тут ок, т.к. у массива индексаторы правильных типов, и значение тоже правильного типа
a[5:Idx][10:Idy] = 20:Idz;

def iX = 1 : Idx;
def iY = 2 : Idy;
//с этого момента iX и iY - самостоятельные типы, 
//которые к int приводятся только через операторы : и :>
//соответственно встроенные операторы сложения вычитания и т.п. 
//тоже начинают понимать только значения правильного типа

Console.WriteLine(a[iX][iX]);//ошибка компиляции, второй индекс должен быть типа Idx;
Console.WriteLine(a[iX][iY]);//всё ок

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

Интересует, в каком направлении копать, и насколько сложно эти две задачи реализовать в Н1 (пусть даже ценой поддержания собственной версии компилятора, если больше никому не надо). И огромная просьба учесть нужность этих фич для системы типов Н2.
Также буду благодарен за критику и возможные идеи в данных направлениях.
фича математика именованные туплы сильные алиасы feature math named tuples strong type aliases
Re: Именованные туплы и более типизированные массивы
От: Аноним  
Дата: 14.02.11 14:54
Оценка:
Здравствуйте, hi_octane, Вы писали:

Крайне заинтересовало чем именно занимаетесь. Есть возможно схожие интересы.

1. Думаю проблем сделать не будет.

2. Не думаю что будет сделать просто.
Re: Именованные туплы и более типизированные массивы
От: WolfHound  
Дата: 14.02.11 16:49
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>И огромная просьба учесть нужность этих фич для системы типов Н2.

У меня есть кое какие мысли по расширяемой системе типов чтобы можно было делать произвольные статически типизированные ДСЛ.
Скажем тот же ПЕГ парсер был бы проще и лучше бы интегрировался с ИДЕ если бы я мог расширить систему типов так чтобы немерле смог выводить типы для правил.
Также можно будет сделать dynamic из C# просто расширением системы типов.
Но пока я разбираюсь с парсером.
Там есть еще куча всего что я хочу сделать.
Это касается как функциональности так и оптимизаций (я знаю как сделать его еще быстрее ).
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[2]: Именованные туплы и более типизированные массивы
От: Аноним  
Дата: 14.02.11 16:55
Оценка:
Здравствуйте, WolfHound, Вы писали:

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


_>>И огромная просьба учесть нужность этих фич для системы типов Н2.

WH>У меня есть кое какие мысли по расширяемой системе типов чтобы можно было делать произвольные статически типизированные ДСЛ.
WH>Скажем тот же ПЕГ парсер был бы проще и лучше бы интегрировался с ИДЕ если бы я мог расширить систему типов так чтобы немерле смог выводить типы для правил.
WH>Также можно будет сделать dynamic из C# просто расширением системы типов.
WH>Но пока я разбираюсь с парсером.
WH>Там есть еще куча всего что я хочу сделать.
WH>Это касается как функциональности так и оптимизаций (я знаю как сделать его еще быстрее ).

Разве вывод типов не сделает их эквивалентными?
Re[3]: Именованные туплы и более типизированные массивы
От: WolfHound  
Дата: 14.02.11 17:01
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Разве вывод типов не сделает их эквивалентными?

Не понял вопрос.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[4]: Именованные туплы и более типизированные массивы
От: Аноним  
Дата: 14.02.11 17:06
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, <Аноним>, Вы писали:


А>>Разве вывод типов не сделает их эквивалентными?

WH>Не понял вопрос.

Разве механизм вывода типов не сделает типы эквивалентными в примере ТС.
Re[5]: Именованные туплы и более типизированные массивы
От: WolfHound  
Дата: 14.02.11 17:11
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Разве механизм вывода типов не сделает типы эквивалентными в примере ТС.

Если он будет знать про "сильные алиасы" то конечно нет.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Именованные туплы и более типизированные массивы
От: Аноним  
Дата: 14.02.11 18:07
Оценка: :)
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, <Аноним>, Вы писали:


А>>Разве механизм вывода типов не сделает типы эквивалентными в примере ТС.

WH>Если он будет знать про "сильные алиасы" то конечно нет.

а разве в немерли есть сильные алиасы?
Re[2]: Именованные туплы и более типизированные массивы
От: hi_octane Беларусь  
Дата: 14.02.11 19:49
Оценка: +1
Здравствуйте, WolfHound, Вы писали:

_>>И огромная просьба учесть нужность этих фич для системы типов Н2.

WH>У меня есть кое какие мысли по расширяемой системе типов чтобы можно было делать произвольные статически типизированные ДСЛ.
Так ты прежде чем делать, какой диз-док опубликуй, ибо необходимость расширять типы есть, причём расширять даже в тех местах где .NET вроде как не позволяет (тот же мой пример с типизацией Array). А как правильно сделать — можно придумать только рассмотрев как можно больше сценариев использования. Например мне в проекте ещё нужны виртуальные наследники, которые существуют только в уме у компилятора, а в IL от них остаются только базовые классы. Ту же типизацию индексаторов можно было бы сделать создав виртуального наследника от массива, у которого индексаторы были бы типизированы, но на последнем этапе компиляции подменялись бы на реальные типы.

WH>Скажем тот же ПЕГ парсер был бы проще и лучше бы интегрировался с ИДЕ если бы я мог расширить систему типов так чтобы немерле смог выводить типы для правил.

WH>Также можно будет сделать dynamic из C# просто расширением системы типов.
dynamic малость ущербен — у него не может быть интеллисенса и compile-time валидации. Более правильно было бы сделать dynamic псевдо-типизируемым дженериком. Например:
def d = obj : dynamic<IList>;
d.|/* <- тут автокомплит показывает методы и свойства IList, 
есть проверка синтаксиса, аргументов, и т.п. При этом компилятор ругается на попытки 
сделать что-то за пределами IList. Но это не кастинг, вызовы идут обычным 
механизмом динамиков, т.е. obj вполне может от всего IList поддерживать только Count.*/

Это кстати тоже кусочек системы типов. Когда тип виртуально есть, а реально вместо него object запечёный с сахаром.

WH>Там есть еще куча всего что я хочу сделать.

WH>Это касается как функциональности так и оптимизаций (я знаю как сделать его еще быстрее ).
Имхо логично сделать сначала медленный парсер, но чтоб его начали прикручивать к Н2 пораньше, а ускорять уже в процессе. Но, полагаю, ты это и без меня прекрасно знаешь
Re[3]: Именованные туплы и более типизированные массивы
От: WolfHound  
Дата: 14.02.11 20:26
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Так ты прежде чем делать, какой диз-док опубликуй, ибо необходимость расширять типы есть, причём расширять даже в тех местах где .NET вроде как не позволяет (тот же мой пример с типизацией Array).

Опубликую конечно. Просто от мыслей до диздока...
Все что ты понаписал моим мыслям не противоречит.

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

Ну я так и делаю.
Правда он у меня уже очень даже не медленный. А будет еще быстрее.
Одна из мыслей дать пользователю возможность давать компилятору хинты на тему какие символы в данном месте всречаются чаще.
Например этот код генерирует ужасающее колличество проверок:
      letterCharacter       = [Lu, Ll, Lt, Lm, Lo, Nl];
      combiningCharacter    = [Mn, Mc];
      decimalDigitCharacter = [Nd];
      connectingCharacter   = [Pc];
      formattingCharacter   = [Cf];

      identifierStartCharacter  = letterCharacter / "_";
      identifierPartCharacters  = letterCharacter / decimalDigitCharacter / connectingCharacter / combiningCharacter / formattingCharacter;
      identifierBody            = identifierStartCharacter identifierPartCharacters*;

Хоть я и сделел генерацию бинарного поиска но всеравно много. Плюс код толстый -> промахи кеша.
При этом в подавляющем большенстве случаев этот код не встретит ничего кроме латинских букв, цифр и "_".
И если правило переписать так:
      identifierStartCharacter  = [hint: 'a'..'z' + 'A'..'Z' + '_'] (letterCharacter / "_");
      identifierPartCharacters  = [hint: 'a'..'z' + 'A'..'Z' + '_' + '0'..'9'] (letterCharacter / decimalDigitCharacter / connectingCharacter / combiningCharacter / formattingCharacter);

и проверять сначала то что попадает в диапозон заданный хинтом то можно сэкономить много проверок в наиболее частых случаях.
... << RSDN@Home 1.2.0 alpha 4 rev. 1472>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Именованные туплы и более типизированные массивы
От: _nn_ www.nemerleweb.com
Дата: 14.02.11 21:29
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Для хардкорной математики очень нужны странные фичи


_>1. Именованные туплы, а лучше именование параметров Generic'ов:


_>
_>func() : (a:int * b:int * color:int)
_>{
_>  def x = new { a = 5, b = 20, color=30 };//тут по пальцам если вместо a и b указаны x и y, идеально если ещё и порядок не важен
_>  x;
_>}

_>//использование
_>def r = func();

_>Console.WriteLine(r.a);
_>Console.WriteLine(r.b);
_>Console.WriteLine(r.color);
_>

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

[Record]
class R
{
  public A     : int { get; }
  public B     : int { get; }
  public Color : int { get; }
}

def f() : R
{
  def x = R(a = 5, b = 20, color = 30);
  x
}


Чем такой вариант не устраивает ?
Как вариант можно еще укоротить макросом скажем наподобие:

[assembly: DefineRecord(A : int, B : int, Color : int)]


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

def func() { (1,2,3) }

def (a, b, color) = func;
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Именованные туплы и более типизированные массивы
От: hi_octane Беларусь  
Дата: 14.02.11 22:08
Оценка:
Здравствуйте, _nn_, Вы писали:

__>
__>def f() : R
__>{
__>  def x = R(a = 5, b = 20, color = 30);
__>  x
__>}
__>


__>Чем такой вариант не устраивает?

Математики от меня наглядности требуют. В случае если таких методов штук 20 наберётся — получится столько-же Record'ов, и все с одной лишь целью — вернуть значение или список значений. Наглядность за этим R для них теряется. Тупл тоже отклоняют — завязываться на порядок аргументов или возвращаемых значений для них смерти подобно.

Про варианты объявления Record'а макросом я много думал, и пробовал. Думал также расширить макрос IAnonymous, таким образом чтобы он возвращал наследника от IAnonymous, с объявленными пропертями. Но нужно максимально информативное и объявление функции и использование её результата. Основная проблема, судя по всему, в объявлении, где нужно смешать и имена и типы, а имён в типе возвращаемого значения сейчас никто не ждёт. Вот это и хочется победить. Record был бы идеален, если бы объявлялся непосредственно как возвращаемое значение функции.

В общем основной вопрос, действительно ли сложно допилить компилятор таким образом, чтобы при разборе туплов расширенная информация о типах и именах скармливалась в какой-то макрос, который бы это разбирал, создавал нужный рекорд на уровне сборке, и далее по образу и подобию IAnonymous. Пока эта задача не выглядит простой, но я очень давно в компилятор не заглядывал, вот и хочу получить напутствие... может там на 3 человеко-месяца рефакторинг, и лучше эти силы вложить в помощь в разработке этих же фич но для Н2.
Re: Именованные туплы и более типизированные массивы
От: Ziaw Россия  
Дата: 15.02.11 15:21
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>Для хардкорной математики очень нужны странные фичи


_>1. Именованные туплы, а лучше именование параметров Generic'ов:


_>
_>func() : (a:int * b:int * color:int)
_>{
_>  def x = new { a = 5, b = 20, color=30 };//тут по пальцам если вместо a и b указаны x и y, идеально если ещё и порядок не важен
_>  x; // по пальцам будет тут конечно
_>}
_>

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

Фича отличная, нужна. Вообще нужен эффективный duck typing, с ним это реализуется легко.

_>2. Сильная типизация алиасов, с типизацией индексов массивов:

_>
_>type Idx = int;
_>type Idy = int;
_>type Idz = int;

_>//объявление двумерного ступенчатого массива, с индексаторами Idx, Idy и типом значения Idz
_>def a : array[(dimension1 : Idx) array[(dimension2 : Idy) Idz]];
_>


Фича спорная, до ума ее довести довольно сложно.
Re[3]: Именованные туплы и более типизированные массивы
От: _nn_ www.nemerleweb.com
Дата: 06.03.11 08:23
Оценка:
Здравствуйте, hi_octane, Вы писали:

<skip>

Я полагаю , что это как раз можно сделать с метаатрибутом.
Знающие люди подскажут насколько такое реально сделать.

Что-то в стиле:
[CreateType(FRet, a : int, b : int)]
public F() : FRet
{
  def x = FRet(a = 1, b = 2);
  x
}


Где CreateType создает тип в классе по аргументам.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Именованные туплы и более типизированные массивы
От: BogdanMart Украина  
Дата: 06.03.11 10:54
Оценка:
Здравствуйте, hi_octane, Вы писали:

_>//тут компилятор даст по пальцам, т.к. у массива типы не int
_>a[5][10] = 20; 
_>//тут ок, т.к. у массива индексаторы правильных типов, и значение тоже правильного типа
_>a[5:Idx][10:Idy] = 20:Idz;


можно зделать так:

enum Idx : int {}

class MyList[Tindex,Tval]
where Tindex : int
{
_l : List[Tval] = List();

public Item[index : Tindex] : Tval // опускаю все методы кроме индексатора
{ // потому что пример чисто
get
{
_l[index]
}
set
{
_l[index] = value;
}
}
}
и использование:
      def l = MyList.[int,int]();
      l[0] = 5;
      
      def l = MyList.[Idx,int](); // Тут почему то дает ошибку: Error: expected int+, got Nemrrrr.Idx in generic specifier: Nemrrrr.Idx is not a subtype of System.Int32 [simple require]
      l[0 :> Idx] = 5;   // если  убрать where Tindex : int  то эта строчка работает


Думаю если пофиксить выведение типов для структур то это будет вполне реализуемо!
Re[2]: Именованные туплы и более типизированные массивы
От: BogdanMart Украина  
Дата: 06.03.11 10:56
Оценка:
Извиняюсь за битый листинг:
  enum Idx : int {}
  
  class MyList[Tindex,Tval]
    where Tindex : int
  {
    _l : List[Tval] = List();
    
    public Item[index : Tindex] : Tval
    {
      get
      {
        _l[index]
      }
      set
      {
        _l[index] = value;
      }
    }    
  }
Re[4]: Именованные туплы и более типизированные массивы
От: hi_octane Беларусь  
Дата: 06.03.11 11:10
Оценка:
__>Я полагаю , что это как раз можно сделать с метаатрибутом.
__>Знающие люди подскажут насколько такое реально сделать.

Да такой вариант возможен, но уже после того как я эту ветку начал, удалось дотумкать ещё до одного вида, который сейчас кажется достаточно простым в реализации, и при этом сохраняет все плюшки автокомплита и интеллисенса:

[ExpandToRecord]
Func(a : int, b : bool, out c : int, out m : decimal) : void
{
//здесь компилятор искаропки проследит чтобы возвращаемые значения были правильно заданы, и т.п.
}

//а аттрибут создаёт пару типов AB и CM, и различные версии функции, которые вызывают основную
Func(ab : AB) : CM
{  
  def cm = CM();
  Func(ab.a, ab.b, out cm.c, out cm.m);
  cm;
}

Func(ab : AB, out c : int, out m : decimal) : void
{ 
}

Func(a : int, b : bool) : CM
{
}


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

Но вот как быть с типизированными индексами массивов пока не знаю Частную задачу из одних массивов решать не хочется. Круто было бы если бы удалось совместно с кем-то продумать и ввести в язык "макротипы", которые ведут себя совсем как настоящие, но на какой-то из последних стадий разворачиваются в то, во что сами решат. Но тут нужно тотальную ревизию понятия "тип" проводить, и не факт что я с этим справлюсь.
Re[5]: Именованные туплы и более типизированные массивы
От: BogdanMart Украина  
Дата: 06.03.11 11:18
Оценка:
Здравствуйте, hi_octane, Вы писали:

__>>Я полагаю , что это как раз можно сделать с метаатрибутом.

__>>Знающие люди подскажут насколько такое реально сделать.

_>Да такой вариант возможен, но уже после того как я эту ветку начал, удалось дотумкать ещё до одного вида, который сейчас кажется достаточно простым в реализации, и при этом сохраняет все плюшки автокомплита и интеллисенса:


_>
_>[ExpandToRecord]
_>Func(a : int, b : bool, out c : int, out m : decimal) : void
_>{
_>//здесь компилятор искаропки проследит чтобы возвращаемые значения были правильно заданы, и т.п.
_>}

_>//а аттрибут создаёт пару типов AB и CM, и различные версии функции, которые вызывают основную
_>Func(ab : AB) : CM
_>{  
_>  def cm = CM();
_>  Func(ab.a, ab.b, out cm.c, out cm.m);
_>  cm;
_>}

_>Func(ab : AB, out c : int, out m : decimal) : void
_>{ 
_>}

_>Func(a : int, b : bool) : CM
_>{
_>}
_>


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

_>Получив кучу версий, можно весьма свободно управлять данными, и при этом иметь автокомплит, интеллисенс, вывод типов и прочие. И, судя по всему, вообще не меняя ничего в компиляторе.


_>Но вот как быть с типизированными индексами массивов пока не знаю Частную задачу из одних массивов решать не хочется. Круто было бы если бы удалось совместно с кем-то продумать и ввести в язык "макротипы", которые ведут себя совсем как настоящие, но на какой-то из последних стадий разворачиваются в то, во что сами решат. Но тут нужно тотальную ревизию понятия "тип" проводить, и не факт что я с этим справлюсь.


ОООо идея с макротипамми это +100 !!
Re[2]: Именованные туплы и более типизированные массивы
От: BogdanMart Украина  
Дата: 06.03.11 12:09
Оценка:
Оказалось это ограничение фреймворка, енум хоть и написано что от инта наследуется но он наследуется от енума на самом деле.
Вот рабочий пример:
  public enum Idx : int {}
  
  public class MyList[Tindex,Tval]
    where Tindex : ValueType

  {
    static this()
    {
      def typ = typeof(Tindex); 
      unless (typ.Equals(typeof(int)) || typ.IsEnum)
        throw System.ArgumentException();
    }    
    
    _l : array[Tval];
    public this(size : int)
    {
      _l = array(size);
    }
    
    public Item[index : Tindex] : Tval
    {
      get
      {
        _l[index :> int]
      }
      set
      {
        _l[index :> int] = value;
      }
    }    
  }

      def l = MyList.[int,int](5);
      l[0] = 5;
      
      def l = MyList.[Idx,int](5);
      l[1 :> Idx] = 5;
      
      def l = MyList.[double,int](5); // тут будет Ексепшн, что тип  недопустим
Re: Именованные туплы и более типизированные массивы
От: _nn_ www.nemerleweb.com
Дата: 06.03.11 15:40
Оценка:
Здравствуйте, hi_octane, Вы писали:
_>2. Сильная типизация алиасов, с типизацией индексов массивов:
_>
_>type Idx = int;
_>type Idy = int;
_>type Idz = int;
_>


А как это должно работать ?
Т.е. что вы хотите конкретно получить ? Возможно это не получится сделать.

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

strong type Idx = int;

=>
class Idx
{
  _value : int;

  public this() { }
  public this(value : int) { _value = value; }

  public static @:(o : Idx) : int { _value; }

  ... // Тут уже надо думать что и как делать
}


Сделать, чтобы работало хотя бы для базовых типов.
Как я понимаю этого вам будет достаточно.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.