185 похожих чатов

А, стоп, дублирование-то зачем?

17 ответов

60 просмотров

Ну потому что из-за того что тип аргумента разный функция дальше будет по-разному компилироваться и соотвественно без дублирования тела функции не обойтись

TOV_MULTIMASSO- Автор вопроса
Богдан
Ну потому что из-за того что тип аргумента разный ...

Инстанцирование делает то же самое, в общем-то.

TOV_MULTIMASSO
Инстанцирование делает то же самое, в общем-то.

Это да, но вот хотелось бы иметь такое же инстанциирование и для return-пути. Сейчас в С++ запрещается возвращать из функции (по рантайм-условию) разные типы (которые никак не связаны между собой) auto func(){ if(rand() % 2){ return A{}; } else { return B{} } } struct A { int field; } struct B { double field; int field2; } а если компилятор будет делать под капотом вот такое преобразование тела функции auto res1 = func(); auto res2 = func(); auto result = process(res1, res2); в имплисит-лямбда-коллбек func([](auto res1){ func([](auto res2){ auto result = process(res1, res2); }); }); ну а в самой функции return будет трансформирован в вызов лямбда-функции auto func(auto fn){ if(rand() % 2){ fn(A{}); } else { fn(B{}); } } то этот лямбда-коллбек дальше будет проинстанциирован отдельно для структуры A и структуры B (которая никак не связана с A) И в результате код продолжит работать с конретным типом и мы реализовали в языке поддержку (как я понимаю довольно уникальной киллер-фичи) возможности возвращать из функции разные типы/классы/структуры по рантайм-условию

TOV_MULTIMASSO- Автор вопроса
TOV_MULTIMASSO
screenshot Что-то такое имеется ввиду?

не совсем, тип возрата должен не зависеть от параметра а возвращаться из функции по рантайм условию например struct A {...}; struct B {...}; auto foo(){ if(rand() % 2){ return A(); } else { return B(); } } то есть если в результате вызова функции rand() было получено случаное число которое делится на два то функция foo() возвращает структуру A а иначе возвращает структуру B

TOV_MULTIMASSO- Автор вопроса
Богдан
не совсем, тип возрата должен не зависеть от парам...

Так, падажжи. Как это тогда в сигнатуре функции-то записать? data Either e a = Left { left :: e } | Right { right :: a } foo :: Int -> Either String Int foo x = if odd x then Right x else Left "not odd" Так?

TOV_MULTIMASSO
Так, падажжи. Как это тогда в сигнатуре функции-то...

я не знаю как записать в сигнатуре, мне кажется весь смысл вывода типов в том чтобы не нужно было писать сигнатуру а тип возврата функции выводился автоматически. И суть этой киллер-фичи которую я пытаюсь объяснить заключается в том что если функция возвращает разные типы по рантайм условию то они не будут боксится в различные полиморфные обертки, вместо этого весь последующий код будет работать с конкретным статическим типом

TOV_MULTIMASSO- Автор вопроса
Богдан
я не знаю как записать в сигнатуре, мне кажется ве...

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

TOV_MULTIMASSO- Автор вопроса
Богдан
я не знаю как записать в сигнатуре, мне кажется ве...

И кроме того различить ситуацию со структурами A и B после rand() по возврату из функции будет невозможно.

