LINUX.ORG.RU

Так же как и с template.

invy ★★★★★
()
Ответ на: комментарий от yetanother

Компилятор D прекрасно понимает, что если из функции может вернуться и значение типа long и значение типа double, то типом результата должен быть именно double.

Вы это преподносите как достоинство, а я вижу недостаток. Разве неявный каст с возможной потерей точности это хорошо?

andalevor ★★★
()
Ответ на: комментарий от andalevor

Да, я уже выше писал, что привел неудачный пример. Я имел в виду, что компилятор может вывести общий тип. А то, что для long и double он вывел double общим типом это не комильфо. Поведение С++ в этом случае мне больше нравится.

yetanother ★★
()
Ответ на: комментарий от Lzzz

Там компилятор, и он делает машинный код. А теперь расскажи как получить двоичный код функции без знания типов?

struct S
{
   virtual ~S() = default;
   virtual void f() = 0;
};

void h(S& s) { s.f(); }

Ой-вей, как же получить двоичный код для h, не зная, ссылку на какой тип передадут???

anonymous
()
Ответ на: комментарий от anonymous-angler

Ну так же и в лиспе и других динамических языках. Есть только один тип [значений]. И несколько классов [значений] («класс» не обязательно в о-о-пе смысле).

Когда нужна операция, которая реализована только в одном или нескольких классах, но не во всех, кастуют к этому классу а-ля dynamic_cast.

anonymous
()
Ответ на: комментарий от anonymous

Ну например

─< command 1 >─
utop # let hh = Hashtbl.create 10;;
val hh : ('_weak1, '_weak2) Hashtbl.t = <abstr>
─< command 2 >─
utop # Hashtbl.add hh 1 "one";;
- : unit = ()
─< command 4 >─
utop # #show hh;;
val hh : (int, string) Hashtbl.t

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko
─< command 1 >─
utop # let hh = Hashtbl.create 10;;
val hh : ('_weak1, '_weak2) Hashtbl.t = <abstr>
─< command 2 >─
utop # Hashtbl.add hh 1 "one";;
- : unit = ()
─< command 4 >─
utop # #show hh;;
val hh : (int, string) Hashtbl.t

что это за куча мусора?

anonymous
()
Ответ на: комментарий от anonymous

Это то, что бы было, если бы C++ имел type inference. Как если бы этот код был валидным:

#include <unordered_map>

int main() {
   auto hh = unordered_map();
   hh.insert(1, "one");
}

И, с точки зрения компилятора, эквивалентным этому:

#include <unordered_map>

int main() {
   unordered_map<int, const char*> hh;
   hh.insert(1, "one");
}
anonymous-angler ★☆
()
Ответ на: комментарий от kawaii_neko

Все случаи. Изучи букварь. Почти весь язык может выполняться в компилтайме, а компилтайм-логика может управлять выводом типов, может порождать типы и т.д.

Таким образом подстановка есть только в твоей бездарной скриптухе.

anonymous
()
Ответ на: комментарий от anonymous-angler

а что должно происходить в этой ситуации:

srand(time(0));

auto hh = unordered_map();

if (rand() % 2 == 0) {
  hh.insert(1, "one");
}
else {
  hh.insert("one", 1);
}
anonymous
()
Ответ на: комментарий от anonymous

Ничего не произойдёт, да и никакого unordered_map, auto и прочего в скриптухе существовать не может. Твоя вопрос обезьяне не имеет смысла.

К тому же с TЗ скриптухи это не так работает. Скриптуха не полиморфна и не учитывает значения тайп-аргументов.

Поэтому с ТЗ скриптухи существует только unordered_map, а никаких int, string - там не существует.

Для предотвращения подобной поплавы существует другой чекер, который проверяет, чтобы все уточнения типа были одного типа. Поэтому в первом случае у тебя будет уточнение для key - int. Для второго string и чекер попросту отвалится.

На какую-либо вложенность этому говне насрать.

anonymous
()
Ответ на: комментарий от anonymous

а что должно происходить в этой ситуации:

В F# в этом случае будет ошибка компиляции именно на строчке с else:

