LINUX.ORG.RU

Man or boy 2к25: Ваш статически типизированный ЯП полноценен?

 


0

4

Когда то Кнут придумал тест для ALGOL реализаций, и он известен под именем «Man or boy test». Но там просто локальные функции, не особо интересно.

Предоставляю вам версию для проверки языка программирования, на то, достоен ли он существовать в 21 веке!

Для начала нарушу это правило (у Python динамическая типизация), и покажу Python версию:

def print_sum(x):
  def make(acc):
    def f(y):
      print("acc(%d) + %d" % (acc, y))
      return make (acc + y)
    return f
  return make(x)

print_sum(10)(20)(30)(40)
Вывод
acc(10) + 20
acc(30) + 30
acc(60) + 40

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

Мое повторение на OCaml с rectypes:

let print_sum x =
  let rec f acc = fun y ->
    printf "acc(%d) + %d\n" acc y;
    f (acc + y)
  in 
  f x
  
let () = ignore (print_sum 10 20 30 40)
Типы он вывел сам, но можно и указать вручную:
type t = int -> t 

let print_sum (x : int) : t =
  let rec f (acc : int) : t = fun (y : int) : t ->
    printf "acc(%d) + %d\n" acc y;
    f (acc + y)
  in 
  f x
  
let () = ignore (print_sum 10 20 30 40)

Языки которые смогли реализовать тест на лямбдах/функциях, их система типов и ее записи позволяет строить рекурсивные по возврату лямбды и функции:

Языки у которых получилось, но замыкания были выраженны через структуры, потому что они так представленны в самом языке, это облегачает построение рекурсивных по возврату типов, потому что рекурсии в структурах есть везде:

Языки у которых пока не получилось без дополнительных средств типа классов/структур для обхода проблем с типами:

  • Rust (использование trait)
  • C (некорректная реализация)
  • Zig (использование классов)
  • D (использование делегатов)

Не являсь полностью статически типизированным языком, через свою систему типов смогли выразить пример

★★★★★

Последнее исправление: MOPKOBKA (всего исправлений: 21)
Ответ на: комментарий от monk

я могу поместить в переменную. Или даже в хэш.

Кому интересно что ты можешь в каком-то позорище бесполезном? Ты мне ещё про брейнфак расскажи. Зачем ты пытаешься брать какие-то базворды из индустрии, которые к тебе не применимы. У тебя нет ни переменных ни хешей.

А вот С++ шаблоны в массив не сложить. Потому что у них нет типа.

Как же ты любишь позорится. https://gcc.godbolt.org/z/s3YnxsEE9

Самое смешное, что тебе на это выше уже несколько раз отвечали.

Ты ничего не знаешь ни про цпп ни про шаблоны. Но проблема не в том что ты не знаешь - это нормально. ТЫ даже не сможешь осознать те концепции что за ними стоят. Несмотря даже на твои жалкие попытки врать, выпаривать убогий евал в своей скриптухи. Ты не знаешь что такое типы.

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

По условию задачи 1 и 2 единичные множества.

Потому что никаких значений нет

каким образом единичные множества у тебя существуют, а значений никаких нет? в единичном множестве сколько значений? неужели ноль???

Какое значение у struct {}

пустое множество - это тебе знакомое понятие?

А любая скриптуха вообще ссылочная - там значений в принципе нет.

Там связывается имя со значением. Потянул за имя, а там хоба - true или 144. И это не значения, а помрачение рассудков, так что ли?

Кстати, как тип может определять какие-то преобразования? Инт без умножения это инт? Или инт с умножением это другой инт?

Тип может определять преобразование других типов в себя и наоборот. умножения тут не причем. как в с++ не просто так есть кастомные операторы преобразования типа или конструкторы себя из других типов.

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

Учитывая что там числа Пеано Это не числа. И там никакое не пеано, а жава-лапша.

Но представим, что там нету ограничений по типам и операциям. Ты пишешь что все на интерфейсе Natural, но int это тоже интерфейс, разве нет? В чем разница между Natural и int?

Нет, инт это не интерефейс. Я уже десять раз это повторял. Там нет интерфейса - там полностью отдельные типы со своим поведением. Вот это int_t<x> - это никакие не инты.

То что оно не генерирует отдельные struct IntT10 / IntT20, похоже больше на вопрос кодогенерации, чем на то, с чем может взаимодействовать программист.

Нет. Там вопрос не в генерации, а в том что это отдельные типы. В этом суть. А числа используются для того чтобы эти типы создать. И только и всегда и именно поэтому боты пытаются постоянно лезть к этим числам. Воруя свои лефтпады и евалы.

Абстракция в примере с eq не протекает. Пусть там отдельный шаг на eval идет. Как абстракция может протечь в итоге?

Она протекает. Просто ты опять же слушаешь шизов, которые пытаются тебя запутать. Никаких чисел нет. У него там жава-лапша из интфрейса + евал. Там нет даже типов рамках чисел.

