Pull to refresh

Comments 34

Пеши исчо. Если будут вопросы по scala-meta — пиши, мы с Женей теперь почти соседи 8-)

Спасибо! Обязательно напишу про работу с мета.
Какое приятное соседство у тебя)
2 вопроса:
1) размер базы
2) коммерческая версия или бесплатная

Можно в личку, интересуюсь потому что сам использую. Возможен обмен опытом при возникновении незапланированных ситуаций. (Были такие на моей памяти)

У меня сейчас:
Один из Namespace — ов
Master Objects: 2.278 G
Disk Used: 2.764 TB
Mem Used: 271 GB
Версия бесплатная.
Если будут вопросы пишите, конечно, обмен опытом всегда на пользу!
1) можем держать 2,5 тб
2) бесплатная
А разве нельзя было то же самое на shapeless зарядить с автоматическим выводом тайп-классов?
Там еще были бы и рекорды из коробки
Привет! Я постаралась объяснить в гисте https://gist.github.com/DanyMariaLee/2774f10e64e6aaff2e855061aa74a16c
Если что-то не достаточно ясно, могу развернуть еще или отправить к литературе соответствующей
Ммм. Немного некорректно дано определение вывода.

Автоматический вывод тайп-классов — это фактически вывод тайп-класса для некого типа `T` на основе уже имеющейся информации. Например, если у вас описаны тайп-классы для примитивов, можно вывести через LabelledGeneric для кейс-классов. А через копродукты еще и для трейтов.

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

Возьмем, как пример, библиотеку circe для работы с JSON. Есть множество энкодеров/декодеров для примитивов из коробки. На основе этих энкодеров в circe есть дженерик для автоматического вывода энкодеров для любых классов (если есть необходимый). Т.е. в вашем кейсе достаточно было один раз описать свои энкодеры для необходимых примитивов и дальше использовать их сколько душе угодно. И никакого абуза макросов.

Евгений говорил, что холивар на тему, когда использовать type level программирование, а когда — макросы, может длиться очень долго. Но основная мысль — макросы нужны там, где у нас реальный кодоген и мы пишем сложные деревья. По-крайне мере, в большинстве крупных проектов они так и работают.

Для L-уровня имхо лучше использовать type level подход просто по той причине, что это сопровождать будет проще.
Я хотела дифференс выделить максимально ярко, но вижу Вы и без того все поняли.

В холиварах я не мастер и спорить на тему эту смысла не вижу. В любом инструменте главное применение, будь это язык или какая-то его особенность/библиотека.
У макросов достаточно вариантов использования, каждый выбирает свой в зависимости от задачи. Тут же тоже вопрос удобства возникает: вам надо подняться с первого этажа на пятый — можно пешком, можно на лифте.
1) Реализация на уровне типов в скале возможна далеко не всегда. К сожалению сейчас эта система типов не тьюринг полная.
2) Помимо функциональных различий есть еще различия в производительности. Обобщенное программирование всегда будет выливаться в вызов виртуальных методов.

А в целом да, холиварная тема.

з.ы. цирцея все-таки с макросами живет.
К сожалению сейчас эта система типов не тьюринг полная.

Разве? Кажется вполне полная. Даже доказательства гуглятся, например.

Производительность надо замерять. Виртуальные методы — еще не самое худшее — jvm умеет девиртуализовать их. Но вот глубина стека растет, что сказывается на инлайне и приминимости оптимизаций.
Если правильно помню, то в этом было одно из основных отличий DOT. Пойду перепроверю.
AFAIR в circe макрос только для проверки, что можно вывести энкодер. А сам вывод на старом добром shapeless
Подскажите, пожалуйста, какую собственно проблему вы решали? Если уж вы взялись писать предметную статью, а не просто про макросы, то наверное стоило написать, вот стандартный api клиента аэроспайка предоставляет вот такой способ положить вот такое вот значение, это неудобно потому что нам нужно здесь передавать вот это и вот это, создавать то и то. Давайте попробуем упростить использование с помощью скала (или: сделаем удобный для использования из scala dsl, решающий эти проблемы), мы выбрали использование макросов, так как все остальные (нормальные) способы (вот такие..) мы исчерпали и они оказались неудобными/слишкоммедленными/подставьсвоё. Тогда нам ничего не оставалось как написать кодогенерацию, что позволило нам то и то.