Возможно, в этом и суть этой фичи которая похожа на "продолжения" или CPS-like трансформации. Компилятор просто возмет код который работает с результатом функции auto main(){ auto result = func(); process(result); } и переделает его в передачу имплисит лямбда-коллбека и в теле самой функции вместо return будет вызван этот лямбда-коллбек auto main(){ func([](auto result){ process(result); }); } auto func(auto fn){ if(rand() % 2){ fn(A{}); } else { fn(B{}) } } Ну а дальше компилятор будет делать так называемое инстанциирование этой лямбды - то есть для каждого типа аргумента продублирует тело функции и для каждой копии функции будет выведен свой тип аргумента auto main(){ func([](auto result){ process(result); }); } auto func(auto fn){ if(rand() % 2){ fn(A{}); //process(A{}) } else { fn(B{}) //process(B{}) } } И таким образом несмотря на то что мы возвращаем из функции разные типы по рантайм условию - для каждой возможной ветки выполнения последующий код программы будет работать со своим конкретным типом без боксинга в полиморфную обертку

TOV_MULTIMASSO- Автор вопроса
Богдан
Возможно, в этом и суть этой фичи которая похожа н...

Мы вызываем в какой-то функции func 5 раз, у нас 32 копии объемлющей функции. А, ещё одна проблема — код, следующий за вызовом func, как он будет работать с разнородными результатами func?

TOV_MULTIMASSO- Автор вопроса

я ниасилил

TOV_MULTIMASSO- Автор вопроса

a = func() код, работающий с `a` - как один и тот же код может обработать `int` и `struct B`, например?

TOV_MULTIMASSO
a = func() код, работающий с `a` - как один и тот...

Надо полагать, он и дальше будет заворачиваться, пока требующих того расхождений не останется.

TOV_MULTIMASSO
a = func() код, работающий с `a` - как один и тот...

ну если у них общий интерфейс (например у struct B есть перегружены математические операторы) - то вполне может. Ну а если нет то тогда будет ошибка компиляции. То есть последующий код должен работать с результатом как будто с пересечением типов но сам тип он будет статически выводиться без полимфорного боксинга

Богдан
Возможно, в этом и суть этой фичи которая похожа н...

Кажется Вы здесь смешиваете систему типов и рантайм семантику. Кажется если использовать обычные A | B, то семантически получится тот же самое. За исключением перфа, конечно, но он не имеет отношения к типизации. Вы можете привести пример, который возможен под Вашим предложением, но не будет работать с юнионом(с очевидными расширениями для их поддержки)?

Владислав Катасонов
Кажется Вы здесь смешиваете систему типов и рантай...

Ну если отбросить аспект производительности и представить что под капотом все работает через структурную полимофность (как динамические языки) то в принципе можно представить эту фичу как то что результат возврата функции (которая возвращает разные типы по рантайм-условию) будет выводиться как пересечение A | B. Но все же в статически-типизированном языке хочется иметь именно статические типы а не полиморфные обертки которые сильно снижают производительность. И вот среди таких статически-типизированных языков я еще не разу не встречал эту фичу когда можно возвращать разные типы по рантайм-условию и дальше можно работать с результатом и мы будем статически обращаться к полям полученного объекта максимально быстро (чтение по конкретному смещению)

Похожие вопросы

Обсуждают сегодня

а через ESC-код ?
Alexey Kulakov
29
30500 за редактор? )
Владимир
47
Чёт не понял, я ж правильной функцией воспользовался чтобы вывести отладочную информацию? но что-то она не ловится
notme
18
У меня есть функция где происходит это: write_bit(buffer, 1); write_bit(buffer, 0); write_bit(buffer, 1); write_bit(buffer, 1); write_bit(buffer, 1); w...
~
13
Недавно Google Project Zero нашёл багу в SQLite с помощью LLM, о чём достаточно было шумно в определённых интернетах, которые сопровождались рассказами, что скоро всех "ибешни...
Alex Sherbakov
5
program test; {$mode delphi} procedure proc(v: int32); overload; begin end; procedure proc(v: int64); overload; begin end; var x: uint64; begin proc(x); end. Уж не знаю...
notme
6
Как передать управляющий символ в открытую через CreateProcess консоль? Собсна, есть процедура: procedure TRedirectThread.WriteData(Data: OEMString); var Written: Cardinal;...
Serjone
6
Вот еще странный косяк, подскажите как бороться. Я git clone сделал себе всего embassy и примеры там запускаю. Всё хорошо. Но вот решил в cargo.toml зависимости не как в приме...
Lukutin R2AJP
1
вы делали что-то подобное и как? может есть либы готовые? увидел картинку нокода, где всё линиями соединено и стало интересно попробовать то же в ddl на lua сделать. решил с ч...
Victor
8
Ребят в СИ можно реализовать ООП?
Николай
33
Карта сайта