Нашли или выдавили из себя код, который нельзя назвать нормальным,
на который без улыбки не взглянешь?
Не торопитесь его удалять или рефакторить, — запостите его на
говнокод.ру, посмеёмся вместе!
function main() {
let a: number | string;
a = "Hello";
if (typeof(a) == "string")
{
print("str val:", a);
}
a = 10.0;
if (typeof(a) == "number")
{
print("num val:", a);
}
print("done")
}
Аллилуйя братья... я вам принес "union"-s . Возрадуйтесь новой фиче. (А ты можешь так в с/c++?)
Было бы еще хорошо добавить нормальную реализацию tagged union-ов (как в Расте например). А не: type MySumType = { kind: 'a'; fieldA: string } | { kind: 'b'; fieldB: boolean } .
Они же пытались очень тонкую прокладку для проверки типов сделать, а не новый язык. Видимо поэтому и не могут добавить какие-то скрытые магические поля в структуры.
На уровне юзера - да. На уровне kernel-а ЖС - в общем случае tagged union (а вы как думали засчет чего динамическая типизация?). Но ведь ОП пилит конпелятор диалекта TypeScript в машинный код, там обычно принято не включать инфу о типе для встроенных типов.
function foo(a: int | float) {
console.log(a); // Не получается статически, насяльника.
// а теперь получается начальника
if (typeof(a) == "number") console.log(a); // мы знаем, что в коде после typeof(a) 100% number
}
foo(42);
foo(16.16);
Но мы же конпелятор пишем. И он может раскрыть этот оператор и заранее подставить его результат. Тогда в рантайме можно такую переменную ничем не обмазывать.
Тут главное в рантайме не дать string засунуть в этот number потом... Но я думаю это учтено.
Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?
В общем как я и сказал почти:
> говно в куче лежит, и динамически диспатчится по указателю
только с исключением на Number и Boolean (строка тоже в куче)
Документацию и пейперы лучше распостранять текстом. Если там очередное тикток видео на полтора часа, то оно не нужно
Ну да, буду щас копипастить простыню, вместо того чтобы сослаться на нее...
> Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?
Скорее структура, которая хранит char-тег и юнион из uint64 (= number), указателя на объект, булеана, view для строки (сама строка лежит в куче) и пр.
" говно в куче лежит, и динамически диспатчится по указателю" - это когда сами данные относящиеся к переменной, всегда хранятся в куче, а переменнная хранит лишь указатель на них не?
> Так что typeof можно получить довольно быстро, действительно. А вот за instanceof придется ходить в объект вероятно по указателю
Да, информация о классе/функции создавшей объект, хранится уже внутри объекта. Так впрочем ведет себя и Джава с Шарпом (иначе невозможна была бы рефлексия).
> если бы она была текстом, то проблем бы не было. Видео на полтора часа неприлично предлагать:)
По ссылке не только видео на полтора часа. Но ладно.
>Да, информация о классе/функции создавшей объект, хранится уже внутри объекта.
Угу. В JS есть типы boolean/string/итд/object, а уже object может быть инстансом класса. Информация о типе хранится прямо в юнионе, а о классе уже по ссылке
> Так впрочем ведет себя и Джава с Шарпом (иначе невозможна была бы рефлексия).
В C# есть value types структуры, их тип можно понять статически, но смысла в этом обычно нет.
И если переменная a и на уровне kernel-а number, то вызов typeof вообще не валидный с точки зрения компилятора (упадет компиляция либо вызов функции вернет черт знает что).
Судя по тому, что typeof - компайл-тайм конструкт, такое предположение возникло. Иначе что должно быть сгенерированно вместо typeof(a) внутри функции, если какого конкретно субтипа будет a в общем случае известно только в рантайме.
Или typeof от аргумента функции внезапно не компайл-тайм конструкт а оператор вычисляющий по магическому полю аргумента строковый литерал? Интересная механика...
Или даже так: если компилятор видит что функция вызывается только с небольшим числом вариантов аргумента, typeof вычисляется в компайл-тайме. И генерятся портянки функций. Иначе generic аргумент имеет тип tagged union-а и typeof - обычная функция, мапящая магическое поле на строку. Комбинаторного взрыва удается избежать.
if (std::string* p = std::get_if<std::string*>(&x)) { ... }
Скопипастим-ка эту портянку ещё 20 раз... Или у них boost preprocessor уже тогда работал?
Они же пытались очень тонкую прокладку для проверки типов сделать, а не новый язык. Видимо поэтому и не могут добавить какие-то скрытые магические поля в структуры.
Это касается только проверки типов. В результирующем JS ничего этого нет
let a: number = 4;
typeof(a);
З.Ы. Если их тип статически известен, конечно. Из void* он тип уже не вытрясет.
Проблема ведь с оптимизацией, когда ты точно знаешь тип и для экономии памяти и тактов выбрасываешь всю рантайм инфу о нём.
Конкретной реализации ASD конечняо ничего не мешает
function foo(a: int | float) {
console.log(a); // Не получается статически, насяльника.
// а теперь получается начальника
if (typeof(a) == "number") console.log(a); // мы знаем, что в коде после typeof(a) 100% number
}
foo(42);
foo(16.16);
Тут главное в рантайме не дать string засунуть в этот number потом... Но я думаю это учтено.
мы думали, что там говно в куче лежит, и динамически диспатчится по указателю
Этоже только в TS ты можешь скзаать
а в JS этого знания нет.
алсо, как там хранится строка?
enum Variable {
Number(uint64),
String{ length: int64; begin: *char },
Object(*void),
Boolean(bool),
// ...
}
На самом деле встроенных "типов" (различающихся по memory layout в т.ч.) больше
https://v8.dev/blog/elements-kinds
Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?
В общем как я и сказал почти:
> говно в куче лежит, и динамически диспатчится по указателю
только с исключением на Number и Boolean (строка тоже в куче)
Документацию и пейперы лучше распостранять текстом. Если там очередное тикток видео на полтора часа, то оно не нужно
> Или всмысле там юнион из uint64в котором может быть number, указатель на объект, bool, и указатель на строку с длиной на перевес?
Скорее структура, которая хранит char-тег и юнион из uint64 (= number), указателя на объект, булеана, view для строки (сама строка лежит в куче) и пр.
" говно в куче лежит, и динамически диспатчится по указателю" - это когда сами данные относящиеся к переменной, всегда хранятся в куче, а переменнная хранит лишь указатель на них не?
если бы она была текстом, то проблем бы не было. Видео на полтора часа неприлично предлагать:)
>Скорее структура
Ну да, я понял: у нас есть 64 бита, в них мы храним булен, намбр, указатель итд, смотря что за сущность у нас.
Так что typeof можно получить довольно быстро, действительно. А вот за instanceof придется ходить в объект вероятно по указателю
Да, информация о классе/функции создавшей объект, хранится уже внутри объекта. Так впрочем ведет себя и Джава с Шарпом (иначе невозможна была бы рефлексия).
> если бы она была текстом, то проблем бы не было. Видео на полтора часа неприлично предлагать:)
По ссылке не только видео на полтора часа. Но ладно.
Угу. В JS есть типы boolean/string/итд/object, а уже object может быть инстансом класса. Информация о типе хранится прямо в юнионе, а о классе уже по ссылке
> Так впрочем ведет себя и Джава с Шарпом (иначе невозможна была бы рефлексия).
В C# есть value types структуры, их тип можно понять статически, но смысла в этом обычно нет.
Превращается перед компиляцией в байт-код во что-то типа:
(как с плюсовыми шаблонами примерно)
Т.е. например функция принимает int|string, мы в неё передаём int, но она внутри в эту переменную ложит string.