Сейчас же статья выглядит так: я решила поиграться с макросами скалы и написала кучу совершенно нечитаемого кода, чтобы решить сама не знаю какую точно задачу, но я о ней думаю как «впереди довольно много однотипных преобразований. Писать все это руками каждый раз желания нет.» Хочу заметить, что вполне возможно получившееся решение действительно решает какую-то проблему и даже возможно это действительно лучший способ решения этой проблемы, но из статьи этого понять невозможно, а разобраться в исходниках сложно даже имея некоторое желание — во многом как раз из за использования макросов (а совсем не потому, что из комментариев есть только имя автора).

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

Все там читаемо.
И на 100% процентов уверен, что на _ЛЮБОМ_ языке, который человеку не знаком, можно найти такой пример, что у субъекта прикипит и он начнет исходить слюнями. От асма до name-yourself.

Макросы в скале в текущей реализации — это экспоуз компилятор наружу, за что их не особо любят (это же, о боже, надо понимать, что такое Expr и Tree!).
Позже появились квазицитаты, стало попроще. Сейчас пилят scala-meta, там все радужно и с пони.

Но меня всегда умиляло, как вылезают такие уникумы, и на абстрактных примерах использования макросов или type level программирования составляют суждение о языке как таковом. Это все равно что о крестах судить через призму шаблонов. Пфф
Тоесть по основной мысли моего комментария возражений нет?
У вашего комментария была мысль?
А вы считаете, что есть смысл писать комментарий, если в нем смысла? Даже если в саму эту мысль закралось противоречие?
Я лишь задал вопрос о том, какую проблему решает кодогенерация (пожалуй что слишком резко, за что уже принес извинения ниже). Из дальнейшего общения ответа на этот вопрос я так и не смог получить, если вы на 100% поняли этот код, можете в двух словах рассказать, зачем нужна кодогенерация в этой библиотеке?
Я понимаю Ваше замешательство. Цель статьи была показать, как макросы могут облегчить разработку.
Насчет кода самой библиотеки — комментарии были вынесены мной в отдельную директорию специально, потому как на мой взгляд легче читать код, не отвлекаясь на текст. В кукбуке https://github.com/TinkoffCreditSystems/aerospike-scala/tree/master/cookbook я подробно описала, как именно использовать на примерах, максимально наглядно. Уверена, прочитав примеры и мое разъяснение вот тут https://gist.github.com/DanyMariaLee/2774f10e64e6aaff2e855061aa74a16c, часть, а может и все вопросы исчезнут.

Если после прочтения останутся вопросы я буду рада на них ответить и помочь Вам разобраться.
Я прошу прощения, предыдущий комментарий был чрезмерно резкий, но по существу мне осталось непонятным какой профит планировался по сравнению с обычным клиентом. Я почитал описание по ссылкам, там подробно описано устройство и использование, но не совсем понятно, какую чистую выгоду мы получаем используя этот дсл, какой именно бойлерплейт код призван убрать этот проект? Я использовал java client и не припомню никаких особых проблем с переиспользованием кода. Так что если у вас найдется время ответить на этот вопрос, было бы очень интересно этот ответ услышать.
Все в порядке, извинения приняты)

Если коротко, у нас база, в которую можно положить что угодно любого типа. java client возвращает некий Record, в котором лежит интересный нам Map<String, Object>. Тип, конечно, съедобный, но не вкусный, согласитесь? Мне нравится возможность положить в одном месте в базу HList или case class Human и потом в любом другом месте (сервиса, приложения) его достать. То есть получить именно тот HLIst/Human, который я сохранила.
Тут вы скажете, как же это мы получим и где гарантии? Гарантий нет. Как и в любом другом случае нет такой силы во Вселенной, которая могла бы помочь Вам или мне, или кому-то еще контролировать, что/как еще кладется по нашему ключу ВНЕ приложения. Но. Данная библиотека помогает, делая максимум работы за нас, позволяя нам в случае неприкосновенности без нашего ведома данных (то есть Вася, сидящий в соседнем отделе, не решит взять и переписать именно Ваш сэт и сохранить там вместо информации по книгам в библиотеке свою любимую песенку в любом доступном его фантазии виде) получить желаемый тип.
Пользуясь этой оберткой Вы пишете грубо говоря:

def saveBook(b: Book): Future[Unit] = ???
def getBook(k: String): Future[Book] = ???

и не разбираете сами руками как там внутри этого драйвера сохранена Ваша книга. Конечно, зная значение ключа.