Но давай подумаем далее. А как этот бот расширит числа до флоатов/прочих чисел? А если это не числа? Собственно именно поэтому он потерялся на флоатах, потому что флоаты нельзя свести к жава-мусору с подсчётом шагов рекурсии. Там не определены некоторые числа.

Научись отличать явления от их попытки воспроизведения о чём я тебе говорил. Потому что жизы - это шизы. Их задача врать и воровать. Если сектант смог воспроизвести какое-то свойство числа - это не значит что это число. Тебя даже в базе обманули и ты принял это. И вопрос дале не в расширении/ограничений операций, а в том что чисел нет. Типов нет. Ничего нет. Это очередной фокус для детей.

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

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

Каждый отдельный шаг программы/контекст существует сам по себе. Хотя в жаве и этой убогой кальки с жавы всё итак сделали объектов. Но толку с этого? Какой смысл сводить всё к одному и тому же?

И вот чтобы это расширить на другие инты - он будет воровать новый тип. Потом ещё один и так до бесконечности. И ты делаешь эти расширения бесконечно. И всех их нужно увалять в одну жава-иерархию. У тебя нет разделения/нет доменов. Ты не сможешь ничего написать.

Именно поэтому он сегодня нагадил своим евалом, а завтра пошёл бацать лабу на интах. Это такой же критерий - применимость. Аналогично с описанной выше расширяемостью.

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

каким образом единичные множества у тебя существуют, а значений никаких нет? в единичном множестве сколько значений? неужели ноль???

Зачем ты нелепо пытаешься дёргать фразы из разных контекстов?

пустое множество - это тебе знакомое понятие?

У пустого множества нет значений, а тут оно есть. Если оно пустое, то что такое void, что такое другая структура?

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

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

К тому же кто отвечает за преобразование? Тип А или тип Б? Значит тип не определяет преобразования и ты опять сел в лужу. В прочем типично для нейробота.

умножения тут не причем.

Умножение это операция. Ну то что ты нелепо пастил и называл функцией:

множество функции применимых к данному типу

Вот тут. Куда ты потерял всё это? Чё там контекст в нейронке потерялся?

как в с++ не просто так есть кастомные операторы преобразования типа или конструкторы себя из других типов.

Причём тут «кастомные»? Что такое «кастомные»? С чего вдруг они кастомные? У тебя явно слишком плохая нейронка, нейробот. Поменяй. Авось узнаешь как это в цпп называет и какой смысл имеет.

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

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

Но толку с этого? Какой смысл сводить всё к одному и тому же?

Идея того что есть тип struct int_t {}; а сверху компилятор к типу привяжет некое значение, которым будет оперировать только в CT (и потом вставлять в asm результаты), кажется интуитивно хорошей.

Тем что компилятор не будет генерировать по сути ненужные копии методов add, mul, и сами эти функции могут быть например возвращенны как просто:

auto f()
{
  return int_t_mul;
}
Получается отложенная материализация шаблона.

А прямое встраивание в тип значения, как раз мешает этому, если рассматривать template <int n> int_t {};

Главное не терять это значение привязанное. Не знаю как лучше назвать такую пару тип+значения, пусть будет тип+.

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

Какое отношение это имеет к тебе и к твоему текущему позору? Эты был прошлый позор и код прошлого. И то залитый не тобой.

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

Я уже не помню ты это был или нет, но у меня прям вьетнамские флешбеки на тему тупняка. Когда-то какой-то одарённый пытался со мною соревноваться. Эти оправдания прям одни из самых тупых которые я помню. Если это был действительно ты, то меня твоё поведение не удивляет даже.

У вас в природе врать и придумывать всякие тупые оправдания. Там шиз написал какой-то мусор на асме и рассказывал про победы, а потом сливал трём строчками на цпп. И вместо признания проблемы он начал нелепо придумывать оправдания. Оправдания звучали так «нужно читать входной файл с хдд». Потому что тогда его поделка не сливала. Они просто видят соломенку и им плевать на всё.

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

Я не совсем понимаю о чём. На самом деле эти функции/прочее может быть возвращено только в цпп. Там чушь он выше нёс - она не работает. Это фокус работает один раз.

Тем что компилятор не будет генерировать по сути ненужные копии методов

Это, опять же, непонимание того как это работает и что это такое. Там нет «ненужных методов» они все нужные. У них совершенно разное поведение.

Пусть это будут не числа, а таплы такого же размера. Ты понимаешь, что железка не может через одну функцию принимать таплы разного размера? Да даже не таплы, а просто массивы. Это не убогая жава с гц и боксингом.

Это выше как позорные набросы вида «у тебя не проверяет». Хотя цпп не проверяет не потому что «не проверяет», а потому что не может. Люди просто пытаются свои жавы натягивать на цпп. Типа у них какие-то проверки есть, но те где они у них есть - это абсолютно бесполезно. А выйти за рамки этого бесполезно они не могут.

