На мой взгляд, говоря о реалистичности видео на разных частотах, не нужно скатываться в дискретный способ мышления и говорить только об fps. Дискретные эффекты покадровой съемки (особенно с малой выдержкой) дают причудливые стробоскопические эффекты на вращающихся колесах, лопастях, спицах и т.д. А недавно в инете ходило видео с камеры наблюдения где какая-то птичка летала не поднимая крыльев. Я бы сказал что нужно рассуждать в интегральных терминах. Рецепторы в глазу человека имеют определенную инертность (как на зажигание так и гашение сигнала), поэтому быстро двигающийся объект (например летающий на темном фоне белый кружок) будет восприниматься размазанным пятном. Длинна этого пятна будет зависеть от таких параметров как скорость движения, условия освещенности и т.д. Так вот, на видео длинна этого пятна не должна зависеть от fps. Образно говоря, на высоких fps может потребоваться длина выдержки больше чем 1/fps. Иначе начнутся стробоскопические эффекты, которые придется трактовать как «художественный замысел режисера». Но это не тоже самое что реализм…
Мне нужно в структуре файла иметь описание всех используемых структур c полями (имена и типы) в строковом виде. Хорошо бы по аннотациям вытягивать доп инфу (например, toltip info).
Да, но мне нужно в структуре файла иметь имя и тип в строковом виде, поскольку там сначала описание структуры а потом данные. Иначе редактор не сможет понять что куда можно добавить (sub-objects, array itmes). Плюс в файлах не нужны версии, при десериализации лишние поля игнорируются, а недостающие остаются default initialized.
Ай, поторопился, извините. Не та функция. Давайте попробуем еще раз с пояснениями. Класс для сериализации:
interface Slzr {
fun get_Slzr_Decl() : Array<Any?>
}
class MyClass : Slzr {
companion object static {
val slzr : Array<Any?> = arrayOf<Any?>(::MyClass, MyClass::class.simpleName, 7, arrayOf<Any>(MyClass::br, MyClass::fr))
}
var br = 777;
var fr = "rrrr";
override fun get_Slzr_Decl() : Array<Any?> = slzr;
}
Сериалайзер обнюхивает этот класс примерно так:
var t : MyClass = MyClass()
var sd = t.get_Slzr_Decl();
@Suppress("UNCHECKED_CAST")
var obj = (sd[0] as KFunction0<Any>)();
var a : Array<*>? = sd[3] as? Array<*>;
if(null!=a) {
for(i in a.indices) {
if(a[i] is KMutableProperty1<*,*>) {
@Suppress("UNCHECKED_CAST")
var pi = a[i] as? KMutableProperty1<Any, *>;
if(null!=pi)
println("member: " + pi.name + " = " + pi.get(t as Any));
}
}
}
Здесь просто печатается имя и значение полей заданных для сериализации, но в реальной жизни парсер генерирует вспомогательные данные (HashMap с именами) для ускорения процессов save/load из промежуточного представления сериализуемых данных, кеширауя их в статическое поле slzr. Ну и вспомогательная переменная t должна инстанциироваться не так явно, а через тип. Надеюсь так чуть понятнее.
class MyClass : Slzr
{
companion object static
{
val slzr : Array<Any?> = arrayOf<Any?>(::MyClass, MyClass::class.simpleName, 7, arrayOf<Any>(MyClass::br, MyClass::fr))
}
var br = 777;
var fr = "rrrr";
override fun get_Slzr_Decl() : Array<Any?> = slzr;
fun reg_internal(vararg p: Any)
{
// for(i in p.indices)
for(i in 0 until p.size)
{
if(p[i] is KMutableProperty0<*>)
{
var pi = p[i] as KMutableProperty0<*>;
// var v = pi.get();
if(pi.get() is Int)
{
@Suppress("UNCHECKED_CAST")
pi = p[i] as KMutableProperty0<Int>;
pi.set(111);
// v = pi.get();
print("Int:\t");
}
else
if(pi.get() is String)
print("String:\t");
println("p[" + i + "] = " + pi.name + " -->" + pi.get());
}
else println("p[" + i + "]")
}
}
А что бы на Kotlin сериализовать без рефлексии, надо сначала все переложить в промежуточную структуру, а это дополнительный код с возможными опечатками. Ну там еще есть вариант с инстанциированием воспомогательного объекта и использованием массива вида [MyClass::field_a, MyClass::field_b...], что тоже не фонтан…
Use-case такой: сериализация идет в строго типизированную структуру данных, которую потом можно редактировать своим универсальным редактором (что-то вроде иерархического object-inspector). Формат может быть любой, (например JSON или бинарный). Сначала идет описание структуры (с возможностью пропускать), потом данные. К объектам это применяется (читается и пишется) через промежуточное представление, ориентируясь на имя и тип поля. Это позволяет гибко добавлять/удалять поля класса во время разработки (за номерами версий в файле следить не нужно). Чуть не забыл, в классе поля для сериализации нужны далеко не все.
Потыкав палочкой в Kotlin я увидел недоделанный долгострой. Первое что обнаружил: кросс-платформенный Reflect API отсутствует, хотя который год обещают.
Классический «for(;;)» убит (лучше бы убили «while» и «do/while»). Некоторые вещи пишутся громоздко.
Когда 8 лет назад kotlin появился, он был похож на еще один backend для JVM. Синтаксис и грамматика со своими причудами и ключевыми словами (it, reified и т.п.), местами на пару букв короче чем в Java, местами длиннее. Странные решения, вроде отмены традиционного синтаксиса for(;;). По своему опыту могу сказать что циклы while и do{}while обычно вообще не используются, так как for(;;) самодостаточен. Вместо static members в kotlin классы двух видов: только static (это называется Object) и только не-static. Если в классе нужно и то и другое, встраиваем один класс в другой как companion (ему еще можно задавать имя, случайно не знаете зачем?). Если статический member один, то конструкция выгляди пухловато. Объявление объектов с динамическими полями в стиле JSON выглядит пухловато, в перемешку со строковыми «mutableListOf» и «mutableMapOf». Ну да на самом деле все это мелочи…
В какой то момент начались таргетинги на разные платформы: JVM, JS, LLVM. Появился соблазн иметь общую кодовую базу, но… Java, JS, C# по отдельности имеют не плохой RTTI (run-time type information), это позволяет писать свои сериализаторы и прочие reflect полезные штуки. В kotlin уже который год видим ошибки вида: «error: unsupported [This reflection API is not supported yet in JavaScript]».
Я понимаю что не всем это надо, но если проект чуть сложнее чем HelloWorld, то начинаются печали…
Так то, да. Язык не предназначен для исполнения в JS среде. Но раз уж речь зашло про wasm, то просто стало интересно чем wasm лучше js. Компилятор go2js гуглится (правда не официальный AFAIU)
Сериалайзер обнюхивает этот класс примерно так:
Здесь просто печатается имя и значение полей заданных для сериализации, но в реальной жизни парсер генерирует вспомогательные данные (HashMap с именами) для ускорения процессов save/load из промежуточного представления сериализуемых данных, кеширауя их в статическое поле slzr. Ну и вспомогательная переменная t должна инстанциироваться не так явно, а через тип. Надеюсь так чуть понятнее.
Классический «for(;;)» убит (лучше бы убили «while» и «do/while»). Некоторые вещи пишутся громоздко.
Для HelloWorld работает хорошо. В прод не катит.
В какой то момент начались таргетинги на разные платформы: JVM, JS, LLVM. Появился соблазн иметь общую кодовую базу, но… Java, JS, C# по отдельности имеют не плохой RTTI (run-time type information), это позволяет писать свои сериализаторы и прочие reflect полезные штуки. В kotlin уже который год видим ошибки вида: «error: unsupported [This reflection API is not supported yet in JavaScript]».
Я понимаю что не всем это надо, но если проект чуть сложнее чем HelloWorld, то начинаются печали…