Я думала уже над тем, как обезопасить свои данные от Василиев всех мастей, вероятно можно посмотреть на настройки в самом Аероспайке и определенному пользователю выдавать права на тот или иной сет. В коде библиотеки в таком случае можно будет описать дополнительные настройки для служебных объектов (типа Writer и тп). В доработках уже достаточно большой список «хотелок» и если Вы работаете на scala с Аероспайком Ваши пожелания мне интересны и будет здорово, если Вы запишите их в issues.

Хорошо, нам для хранения абстрактно любого типа достаточно сериализовать значение и записать его по ключу. Как сериализовать это второй вопрос, можно в джейсон и в строку, можно в бинарный формат, можно свой написать который будет значения по мапе размазывать, в любом случае готовых решений много. Сложности связаны с тем, что аэроспайк ориентирован в первую очедь на хранение в более «колоночном» виде. Но никто не мешает хранить весь объект в одном bin-е в виде массива байт. Обертка для такой сериализации насколько я могу себе представить не требует какой-то кодогенерации. Именно это меня и сбивает с толку — я не могу понять, для чего в итоге используется кодогенерация.

Хорошо. Вы предположим Джейсон руками разбираете или подключаете что-то чтоб "само" разобралось?
Это то самое, что сделает само, но для данной базы.

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

Какой именно момент Вы хотите описать при помощи готового решения? Что это за решение будет?

Сериализацию, видимо. Я как раз и пытаюсь понять для чего же здесь используется кодогенерация. Хотя я посмотрел на сериализацию для кейз-классов и она всё равно сделана через рефлекшн. А это как раз то место, где можно было бы использовать макросы для скорости работы. Но если не для этого, тогда для чего же она используется?
Если посмотрите чуть внимательнее, заметите, что этот код вызывается внутри макросов.
Я был бы очень благодарен вам, если бы вы прямо ответили на мой вопрос о том, какую полезную работу в этом коде делают макросы. Или скажите, что не будете этого делать, чтобы я уже перестал доставать вас этим вопросом.

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

Во всех предыдущих комментариях изложено все, включая последний мой ответ про рефлекшен (Вы посмотрели внимательно, надеюсь).

Но назвать то место, которое стало лучше от использования макросов, вы всё-таки не можете?
Тот факт, что Вам не довелось работать или разобраться с макросами

Почему вы сделали такой вывод? Я этого не говорил.
не означает, что против их использования надо выступать.

Я ни одним своим комментарием не выступал против использования макросов, лишь написал, что такая кодогенерация — это крайняя мера, когда уже другие способы испробованы. Потому что читабельность такого кода сильно падает. А поддержка со стороны ide вообще близка к никакой.
Зря удалили комментарий

В каком смысле? На хабре нельзя удалить комментарий, насколько мне известно.

Вот я комментарий не увидела, а Вы — информации в написанном тексте.
Повторять очевидные вещи утомительное занятие, ответы на все вопросы есть и местами не по одному разу в разных формах. Одного комментария про рефлекшен более, чем достаточно, чтобы удовлетворить даже самого некомпетентного человека. Но так как я невероятно терпелива и это блог компании, а не мой, попробую объяснить ещё один раз (числительное — ключевое слово).
Основная идея этой библиотеки в том, чтобы пользователь не задумывался о внутренней структуре данных аероспайка и о том, как из пришедших к нему данных вытащить искомое. Также не должен размышлять, как эти данные хранить, это тоже продумано за него. Плюс рефлексии в макросах достаточно понятен (очень надеюсь, что это так), также важно, что код для различных типов как скажем в шэйплиссе писать не надо, все имплиситные врапперы сгенерируются сами "по требованию" — то есть именно те, которые Вы намерены использовать, а именно: если Вы напишете, что ваш бин "some s" — будет сгенерирован только один инстанс враппера, один, а не сто (числительное тут не конкретное, это просто утрирование, хотя по сути, при написании подобной библиотеки можно убить достаточно много времени, прописывая все типы, о чем прекрасно написано в гисте, который я написала в самом начале — посмотрите ещё разок на пример под номером один, и если все ещё не будет понятен профит — посмотрите ещё два раза).
Если Вам все ещё не понятно прошу не писать тут больше комментариев, потому что весь скаловый букварь в приложении к этой статье совершенно не нужен.

Запихать все в один бин можно, но лишь в части кейсов. Таким образом вы лишаетесь возможности создавать вторичные индексы по части данных и доставать из базы лишь часть данных. Я надеюсь, что библиотека все же ориентируется на универсальное использование. Иначе смысла в этом действительно нет.
Sign up to leave a comment.