Так же и тут. Методы не являются бесполезными - это просто кажется так пока ты не осознаешь причины и назначения этого. Пока не начнёшь мыслишь шире жавы. Хотя жава в этом плане куда как шире кописты с неё в виде хаскеля.

Как я уже говорил выше - теоретически можно сделать так чтобы лишние функции не генерировались потому что они не всегда нужны. Но не «генерировались иногда» и «не генерировались вообще» - это разное. Никогда ненужно это путать. И набросы шизов вида «ну у нас нет лишних» - у них нет ничего.

Но всем просто как-то плевать. Да, можно сделать, но это не так чтобы проблема. Всё же цпп это кружок для одарённых и они могут сделать себе компилятор. К тому же убирать эти функции достаточно просто и это быстро происходит.

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

Но в целом да. Это имеет смысл. Этим люди занимаются.

А прямое встраивание в тип значения, как раз мешает этому.

Ещё раз. Там нет никаких значений. Нет никакого встраивания. Там есть отдельные типы. Отдельные типы нельзя свести к чему-то одному. Это невозможно. Да и на это я уже ответил.

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

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

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

Ещё раз. Там нет никаких значений. Нет никакого встраивания. Там есть отдельные типы.

Значением я называю 30 в записи int_t<30>.

Ты понимаешь, что железка не может через одну функцию принимать таплы разного размера?

Это не замена механизму шаблонов в общем, а только для ситуаций когда в шаблон передается значение с конкретным типом, я терминологию не знаю, но вот к примеру для template <typename T> struct int_t {} предложенный механизм явно НЕ подходит, а для template <std::tuple<int, float> tup> struct int_t {} уже подходит.

На самом деле эти функции/прочее может быть возвращено только в цпп.

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

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

Зачем ты нелепо пытаешься дёргать фразы из разных контекстов?

контекст был один. ты высказал «мысль», что никаких значений не бывает! при этом у тебя «сменился контекст», поскольку в предыдущем предложении ты говорил об «одноэлементном множестве».

я тебя и спрашиваю - так бывают значения или нет? в одноэлементном множестве сколько значений? ты можешь ответить наконец?

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

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

Значением я называю 30 в записи int_t<30>.

Я понимаю что ты называешь значением. Но я тебе и говорю, что это не значение - это тип. Просто в цпп ты не можешь использовать 30 как тип вот и приходится делать обёртку. Ты можешь это воспринимать просто как 30, который тип. Ну примерно как тс, но там не число это, конечно же, но в любом случае.

То, что там int_t<30> вместо 30 это цпп-специфика. Она не особо относится к теме.

Это не замена механизму шаблонов в общем, а только для ситуаций когда в шаблон передается значение с конкретным типом

Я ничего не понимаю. Здесь нет никакой разницы. Ты что-то левое нагородил у себя в голове.

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

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

И так работает в реальности. Конечно можно было бы сделать так чтобы оно делало, но я писал об этом выше.

а для template <std::tuple<int, float> tup> struct int_t {} уже подходит.

Что такое механизм? Одна функция? Нет, не подходит. Это тебе не скриптуха. Это int_t совершенно разное для разных таплов, которые ты туда передашь. Фундаментально разное. То, что тебе кажется что сишный лейаут тут одинаковый - это на самом деле не так.

template <std::tuple<int, float> tup> struct int_t { int arr[tup[0]]; } и всё - ты вернулся к разному лейауту. Тут нет такого «Тут можно, а тут нельзя» - это не скриптуха убогая.

Сейчас тоже можно, но не таким простым кодом как я показал.

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

Хотя я непонимаю почему сейчас нельзя ее вернуть, почему нельзя после возврата указать с какими шаблонами вызывать ее.

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

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

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

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

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

Там было два контекста, вот где было определение одного:

А то, что ты как и в прошлый раз опозорился даже в рамках того что копипастишь.

в рамках того что копипастишь

А второй было определено тут:

Тут даже проблема не в том что это определение чушь и никого в реальности не волнуют определения для домохозяек.

Соответственно я отрицаю эту шизу и не должен мыслить в рамках неё.

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

Самое смешное, что там даже доказано несуществование для обоих контекстов. Ещё одно, что не может понять бот. В чём разница между нашими контекстами?

Бот мне сообщил что у него какое-то строгое определение. Я такого не сообщал.

есть довольно строгие определения

Поэтому у меня могут быть значения, а могут не быть. Для меня это работает. А вот для бота с его определением это не работает. Потому что он сделал заявку на строгое.

Есть/нет значение это констатация фактов. К тому же значение там было сказано, опять же, в его контексте, а не моём. Из «нет твоих шизо-значений» не значит что нет значений.

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

... и всё - ты вернулся к разному лейауту

Действительно, тогда идея так себе.

Там проблема не в шаблоне.

Ага, понял, с лямбдами уже получается.

MOPKOBKA ★★★★★
() автор топика