Re[10]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 22.02.12 13:47
Оценка: 16 (1)
Z>Давно подумывал о чем-то подобном, но руки не доходят. После рельс, постоянная перекомпиляция веб-приложения реально мешает разработке и выбивает из ритма. Решение частное или сможешь выложить в общий доступ?

Выложу, как только разберусь с DI контейнерами. Хотя, если хочешь посмотреть, можно сейчас уже сделать приватный репо.
Там ещё одна проблема осталась, копирование статичных данных в новую сборку.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[8]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 18:45
Оценка: 8 (1)
VD>Можно все таки описать исходную задачу? Какова цель обхода?

В общем я делаю некий аналог jRebel для .NET. Это такая штука которая позволяет без явной перекомпиляции изменять код веб приложения. То есть изменил ты что-то в контроллере, нажал ctrl+s и получил обновлённое значение в браузере. Все это без потери HttpContext, сессии и прочего.

Для того, чтобы этого добиться, я компилирую новую сборку при изменении файлов исходников. Но даю ей другое имя, чтобы не было конфликтов типов. Потом подгружаю её в текущий AppDomain и подсовываю "новый" контроллер при следующем запросе. Там ещё много тонкостей, в основном связанных с тем, что типы из views-сборки должны соответствовать типам из сборки приложения, но это уже готово.

Короче практически всё работает, осталась проблема с IoC контейнерами. Типы в них остаются из старой сборки. Инициализировать их заново — это лишняя работа для пользователя библиотеки, так что желательно заменить типы автоматически.
Тонкость здесь вот в чём: конкретных типов контейнеров я не знаю, иначе мне пришлось бы добавлять все существующие IoC решения к себе в референсы и ориентироваться на них. Вместо этого я просто беру контейнер как object, а там уже с помощью рефлекшена произвожу раскопки.

Так что генерировать дерево типов на стадии компилации скорее всего не выйдет.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[4]: Матчинг дженерик параметров
От: m e  
Дата: 22.02.12 19:55
Оценка: +1
VD>Еще можно воспользоваться активными паттернами. Это аналогично введению своего макроса, только значительно проще.

слово active можно было бы распологать у самого паттерна, а не у слова match:

match(5)
{
  | 4 => Console.WriteLine(4);
  | active Sum(2,x) => Console.WriteLine(x);
  | _ => Console.WriteLine("You will never see it");
}


тогда была бы возможность пользоваться как обычными паттернами, так и активными в рамках одного матчинга
Матчинг дженерик параметров
От: Аноним  
Дата: 16.02.12 15:11
Оценка:
Может это уже спрашивали, но у меня не получилось найти.

def m() {
  ...
  def t : object = ...;
  match(t) {
    | _ is IDictionary['k,'v] => {}
    | _ is IEnumerable['k] => {}
    | _ => {}
  }
  ...
}


Такая штука штука не работает. В принципе понятно, что компилятору нужно знать откуда объявились ['k, 'v].
То есть, так работает:

def m['k,'v]() {
  ...
  def t : object = ...;
  match(t) {
    | _ is IDictionary['k,'v] => {}
    | _ is IEnumerable['k] => {}
    | _ => {}
  }
  ...
}


Но этот матч у меня часть большого comp expression, а вводить типы во внешней функции совсем не хочется.
Есть ли обходные варианты? Сейчас беру типы из GetGenericArguments()
Re: Матчинг дженерик параметров
От: catbert  
Дата: 16.02.12 19:31
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Такая штука штука не работает.


Мне кажется, вы хотите сделать что-то противоречащее логике системы типов .NET. В рантайме нельзя спросить, имеет ли объект тип IDictionary[чегототам, чегототам]. Нужно точно знать конкретный тип с подставленными конкретными параметрами (кажется это называется closed generic type).

Но можно матчить просто по IEnumerable, потому что IEnumerable[T] подтип IEnumerable. С IDictionary[K, V] хуже; тем не менее, большинство объектов, которые реализуют IDictionary[K, V], также реализуют IDictionary, так что можно матчить просто по IDictionary.
Re[2]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 16.02.12 22:18
Оценка:
C>Мне кажется, вы хотите сделать что-то противоречащее логике системы типов .NET. В рантайме нельзя спросить, имеет ли объект тип IDictionary[чегототам, чегототам]. Нужно точно знать конкретный тип с подставленными конкретными параметрами (кажется это называется closed generic type).

С проверкой всё не так уж и сложно:

def d = Dictionary.[int, string]();
// | d is Dictionary[TKey, TValue] => {}
Console.WriteLine(d.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)));

