Size: a a a

Compiler Development

2020 March 04

А

Алексей in Compiler Development
и передавать эту функцию как параметр в другую функцию будет проблематичнно
источник

А

Алексей in Compiler Development
хотя
источник

А

Алексей in Compiler Development
я думаю, что тут для каждой дженерик функции нужна мапа с ключами в виде фактических типов-параметров
источник

А

Алексей in Compiler Development
и значениями этой мапы будут сгенерированные функции
источник

M中

Mikhail 才藤 中村 Bashurov in Compiler Development
как параметр да, не получится
можно частично применить дженерик и передавать уже такую функцию
const foo = obj => validate<User>(obj)
источник

А

Алексей in Compiler Development
Алексей
и значениями этой мапы будут сгенерированные функции
но тогда ещё за именами надо следить
источник

А

Алексей in Compiler Development
потому что юзер может написать свою функцию с именем foo_User
источник

А

Алексей in Compiler Development
или
источник

M中

Mikhail 才藤 中村 Bashurov in Compiler Development
Алексей
я думаю, что тут для каждой дженерик функции нужна мапа с ключами в виде фактических типов-параметров
ну это детали реализации
у меня главный вопрос как решить в константное количество проходов проблему с
import { validate } from ‘my-module’

type User = { id: number }

function foo<T>(obj) {
 return bar<T>(bar)
}

function bar<T>(obj) {
 return validate<T>(obj)
}

foo<User>({ id: “1” })
источник

А

Алексей in Compiler Development
function foo<T>(value: T) {...}

превратить в
function foo(T, value) {...}
источник

M中

Mikhail 才藤 中村 Bashurov in Compiler Development
Алексей
потому что юзер может написать свою функцию с именем foo_User
я помимо сериализованного имени типа вставляю дополнительный gibberish
источник

А

Алексей in Compiler Development
Mikhail 才藤 中村 Bashurov
я помимо сериализованного имени типа вставляю дополнительный gibberish
даже так
источник

M中

Mikhail 才藤 中村 Bashurov in Compiler Development
Алексей
function foo<T>(value: T) {...}

превратить в
function foo(T, value) {...}
думал об этом, но вышеозначенной проблемы это не решает
источник

А

Алексей in Compiler Development
Mikhail 才藤 中村 Bashurov
ну это детали реализации
у меня главный вопрос как решить в константное количество проходов проблему с
import { validate } from ‘my-module’

type User = { id: number }

function foo<T>(obj) {
 return bar<T>(bar)
}

function bar<T>(obj) {
 return validate<T>(obj)
}

foo<User>({ id: “1” })
наверное надо делать что-то типа ленивости, то есть получать специализацию только для foo<User>, а внутри тогда для bar<User> и validate<User>
источник

M中

Mikhail 才藤 中村 Bashurov in Compiler Development
Алексей
наверное надо делать что-то типа ленивости, то есть получать специализацию только для foo<User>, а внутри тогда для bar<User> и validate<User>
внутри чего?
визитор бежит по файлу
видит foo c дженериком
пробегается по телу не видит вызова validate хотя видит вызов bar
видит объявление bar
ОПА видит в его теле вызов validate

НО
1. мы уже в теле функции в визиторе, а значит поменять саму функцию bar уже нельзя
2. нам надо поменять не только bar но и foo (и еще понять это)
3. а еще вызовы foo которые опять же могли находится выше ее объявления
источник

EM

Evgenii Moiseenko in Compiler Development
Mikhail 才藤 中村 Bashurov
я как раз и делаю по сути темплейты в ТС
вопрос зачем?
темплейты/дженерики - это два способа реализации параметрического полиморфизма.
Разница в том, что темплейты реализуют его с помощью мономорфизаци, т.е. как раз когда для каждого инстанса функции/класса под тип генерируется код.
В дженериках необходимости генерировать код под каждый инстанс просто нет, потому что все значения в рантайме имеют одинаковую структуру (в первом приближении все объекты — это просто указатели в кучу), и если программа протайпчекалась, то гарантируется что в рантайме уже не будет ошибок из-за несоответствия типов.
Собственно в C/C++ как и в Rust используются мономорфизация как раз потому что переменные зачастую передаются по значению и там как раз не гарантируется какое-то унифицированное представление в рантайме.
источник

А

Алексей in Compiler Development
Evgenii Moiseenko
вопрос зачем?
темплейты/дженерики - это два способа реализации параметрического полиморфизма.
Разница в том, что темплейты реализуют его с помощью мономорфизаци, т.е. как раз когда для каждого инстанса функции/класса под тип генерируется код.
В дженериках необходимости генерировать код под каждый инстанс просто нет, потому что все значения в рантайме имеют одинаковую структуру (в первом приближении все объекты — это просто указатели в кучу), и если программа протайпчекалась, то гарантируется что в рантайме уже не будет ошибок из-за несоответствия типов.
Собственно в C/C++ как и в Rust используются мономорфизация как раз потому что переменные зачастую передаются по значению и там как раз не гарантируется какое-то унифицированное представление в рантайме.
но тем не менее в расте дженерики, а не темплейты
источник

EM

Evgenii Moiseenko in Compiler Development
Алексей
но тем не менее в расте дженерики, а не темплейты
в расте трейты, которые реализуются через мономорфизацию, как и темплейты в С++
источник

EM

Evgenii Moiseenko in Compiler Development
т.е. под каждый инстанс генерируется код
источник

А

Алексей in Compiler Development
да, но семантика у них типичная для дженериков с параметрическим полиморфизмом
источник