let mutable students = Map.empty
if true then
    students <- students.Add (1, "one")
else
    students <- students.Add ("one", 1) // обе ошибки на эту строчку
//  Ошибка FS0001 В данном выражении требовалось наличие типа
    "int"    
, но получен тип
    "string"

//  Ошибка FS0001 В данном выражении требовалось наличие типа
    "string"    
, но получен тип
    "int"
fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

а как же type inference? в половине случаев должен быть один тип, а в половине другой. почему компилятор не может вывести тип?

anonymous
()
Ответ на: комментарий от anonymous

Конкретно в данном случае hh.insert(1, "one"); встречается раньше, поэтому hh - unordered_map<int, const char*> и блок else содержит ошибку. Есть случаи, когда компилятору вовсе не ясно какой тип должен быть (Циклическая зависимость), тогда он требует указать его вручную.

anonymous-angler ★☆
()
Ответ на: комментарий от anonymous

нет, ты не понял, в половине случаев должен возвращаться map<int, string>, а в половине map<string, int>. в с++ это делается так:

template <int x>
auto f() {
  if constexpr (x % 2 == 0) {
    return map<int, string>()
  }
  else {
    return map<string, int>();
  }
}

а как это делается в той куче мусора которую они сюда тащат? вот в чём вопрос.

anonymous
()
Ответ на: комментарий от anonymous-angler

какой один тип? ты говоришь, что тип выводится. в половине случаев должен вывестись один тип, в половине другой.

anonymous
()
Ответ на: комментарий от anonymous

В какой половине, ты о чём?

Там точно также как в С++ с выводом типов у функций:

auto deduce_int(bool cond) // внезапно компилятор вывел int
{
    if (cond)
    {
        return 1;
    }
    else
    {
        return deduce_int(!cond);
    }
}

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

В С++ такой же вывод типов. В этих других языках, его расширили для контейнеров просто потому что там нет неявных преобразований.

В С++ можно сделать всё тоже самое компилятор позволяет, просто решили что не нужно ломать неявные преобразования типов.

Как говорят Rust фанатики, это их выбор, а не немощь компилятора.

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 2)
Ответ на: комментарий от fsb4000

ну я же не зря написал ранд. ну давай скажем, что если cond == true, то функция должна возвращать int, а если cond == false, то string.

anonymous
()
Ответ на: комментарий от anonymous

ну я же не зря написал ранд. ну давай скажем, что если cond == true, то функция должна возвращать int, а если cond == false, то string.

C++ std::variant или Rust enum или F# discriminated union или подобный тип в других языках

fsb4000 ★★★★★
()
Последнее исправление: fsb4000 (всего исправлений: 1)
Ответ на: комментарий от kawaii_neko

Ну вот только не надо тут устраивать интригу. Понятное дело, что в плане вывода типов С++ не самый продвинутый. Но это не отменяет наличие вывода типов в С++.

yetanother ★★
()
Ответ на: комментарий от anonymous-angler

завертелся ужик на сковородке? тип один. но если rand() чётный, то это один тип, а если нечётный, то другой. тип переменной остаётся одним, но он зависит от rand(). выведи тип свой мусорный тип позязя.

anonymous
()
Ответ на: комментарий от anonymous

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

Никаких «новых типов» такими приседаниями не сделать. Весь constexpr по сути просто костыль для того, чтобы подинамичней подстановочки в шаблончики делать. Да и «compile-time C++» — это весьма другой язык.

kawaii_neko ★★★★
()
Ответ на: комментарий от anonymous

Ещё раз: в контексте статически типизированных языков твоя просьба нериализуема.

Однако я и не утверждал, что type inference может выполнить все нездоровые желания. Однако, оно может больше, чем type deduction в C++. Последняя требует что бы r-value было и имело конкретный тип во время объявления переменной. А type inference в Rust - нет.

use rand::random;

fn main() {
    let mut a = Vec::new();
    let mut b = Vec::new();
    
    for _ in 0..10 {
        if random() {
            b.push("Hello");   
        } else {
            a.push(b.pop());
        }
    }
}
anonymous-angler ★☆
()
Ответ на: комментарий от yetanother

