juan_gandhi: (Default)
[personal profile] juan_gandhi
http://vpatryshev.blogspot.com/2012/06/cake-pattern-practices.html

Только что запостил. Там всё примитивно (надеюсь); если чего не хватает или неправильно, буду рад выслушать.

Date: 2012-06-10 09:10 pm (UTC)
From: [identity profile] xeno-by.livejournal.com
А как же селф-тайпы, чтобы избежать импортов FS? Плюс, иногда, когда наследование, как вид тюнинга логики, не спасает, нужны абстрактные типы. Также интересно, как внешне в миру интероперироваться с кейком.

Очень понравилось, что все крайне просто написано. Еще бы про селф-тайпы и получится замечательное эссе на тему того, как и за что мы любим Скалу. Спасибо :)
Edited Date: 2012-06-10 09:11 pm (UTC)

Date: 2012-06-10 09:45 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
Хм, self: FS? Попробую.
Абстрактные типа - может быть, но пока что на работе не сталкивался, в этих аппликативах с ними что-то не получается (а хотелось бы).

Последнее не понял. В смысле, различные имплементации подставлять?

Date: 2012-06-10 10:33 pm (UTC)
From: [identity profile] xeno-by.livejournal.com

Вот, например, разросся у меня кейк за время использования. Хочу из него вынуть пару слоев и вынести в отдельный объект, чтобы уменьшить каплинг (кейком хорошо прототипировать, но в нем все всех видят, поэтому быстро накапливается энтропия). С этим могут быть проблемы.

Конкретный пример. Есть кейк компилятора, в котором пасутся типы, деревья, блабла. Прямо в этом кейке сидел реификатор. Потом выяснилось, что реификатор хорошо бы вообще выщемить из компилятора, превратив в макрос, у которого отдельная вселенная со своими типами и деревьями. Т.е. тип вселенной тот же самый (scala.reflect.api.Universe), но инстанс другой (в компиляторе это переменная под названием global, а у макроса это c.universe, где с это переменная типа Context, которую передают в имплементацию макроса).

Нифига наверное не понятно, поясню на датафлове, который примерно такой. Тайпчекер тайпчекает Apply(fun, args), и обнаруживает, что fun ссылается на reify. Тайпчекер говорит: окей, вот у меня есть global, я сейчас создам new Context(global). А потом возьму этот контекст и передам его метод reify_impl. reify_impl говорит: отлично, делаем import c.universe._ и создаем AST, соответствующие результату.

Все прекрасно до того момента, как мы захотим вернуть результат reify_impl и отдать его обратно в тайпчекер. Внезапно оказывается что тип результата - _1156.Tree forSome { val _1156: scala.reflect.api.Universe } (это он так выводится, тип результата мы, как водится, опустили), а тайпчекеру нужен global.Tree. В 2.9 это сигнал к кровавому угару кастов (угар этот и называется bakery of doom), но в 2.10 есть выход при помощи dependent method types.

В 2.10 сигнатура нашего reify_impl запишется вот как: "def reify_impl(c: Context)(input_tree: c.universe.Tree): c.universe.Tree". Отлично смотрится, что же мне еще надо? Сейчас посмотрим.

Во-первых, чтобы уломать компилятор на тему того, что c.universe.Tree это ни что иное как global.Tree, надо запретить ему делать widen для типа параметра c. Можно это сделать вот так: "def reify_impl[C <: Context with Singleton](c: Context)..." (если я ничего не путаю). Можно вот так: "val c = new Context { val universe: global.type = global }; reify_impl(c)(tree)". Многабукф.

Во-вторых, этот с приходится всюду таскать с собой. Не передашь ведь просто tree в хелпер-метод, так как надо будет в сигнатуре хелпер-метода сказать, какой именно это Tree, а то опять получится _1774.Tree forSome blah. По похожим соображениям для dependent methods не работает эта-конверсия (преобразование в функциональные типы). Снова неудобно - сильно обрезаются возможности по абстрагированию. Так и до копипаста недолго.

Наконец, вся эта машинерия в особо адовых случаях ломается и приходится идти в Types.scala и допиливать проверки isSubType. Я это сам не делал, просто тихо сидел в сторонке с большими глазами, пока Мартин колбасил. На любителя, короче.

К чему я все это? Мне очень нравится кейк паттерн (вон сейчас на питоне фигачу его же), но у него есть определенные границы применимости. Интересно узнать как их расширить. Цитируя Мартина: "We believe in power" :)

Date: 2012-06-10 11:06 pm (UTC)
From: [identity profile] ivan-gandhi.livejournal.com
А! Этот дум я неоднократно наблюдал пока перепирал аппликативы с МакБрайда и Патерсона.

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

А в реале не встречалось (близко проходил, но проскочил). Наверное, надо будет тот случай тоже осветить (сорсов с собой дома нету).

Date: 2012-06-11 01:51 am (UTC)
From: [identity profile] smalgin.livejournal.com
На уровне чайника, гаврюши и стремительного все понятно.

Profile

juan_gandhi: (Default)
Juan-Carlos Gandhi

June 2025

S M T W T F S
1 2345 6 7
8 9 10 11 121314
15161718 1920 21
222324252627 28
29 30     

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 1st, 2025 06:04 am
Powered by Dreamwidth Studios