// | d is Dictionary[int, TValue] => {}
Console.WriteLine(d.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>))
                  && d.GetType().GetGenericArguments()[0] == typeof(int));

А вот как эти типы "продвинуть" в тело матча, я не представляю. Мне кажется макросом тут уже не обойдёшься.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.02.12 23:15
Оценка:
Здравствуйте, Аноним, Вы писали:

А>
А>    | _ is IDictionary['k,'v] => {}
А>


А>Такая штука штука не работает. В принципе понятно, что компилятору нужно знать откуда объявились ['k, 'v].


Дело в том, что паттерн is не просто проверяет реализует ли тип некоторый интерфейс, но и, в случае успеха, приводит тип к нему. А привести значение к открытому дженерик-типу невозможно. Это станет понятно, если вместо "_" использовать паттер "переменная":
  | x is IDictionary['k,'v] => // Какой будет тип у "x"?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 16.02.12 23:22
Оценка:
Здравствуйте, ionoy, Вы писали:

I>
I>def d = Dictionary.[int, string]();
I>// | d is Dictionary[TKey, TValue] => {}
I>Console.WriteLine(d.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>)));

I>// | d is Dictionary[int, TValue] => {}
I>Console.WriteLine(d.GetType().GetGenericTypeDefinition().IsAssignableFrom(typeof(Dictionary<,>))
I>                  && d.GetType().GetGenericArguments()[0] == typeof(int));
I>

I>А вот как эти типы "продвинуть" в тело матча, я не представляю. Мне кажется макросом тут уже не обойдёшься.

Ну, почему? Макросами можно решить много чего, в том числе, и эту задачу .

Можно создать макрос typematch (аналог match) который перепишет паттерны в приведенный выше код. Если это удовлетворит (т.е. если само значение не нужно приводить к этому типу), то это решит проблему. В прочем с тем же успехом можно просто написать:
def m()
{
  ...
  def t : object = ...;
  match(d.GetType().GetGenericTypeDefinition())
  {
    | x when x.IsAssignableFrom(typeof(IDictionary[_,_])) => {}
    | x when x.IsAssignableFrom(typeof(IEnumerable[_]))  => {}
    | _ => {}
  }
  ...
}


Еще можно воспользоваться активными паттернами. Это аналогично введению своего макроса, только значительно проще.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 10:02
Оценка:
VD>Ну, почему? Макросами можно решить много чего, в том числе, и эту задачу .
VD>Можно создать макрос typematch (аналог match) который перепишет паттерны в приведенный выше код. Если это удовлетворит (т.е. если само значение не нужно приводить к этому типу), то это решит проблему.

Сравнение и правда несложно макросом описать. А вот как сделать нечто вроде этого:


match(t) // t : object
{
 | t is Dictionary['t,'k] => {
    def l = List.['t]();
 }
}


С одной стороны, понятно, что это несколько протеворечит системе типов .NET. А с другой, мне кажется, очень органично вписывается в паттерн матчинг.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[2]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 10:17
Оценка:
VD>Дело в том, что паттерн is не просто проверяет реализует ли тип некоторый интерфейс, но и, в случае успеха, приводит тип к нему. А привести значение к открытому дженерик-типу невозможно. Это станет понятно, если вместо "_" использовать паттер "переменная":
VD>
VD>  | x is IDictionary['k,'v] => // Какой будет тип у "x"?
VD>


Я уже ответил выше, чего хотелось бы добиться. Теоретически, это должно быть решаемо (правда на уровне компилатора).
Мы ведь работаем с дженерик типами в методах:

void m['t](l : List['t]) 
{
   def d = Dictionary.['t, int]();
}


Вот сигнатура метода получается условие для матча, а тело и есть тело.
Но это наверное всё слишком сложно, надо ведь констрейнты учитывать и прочее.

Можно, конечно написать нечто вроде:

match(t) {
  | _ is Dictionary<,> typed (t1, t2) => {}
}


Но тогда t1 и t2 будут объектами Type, т.е. чтобы из них сделать новый экземпляр дженерик типа придётся лезть в рефлекшн.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[3]: Матчинг дженерик параметров
От: catbert  
Дата: 17.02.12 11:38
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Но тогда t1 и t2 будут объектами Type, т.е. чтобы из них сделать новый экземпляр дженерик типа придётся лезть в рефлекшн.


Да, теоретически можно написать генерик-метод, и вызывать его через рефлекшн. Но это чудо не стоит делать частью языка или стандартной библиотеки
Re[5]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 14:24
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Сравнение и правда несложно макросом описать. А вот как сделать нечто вроде этого:

I>
I>match(t) // t : object
I>{
I> | t is Dictionary['t,'k] => {
I>    def l = List.['t]();
I>


I>С одной стороны, понятно, что это несколько протеворечит системе типов .NET. А с другой, мне кажется, очень органично вписывается в паттерн матчинг.


А что за задача в целом? Почему данные в object-ах гоняются?

Может быть имеет смыл перенести часть вычислений на стадию компиляции и сделать их типизированными? Макросы как раз подобное позволяют.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[3]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 14:26
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Но тогда t1 и t2 будут объектами Type, т.е. чтобы из них сделать новый экземпляр дженерик типа придётся лезть в рефлекшн.


Без рефлекшона, то что ты хочешь на дотнете не сделать. Причем это еще будет не очень то и быстро.

Лучше опиши саму задачу (а не часть ее решения). Возможно есть лучше методы ее решения.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 15:06
Оценка:
VD>Лучше опиши саму задачу (а не часть ее решения). Возможно есть лучше методы ее решения.

Мне надо обойти сложный объект (в данном случае IoC контейнер), и найдя в нём определённые типы заменить их на свои собственные.
На самом деле приведённый код мне не так уж и нужен, вопрос я задал скорее из спортивного интереса.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[5]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 15:16
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Мне надо обойти сложный объект (в данном случае IoC контейнер), и найдя в нём определённые типы заменить их на свои собственные.

I>На самом деле приведённый код мне не так уж и нужен, вопрос я задал скорее из спортивного интереса.

Если типы известны во время компиляции, то код обхода и замены можно сгенерировать автоматически.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[6]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 16:29
Оценка:
VD>Если типы известны во время компиляции, то код обхода и замены можно сгенерировать автоматически.

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

public class A
{
  private _b : IB;
  this() {
    _b = B();
  }
}


Поэтому ходить желательно по инстансу в рантайме, только тогда будут известны настоящие типы.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[7]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 17:05
Оценка:
Здравствуйте, ionoy, Вы писали:

I>В таком случае код макроса будет не сильно отличаться от кода обхода, если я не ошибаюсь.


Макрос может генерировать код по ДСЛ или другой мета-модели. Т.е. другой уровень кода.

I>Ну и главный недостаток такого подхода в том, что такая ситуация разрулится неверно:

I>
I>public class A
I>{
I>  private _b : IB;
I>  this() {
I>    _b = B();
I>  }
I>}
I>

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

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

Можно все таки описать исходную задачу? Какова цель обхода?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[9]: Матчинг дженерик параметров
От: VladD2 Российская Империя www.nemerle.org
Дата: 17.02.12 20:32
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Тонкость здесь вот в чём: конкретных типов контейнеров я не знаю, иначе мне пришлось бы добавлять все существующие IoC решения к себе в референсы и ориентироваться на них. Вместо этого я просто беру контейнер как object, а там уже с помощью рефлекшена произвожу раскопки.


Очень багодромное решение.

А почему не подходит перезагрузка домена как а АСП.НЕТ?

I>Так что генерировать дерево типов на стадии компилации скорее всего не выйдет.


Да. Тут только через рефлекшон можно что-то сделать.

Макросы могут только помочь скрыть некрасивости под более читабельным синтаксисом.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[10]: Матчинг дженерик параметров
От: ionoy Эстония www.ammyui.com
Дата: 17.02.12 21:02
Оценка:
VD>Очень багодромное решение.
Согласен, но моя цель сделать инструмент максимально прозрачным для программиста. Сейчас достаточно вызвать Init метод в Application_Start, хотелось бы, чтоб так это и осталось. Разные контейнеры я могу отличать по имени типа, а значит изменять немного логику, если понадобится.

VD>А почему не подходит перезагрузка домена как а АСП.НЕТ?

Если перегрузить домен, то все статические члены обнулятся. Это значит, что нужно всё заново инициализировать, а инициализация в некоторых приложениях может 10-15 секунд занимать. Не лучший дебаг экспириенс. Плюс потеря сессии, HttpContext и прочего.
www.livexaml.com
www.ammyui.com
www.nemerleweb.com
Re[9]: Матчинг дженерик параметров
От: Ziaw Россия  
Дата: 21.02.12 18:59
Оценка:
Здравствуйте, ionoy, Вы писали:

I>В общем я делаю некий аналог jRebel для .NET. Это такая штука которая позволяет без явной перекомпиляции изменять код веб приложения. То есть изменил ты что-то в контроллере, нажал ctrl+s и получил обновлённое значение в браузере. Все это без потери HttpContext, сессии и прочего.


Давно подумывал о чем-то подобном, но руки не доходят. После рельс, постоянная перекомпиляция веб-приложения реально мешает разработке и выбивает из ритма. Решение частное или сможешь выложить в общий доступ?
Re[4]: Матчинг дженерик параметров
От: m e  
Дата: 22.02.12 17:20
Оценка:
VD>Еще можно воспользоваться активными паттернами. Это аналогично введению своего макроса, только значительно проще.

там объяснение только в https://github.com/rsdn/nemerle/blob/master/snippets/ActivePatterns/ActivePatterns/ActiveImpl.n или еще где-то есть?

ну и как всегда -- епрст, кто же *так* документацию пишет, на уровне шифровки

пример должен быть мотивированным, скажем простой пример может быть таким:

Console.WriteLine("Note, that y="); Console.WriteLine(y); /// это покороче надо записать, но я ваш синтаксис не помню
active match(y)
{
  | Product(2,x) => Console.WriteLine("Here is an integer x, that 2*x=y; such x = "); Console.WriteLine(x);
  | _ => Console.WriteLine("Sorry, there is no such an integer x, that 2*x=y");
}


почему именно от 4 потребовалось отнимать 2, совершенно не понятно, в то время как то, что только четные числа делятся на 2 придает мотивированность

и наконец -- можно ли писать 2*х вместо Product(2,x)? можно ли (рекурсивно) писать 3*х+1 ?
Re[4]: Матчинг дженерик параметров
От: m e  
Дата: 22.02.12 18:59
Оценка:
VD>Еще можно воспользоваться активными паттернами. Это аналогично введению своего макроса, только значительно проще.

еще момент: при первом взгляде на
Sum(a : int, b : int) : option[int]
{
   Some(b - a)
}

парсер вылетает с исключением (мой парсер, а не немерлешный)

при втором начинаешь подозревать опечатку (- вместо +)

вывод из этого тот, что *реализацию* (т.е. код Sum) надо показывать только после примера использования (т.е. после active match(y) ...)

и кстати еще один вопрос -- а что будет, если юзер напишет х,2 вместо 2,х:
active match(5)
{
  | 4 => Console.WriteLine(4);
  | Sum(x,2) => Console.WriteLine(x);
  | _ => Console.WriteLine("You will never see it");
}
Re[11]: Матчинг дженерик параметров
От: Ziaw Россия  
Дата: 23.02.12 05:56
Оценка:
Здравствуйте, ionoy, Вы писали:

I>Выложу, как только разберусь с DI контейнерами. Хотя, если хочешь посмотреть, можно сейчас уже сделать приватный репо.

I>Там ещё одна проблема осталась, копирование статичных данных в новую сборку.

Да мне не к спеху, все равно сейчас на рельсах пишу, в моно разве что потестить могу, если развернуть можно быстро.
Re[12]: Матчинг дженерик параметров
От: catbert  
Дата: 23.02.12 17:44
Оценка:
Здравствуйте, Ziaw, Вы писали:

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


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


А что с NRails кстати?
Re[13]: Матчинг дженерик параметров
От: Ziaw Россия  
Дата: 24.02.12 04:27
Оценка:
Здравствуйте, catbert, Вы писали:

C>А что с NRails кстати?


Да ничего. Я приостановил работу, когда понял, что проблем с интеграцией в 2008 студию будет больше чем с самим движком, а 2008 в тот момент стремительно уходила в небытие. Сейчас уже можно было бы пробовать написать интеграцию для 2010, но у меня нет задач, в которых я мог бы применить nrails. Если бы было время и задачи, я бы сейчас не стал завязываться на ASP.NET MVC, а сделал бы отдельные модули для генерации типов и маппинга, для роутинга, для генерации view. И применил бы все для NancyFx, который не требует специальных заточек студии и хостится в чем угодно.

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

Возможно система перекомпиляции на лету от ionoy, даст какую-то базу, для построения похожего по юзабилити решения, но все равно, есть куча моментов, которые на решениях от ms приходится делать через задницу. И есть куча прикладных инфраструктурных задач, которые требуют реализации и поддержки (организация скриптов и стилей, трансляция в javascript, вменяемый роутинг). Я не могу столько времени уделять на хобби.

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