Понятное дело, что в плане вывода типов С++ не самый продвинутый. Но это не отменяет наличие вывода типов в С++.

Еще раз: в C++ полностью отсуствует вывод типов. Начисто. Совсем.

Есть «overload resolution» и «template arguments deduction». C++ — реально тупиковая ветвь, полная внутренних противоречий и граблей на каждом шагу.

Но тут все как в жизни: на каждый жуткий инструмент найдутся мазохисты, которые будут этим пользоваться и биться в экстазе. Это нормально, уж такова природа человека. Ненормально — это когда зашоренные фанаты начинают затирать про «исполнение в компайл тайме» и «вывод типов», когда в жизни своей не видели ни того, ни другого.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

Ненормально — это когда зашоренные фанаты начинают затирать про «исполнение в компайл тайме» и «вывод типов», когда в жизни своей не видели ни того, ни другого.

в каком языке лучше компайл тайм чем в С++?

Удиви меня. Раст разрабы сколько лет уже не могут выдрать constexpr возможности из LLVM для своего язычка: https://github.com/rust-lang/rust/issues/57563

fsb4000 ★★★★★
()
Ответ на: комментарий от kawaii_neko

Согласен, что в С++ много противоречий и граблей. Но это следствие эволюции, он был во многом первый и за счет его ошибок другие учились. Как по мне, так возможность использовать `auto` это все равно шаг вперед.

yetanother ★★
()
Ответ на: комментарий от fsb4000

в каком языке лучше компайл тайм чем в С++?

Я извиняюсь, что повторяюсь, но я снова не могу не вспомнить D, где (опять же давным давно) есть CTFE, которое лучше чем в плюсах. Уже за счет того, что не нужно тащить совместимость с легаси. Например в D нет нужды в использовании `constexpr`. И тот же static if не вводит scope. И в CTFE работает значительное подмножество языка, можно работать со строками, например.

yetanother ★★
()
Ответ на: комментарий от fsb4000

в каком языке лучше компайл тайм чем в С++?

Да, в 2020 лор деградировал до невозможности, если задают такой вопрос. Конечно же в Common Lisp.

kawaii_neko ★★★★
()
Ответ на: комментарий от yetanother

возможность использовать `auto` это все равно шаг вперед.

Возможно, но читать портянки из const auto &foo = do_bar(is_fuckable_v<decltype(with_baz(baz))>);, мягко говоря, неприятно.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

Ну как бы такое читать еще хуже:

const WTF<very_long_list_of_types_etc_that_can_take_several_lines_of_nested_complex_constructions>::const_iterator &foo = do_bar(is_fuckable_v<decltype(with_baz(baz))>);

Что мне реально нравится в auto это если в процессе прототипирования изменяются типы, особенно шаблонные, их не надо прописывать во всей цепочке вызовов где они используются, это повышает продуктивность.

Да, может с академической точки зрения auto это скучно и банально, но с точки зрения работы в полях это очень даже полезно.

yetanother ★★
()
Последнее исправление: yetanother (всего исправлений: 1)
Ответ на: комментарий от kawaii_neko

читать портянки … неприятно

Не читай

fsb4000 ★★★★★
()
Ответ на: комментарий от yetanother

Ну как бы такое читать еще хуже

А может что-то не так с языком, если он порождает такие конструкции на каждом шагу?

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

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

yetanother ★★
()
Ответ на: комментарий от yetanother

Тот же лисп все-таки не получил такого распространения как плюсы при всех его достоинствах

Кажется ныне живущие забыли, что во времена лиспа и зарождения плюсов важную роль играла производительность. Динамический ЯП, да еще и с GC... Думаю, что и ruby с python навряд ли добились бы сегодняшней распространенности, если бы железо не нивелировало их тормознутость в подавляющем большинстве задач.

kawaii_neko ★★★★
()
Ответ на: комментарий от kawaii_neko

Я с этим не спорю. Я больше про то, что все-таки плюсы более распространены и приходится использовать то, что имеем, а не то, что хочется.

yetanother ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.