LINUX.ORG.RU

Возврат значения из замыкания


0

4

Как вы считаете, если противопоставить, какое _и почему_ в абстрактном ЯП поведение оператора return внутри замыкания более правильное/оправданное: когда return только возвращает управление из замыкания или когда return вызванный внутри замыкания приводит ещё и к возврату из контекста, откуда было вызвано замыкание?

p.s. В качестве примера второго поведения - return из Proc в Ruby.

★★

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

тьюринг-полнота никак не связана со сложностью.

Иди, читай, что такое Колмогоровская сложность.

Но при чем тут джава? Эффективный низкоуровневый код - это сишка тогда. И опять ООП нинужно.

Java генерит достаточно эффективный код. И кто тебе сказал, что в Си ООП не нужно? Посмотри на хотя бы даже ядро линукса - там ООП на ООПе сидит и ООПом погоняет.

Самое смешное, что на таких задачах динамическое скриптовое говно с хорошим трассирующим джитом (типа луа) вполне уделает ту же сишку.

Пруф или не было.

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

Просто ты не понимаешь, что такое ООП. Точнее воспринимаешь его слишком широко.

Я его понимаю ровно так, как завещал понимать товарищ Кей.

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

А зачем ООП? Я не про лисп, а вообще. Инкапсуляция - модули

Полиморфизм - дженерики/шаблоны для параметрического, тайпклассы/инстансы - для ad-hoc

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

И т.д.

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

А зачем ООП? Я не про лисп, а вообще.

Для управления абстракцией и для контроля за сложностью, очевидно.

Инкапсуляция - модули

Ну да, в одном из лучших ОО-языков, в Обероне, именно так и сделано.

Полиморфизм - дженерики/шаблоны для параметрического, тайпклассы/инстансы - для ad-hoc

Полиморфизма много не надо. Как в Обероне - в самый раз.

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

Наследование тоже сомнительную пользу в ООП имеет. Достаточно самой простой формы (subclasses, virtual methods).

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

А при чем тут Кей? ООП было до него, первым языком была Simula 67, к которому указанный товарищ, мягко скажем, не имел никакого отношения.

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

Тогда от ООП остается только «все объекты», а это не серьезно. Так было и до ООП.

P.S. Оберон - говно.

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

Я его понимаю ровно так, как завещал понимать товарищ Кей.

ООП в понимании Кея нет в той же Java.

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

Функция не может изменить control flow там, где ее вызвали, кроме очевидного варианта с выбросом exception-а.

Ну так и макрос не может. Попробуй написать макрос, который его поменяет.

И для понимания локального control flow это все абсолютно не важно.

Как и в случае макроса. макрос - это же тоже такой же черный ящик как и функция.

Я очень много чего могу о нем сказать исходя из одной только сигнатуры.

Если на экспанд макроса посмотреть тоже можно многое сказать.

Я говорю про локальный control flow.

ясно. но макросы в этом плане ничем не отличаются от ф-й тогда.

Не знаю! Ни хера я не знаю, пока не увижу определения макроса.

А тип функции ты не узнаешь пока не увидишь определение функции.

Я не знаю, вычислит ли он свои аргументы, когда он их вычислит, сколько раз, и т.д.

Для ленивой ф-и это столь же верно.

Какая несусветная чушь! Давай, напиши функцию LOOP. Ну или хотя бы COND.

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

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

А это баг. Да, баги бывают. В функциях тоже. Санку передать например.

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

Но таких языков программирования нет. Если знаешь такие языки - приведи пример. Ну хоть один.

Код на хорошем языке понятен и очевиден сразу, и не требует лишней информации.

А макросы при чем?

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

Что за бред? def f x = g x, ну и какова логика ф-и f, если ты не знаешь логики g?

С макросами же это невозможно.

Ты можешь конкретно объяснить что невозможно для макросов, возможное для ф-и? Ну пример приведи в качестве proof of concept, я хз.

С моей точки зрения все твои перлы находятся на уровне «функции писать нельзя, потому что они путают control-flow блаблабла». Вот точно такой же бред. Один уровень бредовости утверждений.

Тупишь изрядно. Это вообще не при чем.

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

У-тю-тюшечки. Весь энтерпрайз на Java написан. Просто ВЕСЬ.

Какой весь? Я вот слышал что куча софта написана на лиспе. Кто врет? Ты или mv?

Из того, чем я непосредственно пользуюсь - Jira, Eclipse, Tomcat, Maven, и вообще десятки других инструментов, с помощью которых я зарабатываю деньги.

Ну то есть на джаве написан софт для написания и использования софта на джаве. И если вдруг джава вот возьмет и исчезнет весь этот софт станет бесполезен. то есть создаем сами проблемы (жабу) и героически ее преодолеваем написанием жабасофта для жабы.

А много денег тебе приносит говнософт на говнолиспе?

Мне - нет, я пишу на лиспе для собственного удовольствия и нужд. А вот кому-то приносит (тем самым людям, которые пишут говнософт на говнолиспе для банков, да).

То есть получаем что?

На жабе есть софт, этот софт предназначен для жабы.

На лиспе есть софт и этот софт предназначен для самого лиспа.

На жабе можно зарабатывать деньги - на лисе можно зарабатывать деньги. Пока что все ровно идет.

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

Иди, читай, что такое Колмогоровская сложность.

Колмогоровская сложность имеет отношение к сложности программ примерно такое же, как и тьюринг-полнота. Ну то есть никакого. Легко придумать тьюринг-худой ЯП, который будет посложнее малболга, например.

что в Си ООП не нужно?

Оно, может, и нужно - но его там нет.

Пруф или не было.

Ну посмотри на бенчмарки luajit. Суть в том, что тут трассирующий джит будет быстрее _любого_ компилируемого языка. Так он устроен, чтобы давать максимальную производительность на подобных задачах. А все проверки на типы и боксинги джит из лупа просто уберет - то есть в скомпилированном коде будет та самая статика.

Посмотри на хотя бы даже ядро линукса - там ООП на ООПе сидит и ООПом погоняет.

Ага, тут важен исторический контекст. Вот смотри, люди начали писать программы. Оказалось, что есть некий набор принципов, которые позволяют упростить написание программ. И люди начали использовать эти принципы. Их никто не называл и не называет ООП. Внезапно оказалось, что эти принципы наиболее легко и естественно используются в рамках определенной парадигмы - эту парадигму назвали «функциональное программирование» (по сути это и есть программирование в соответствии с указанными принципами, программирование заточенное под них). Никакого ООП, опять же, и близко еще не было. К сожалению, рантайм реального процессора был очень далек от рантайма таких языков и потому они ТОРМОЗИЛИ. Надо было писать на чем-то более низкоуровневом. Люди пытались и там использовать все те же принципы - но изза низкоуровневости языка это уже не было легко, изящно и просто. Это было криво и костыльно. Тогда пришла идея - ввести в язык ряд встроенных средств, которые бы упрощали использование этих принципов (то есть сделать эдакий набор стандартизованных универсальных костылей). Сказано - сделано. Вот этот набор стандартизованных костылей и назвали ООП. Но те самые принципы, использование которых ООП должно упрощать в низкоуровневых язычках, как и раньше, наиболее легко, полно и удобно выражаются именно в рамках ФП. Потому что именно ФП - программирование в соовтетствие с этими принципами. А ООП - это просто костыль. Исторически сложившийся казус.

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

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

Я его понимаю ровно так, как завещал понимать товарищ Кей.

Давай тогда определимся с терминологией. А то ведь ООП товарища Кея - это message-passing. И в жабе нет такого ООП.

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

Любой инструмент должен быть реализован удобно. Ну то есть вот в плюсах есть ФВП и замыкания, но сделаны костыльно. потому нахуй там не нужны, кроме как приговаривать «а у нас есть». Наличие плохо реализованного инструмента на практике не отличается от его отсутсвтия.

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

Давай ты скажешь, что такое ООП.

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

Но ведь под эту формулировку не подходит ни ява, ни тем более упомянутый тобой Оберон.

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

А что там не так? Удобно вполне. Если еще Boehm GC юзать и забить на слежение за замыканиями - так вообще не отличить от нормальных языков.

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

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

Каг бе, ты не прав.

В продакшене, кстати, на удивление отлично работает. Я после глюков SBCL 3-4 года назад при работе с не очень сложной программой StumpWM ожидал проблем и с моим Ъ-энтерпрайз софтом, в котором применено всё самое плохое, что лиспофобы боятся в лиспе, но Lispworks на удивление хорошо работает за свои деньги.

Из бесплатных Clozure примерно того же порядка надёжности.

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

Тогда от ООП остается только «все объекты»

Еще наследование объектов-структур, геттеры, сеттеры, прочие поведенческие «триггеры» для хитрого изменения состояния, а больше от ооп и не надо.

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

Ну так и макрос не может. Попробуй написать макрос, который его поменяет.

В говнолиспе (CL) есть PROG, в котором есть label-ы и GO. Намек ясен?

Если на экспанд макроса посмотреть тоже можно многое сказать.

А тип я знаю из кода. Потому что код написан не ублюдками, а нормальными людьми, у которых никаких таких «var» или «auto» не будет. Все типы выводятся из текущего контекста, так что я знаю сигнатуру функции и так.

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

Ну и напиши. Меньше трепа, больше кода. Так, чтоб синтаксически не отличалось от COND.

Что за бред? def f x = g x, ну и какова логика ф-и f, если ты не знаешь логики g?

Такова - функция f вызывает функцию g и тут же возвращает полученное значение. Control flow понятен. А вот если б g было макросом, то ни черта бы не было понятно. Может он, например, catch тут вставит, или еще какую дрянь, глобально меняющую поведение кода.

Ты можешь конкретно объяснить что невозможно для макросов, возможное для ф-и? Ну пример приведи в качестве proof of concept, я хз.

Для вызова функции или метода всегда понятен control flow. Для мароса - нет. Для аргументов функции всегда понятна семантика - вычисляем один раз, в определенном порядке, передаем полученные значения. Для макроса порядок вычислений неопределен, как и вообще сам факт, что аргументы будут вычислены.

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

(defmacro yoba (x y) `(let ((blahamuha ,y)) ,x))

Вот у нас какая-то blahamuha в контексте появилась. А если мы в x на blahamuha ссылаемся, то будет интересно.

Какой весь? Я вот слышал что куча софта написана на лиспе. Кто врет? Ты или mv?

Конечно же mv лжет. Ведь элементарно проверяется.

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

Ну посмотри на бенчмарки luajit.

Говно твои бенчмарки. Нет там видеокодеков. Даже рейтрейса банального нет.

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

Чушь. В случае, когда в потоке обрабатываются однотипные данные, никакой трассирующий jit никак не поможет.

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

Не надо чушью разговаривать. ФП - это отсутствие сайд-эффектов. А реальность (объективная, данная нам в ощущениях) только из сайд-эффектов и состоит. ФП, следовательно, к реальным задачам вообще неприменимо.

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

Каг бе, ты не прав.

Пруф или не было.

в котором применено всё самое плохое, что лиспофобы боятся в лиспе,

И сколько человек (и за какие деньги) это говно поддерживает?

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

«Наследование объектов-структур» - это что? Наследование реализации там выше предлагали заменить композицией, а наследование интерфейсов - тайпклассами. А остальное из тобой перечисленного - не ООП, ибо просто абстракция и инкапсуляция.

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

Т.н. сайд-эффекты заменяются на потоки-списки состояний. Ну и к тому же, монады и моноиды...

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

Т.н. сайд-эффекты заменяются на потоки-списки состояний. Ну и к тому же, монады и моноиды...

Я сейчас позову братву Оккама. Суровые ребята, не любят лишних сущностей.

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

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

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

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

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

В говнолиспе (CL) есть PROG, в котором есть label-ы и GO. Намек ясен?

Нет. Макросы тут при чем?

А тип я знаю из кода.

И экспанд ты знаешь из кода.

Ну и напиши. Меньше трепа, больше кода. Так, чтоб синтаксически не отличалось от COND.

а почему оно не должно синтаксически отличаться от COND?

Такова - функция f вызывает функцию g и тут же возвращает полученное значение. Control flow понятен.

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

Может он, например, catch тут вставит, или еще какую дрянь, глобально меняющую поведение кода.

Может у тебя catch внутри g или g аффектит глобальные переменные? Одно и то же.

Для вызова функции или метода всегда понятен control flow.

Так же как и для макроса.

Для мароса - нет.

Можно пример, где непонятно?

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

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

Вот у нас какая-то blahamuha в контексте появилась. А если мы в x на blahamuha ссылаемся, то будет интересно.

А, ну так это проблема негигиенического общеговна. Негигиенические «макросистемы» - это хуита на уровне препроцессора цпп, да, тут ты верное сравнение привел. Но я же говорил о макросах, а не о препроцессоре. В макросах мне такой хуйни не надо, нет, и даром не надо. И нету ее, слава богу.

Конечно же mv лжет. Ведь элементарно проверяется.

Да? проверь.

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

Говно твои бенчмарки. Нет там видеокодеков. Даже рейтрейса банального нет.

Там задачи с тайт лупами.

Чушь. В случае, когда в потоке обрабатываются однотипные данные, никакой трассирующий jit никак не поможет.

Молчи, если не знаешь. Оптимизация как раз такого кода (потоковая обработка однотипных данных) - это то, под что заточен трассирующий джит. Благодаря трассировке такой джит может произвести ряд существенных оптимизаций, которые в компайлтайме произвести невозможно в принципе - например, заинлайнить константу или сделать elimination кода, который можно сделать только на текущей итерации цикла (т.к. в общем эта константа не константа нихуя и на другой итерации будет иметь другое значение, а удаленный код нельзя будет удалять). Развернуть цикл который проходит через несколько функций или вынести код из цикла за функциональный вызов и т.п.

Не надо чушью разговаривать. ФП - это отсутствие сайд-эффектов.

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

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

Нет. Макросы тут при чем?

При том, что они могут этим пользоваться. Допустим, у нас есть `(f g h i)`. Что оно делает? А что угодно. f может раскрыться в (prog (g) (h) (i)), например, (g) в свою очередь раскроется в label, а (h) будет содержать (go label). И в результате получаем безумный и абсолютно неочевидный из исходного синтаксиса control flow.

И экспанд ты знаешь из кода.

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

а почему оно не должно синтаксически отличаться от COND?

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

Что понятно-то? Ты же не описал никакой control-flow.

Описал. Локальный. Для данной функции. Большего и не надо.

Что происходит в g? ты не знаешь.

И мне наплевать. Главное, чтобы оно в принципе возвращало значение.

То есть никакой информации об f у тебя нет. А теперь предположим, что g - макрос. Что изменилось? Ничего.

Определение функции f изменилось. В неизвестном направлении.

Какую полезную информацию ты потерял по сравнению со случаем, когда g - функция? Никакой.

Я потерял понимание семантики функции f. Всего лишь.

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

Там задачи с тайт лупами.

Там ни единого случая, когда luajit обогнало бы C на вычислительно тяжелой задаче.

который можно сделать только на текущей итерации цикла

Господи, откуда в мире столько идиотов?!? Нет времени на компиляцию, тем более на каждой итерации цикла! Вообще нет.

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

В первых ФП языках никакого отсутствия сайд-эффектов не было и близко.

Первый ФП-язык - это само лямбда-исчисление. Где там сайд-эффекты?

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

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

Мутабельные состояния только в твоей голове.

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

К моему глубочайшему сожалению, твоя голова устроена практически точно так же, как и моя (и тем самым оскорбляет вообще весь человеческий род).

В твоей голове электрохимические сигналы распространяются по синапсам (непрерывно меняя их состояние), и вызывают каскады реакций в нейронах (что меняет их состояние).

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

При том, что они могут этим пользоваться.

Только внутри. Так же как и функция.

Допустим, у нас есть `(f g h i)`. Что оно делает? А что угодно.

Как и функция.

Не знаю. Код на бумажке распечатан, лежит на столе. Определение макроса я посмотреть не могу и не хочу.

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

Просить интерпретатор мне его раскрывать я тоже не собираюсь - код, напоминаю, на бумажке.

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

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

Да, все так. Но при чем тут синтаксис? Почему ф-я, которая принимает некую строку и както хитро ее интерпретирует с нетривиальным control-flow отличается в чем-то от макроса, который принимает форму макровызова и раскрывается в нетривиальный control-flow? результат же полностью совпадает.

Описал. Локальный. Для данной функции. Большего и не надо.

Ну так для макроса то же самое все. функция: «происходит вызов кода, который определяется в функции g», макрос: «происходит вызов кода, в который раскрывается макрос g».

Знаешь тут смешное что? В случае TCO два случая f = g x и f = *hur-dur-macros* отличается на ровно один джамп. Другими словами в первом случае ты можешь утверждать лишь одно - перед *hur-dur-macros* (которое возможно есть в реализации g) есть джамп.

А знаешь что еще смешнее? Что тебе компилятор можеть заинлайнить g. По-этому получится *hur-dur-macros* безо всяких джампов. Так что мы пришли к тому, что ты _ничего_ не можешь сказать.

И мне наплевать. Главное, чтобы оно в принципе возвращало значение.

А с чего ты взял что оно возвращает значение? Как мы уже выяснили, g может быть заинлайнена, а в самом же может быть все что угодно.

Определение функции f изменилось. В неизвестном направлении.

Еще раз - какая информация о f потеряна? Никакой.

Я потерял понимание семантики функции f.

конкретно. Что ты знал о семантике f, что потерял? (очень хороший вопрос - особенно учитывая тот факт, что семантика никак не поменялась, лол).

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

Там ни единого случая, когда luajit обогнало бы C на вычислительно тяжелой задаче.

Как раз на них и обгоняет.

Господи, откуда в мире столько идиотов?!? Нет времени на компиляцию, тем более на каждой итерации цикла! Вообще нет.

Если эта компиляции в итоге сэкономит на исполнении этой итерации время большее, чем занимает сама компиляция (а это в данном случае так) - то время есть.

Первый ФП-язык - это само лямбда-исчисление. Где там сайд-эффекты?

Лямбда-исчисление - это лямбда-исчисление. _исчисление_. А первый функциональный ЯП - это лисп.

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

А может монады проще? Семантику описать легче, чем разрушающего присваивания...

Что касается реальности, то это вопрос исключительно философский, как заметили выше. А в плане вычислимости, все зависит от того, идем ли мы от машины Тьюринга, или же от лямбд Черча... Еще можно от алгорифмов Маркова идти, тогда придем к Рефалу(который таки ближе к ФП).

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

Только внутри. Так же как и функция.

У тебя в коде только один макрос используется? Функции между собой control flow перебрасывать не могут. Макросы же могут с твоим control flow сделать все, что угодно.

Как и функция.

Ладно. Ты все еще тормозишь. Упростим задачу. Что делает (prog (a) (b) (c) (d))?

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

Какой-то ты совсем медленный головою. Не смотрю я на определение функции! Мне ее сигнатура понятна из того кода, где она используется.

Да, все так. Но при чем тут синтаксис? Почему ф-я, которая принимает некую строку и както хитро ее интерпретирует с нетривиальным control-flow отличается в чем-то от макроса, который принимает форму макровызова и раскрывается в нетривиальный control-flow? результат же полностью совпадает.

Функция ничего не может изменить в control flow той функции, которая ее вызывает. А макрос - может. Функция не может ничего сделать с переменными, которые ей не передаются. Макрос может изменить что угодно и как угодно. Функция в контекст вызова насрать не сможет. Макрос - сможет, и почти наверняка это сделает.

конкретно. Что ты знал о семантике f, что потерял? (очень хороший вопрос - особенно учитывая тот факт, что семантика никак не поменялась, лол).

Например, макрос g мог иметь какие-то сайд-эффекты (в момент раскрытия). И тем самым повлиять на компиляцию всего последующего кода.

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

А может монады проще? Семантику описать легче, чем разрушающего присваивания...

Не проще. Объективно.

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

Как раз на них и обгоняет.

Пруф или лжешь.

Если эта компиляции в итоге сэкономит на исполнении этой итерации время большее, чем занимает сама компиляция (а это в данном случае так) - то время есть.

Это только в твоей больной голове такое возможно. В реальности этого не бывает. Нет таких задач, где это было бы возможным.

Лямбда-исчисление - это лямбда-исчисление. _исчисление_. А первый функциональный ЯП - это лисп.

Лисп - императивный язык с некоторыми элементами ФП. Не будь тупицей.

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

«Наследование объектов-структур» - это что?

Наследование структуры полей, конструктора, геттеров-сеттеров (если надо)

Наследование реализации там выше предлагали заменить композицией

Что такое композиция? Миксины или что?

а наследование интерфейсов - тайпклассами

Тайпклассы в динамически типизированном лиспе? Это как?

А остальное из тобой перечисленного - не ООП, ибо просто абстракция и инкапсуляция.

Абстракция, например, в моем примере вообще не при чем. А инкапсуляция - на уровне структуры и того, что я перечислил выше.

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

а не заменяется на что-то другое. Это вопрос философский.

Мир здесь не при чем, при in-place замене - структура не копируется. Кроме того, императивные алгоритмы часто по совместительству и декларативные.

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

У тебя в коде только один макрос используется? Функции между собой control flow перебрасывать не могут. Макросы же могут с твоим control flow сделать все, что угодно.

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

Ладно. Ты все еще тормозишь. Упростим задачу. Что делает (prog (a) (b) (c) (d))?

Выполняет по очереди формы (a), (b), (c), (d).

Не смотрю я на определение функции! Мне ее сигнатура понятна из того кода, где она используется.

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

Функция ничего не может изменить в control flow той функции, которая ее вызывает. А макрос - может.

Пример конкретный дай. Вот функция, вот в ней макрос, вот он меняет control-flow.

Функция не может ничего сделать с переменными, которые ей не передаются.

Может, конечно. Например изменить состояние глобальных переменных.

Макрос может изменить что угодно и как угодно.

Пример как макрос меняет «что угодно и как угодно» (предполагается, что функцией такого «что» и «как» не поменяешь).

Функция в контекст вызова насрать не сможет. Макрос - сможет, и почти наверняка это сделает.

Мы уже выяснили, что это проблема препроцессоров, а не макросов. Макросы никуда не срут.

Например, макрос g мог иметь какие-то сайд-эффекты (в момент раскрытия). И тем самым повлиять на компиляцию всего последующего кода.

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

То есть, как видно, вся проблема в том, что ты просто не знаешь, что такое макросы, и делаешь вывод на основе знакомства с препроцессорами (сишка, общелисп, прочее говно).

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

а какие недостатки реализации у Clozure по сравнению с SBCL?

Код помедленнее генерит, плюс некоторые товарищи пишут библиотеки под SBCL-only.

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

Пруф или лжешь.

До того как луаджит убрали с шутаута, оно обгоняло фортран на mandelbrot и spectralnorm. Учитываем, что это была _бета_.

Это только в твоей больной голове такое возможно. В реальности этого не бывает. Нет таких задач, где это было бы возможным.

В реальности как раз и бывает. Вот такой пример:

for (i = 0; i < 1000; i++){
   for (j = 0; j < 1000000; j++){
      if even(i) then yoba1(i) else yoba2(j);
   }
}
вот обычный компилятор тут ничего особо не сделает. Ну банальные loop-unrolling и т.п., а трассирующий джит для каждого i уберет проверку even и будет выполнять во внутреннем лупе либо вызов yoba2, либо вызов yoba1 (безо всяких проверок и if-ов), а если есть возможность на текущей итерации зафолдить yoba1(i) (например окажется что это константа), то мы вообще сэкономим весь луп, ну целиком (почти миллион итераций). Если вдруг компилятор все-таки догадается вынести хитро условие за внутренний цикл - можно усложнить пример, засунув внутренний луп в другую функцию. С точки зрения трассирующего джита разницы не будет никакой, а вот обычный компилятор не справится уже гарантировано, том случае если ф-я не будет заинлайнена.

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

Вообще интересно было бы посмотреть на ЯП спроектированный _под_ трассирующий джит.

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

Выполняет по очереди формы (a), (b), (c), (d).

Ну ты совсем медленный. Повторяю еще раз: (b) раскрывается в label, (c) раскрывается в (go label). Итак, что делает (prog (a) (b) (c) (d))? Правильный ответ - «хрен его знает, что он делает».

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

Бред. Смотри пример выше - из контекста ничего не понятно. А для функции я из контекста знаю типы аргументов и тип возвращаемого значения.

Может, конечно. Например изменить состояние глобальных переменных.

На то они и глобальные. А вот в случае с (let ((a ...)) (f) (g a)) мы не знаем, делает ли f что-то c a. Если бы это была функция - знали бы точно, что ничего не делает. С макросом же - не знаем и знать не можем. И не надо про гигиену - она обходится.

Мы уже выяснили, что это проблема препроцессоров, а не макросов. Макросы никуда не срут.

Смотри пример выше.

В макросистемах сайд-эффекты изолируются на уровне рантайма (именно из-за своей опасности, да).

А если без сайд-эффектов, то на кой это говно вообще нужно? Единственный хоть немного оправданный пример применения макросов - вытащить структуру из СУБД и нагенерить boilerplate-кода для доступа. Или прочитать XML Schema и нагенерить из нее классов.

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

Лисп - императивный язык с некоторыми элементами ФП. Не будь тупицей.

Нет, это функциональный ЯП. В то время никаких таких «элементов ФП» не было. Это сейчас ФП языков куча и речь зашла о «элементах», а классическое ФП - это именно лисп. ГЦ, замыкания, лямбды, динамика.

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

Пруф или не было.

Дак, это давно известный на ЛОРе факт, что я лиспом на хлеб/двухподвес/Вольво (две) зарабатывал.

И сколько человек (и за какие деньги) это говно поддерживает?

Говно - это твоя никчёмная сущность, а проект писал я один. Кое-какую алгоритмическую лабуду закодировал наш CTO, поддержку SNMP написал ньюхайр в рамках знакомства с системой. ~200 программ на DSL написали железячники, что, каг бе, намекает на простоту использования DSL простыми смертными.

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

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

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

Это смотря какой компилятор. Если even определена в этом же модуле, и оптимизация просматривает весь модуль - сделает; если even из другого модуля этой же программы, и оптимизатор просматривает всю программу - то же самое.

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

вот обычный компилятор тут ничего особо не сделает. Ну банальные loop-unrolling и т.п., а трассирующий джит для каждого i уберет проверку even и будет выполнять во внутреннем лупе либо вызов yoba2, либо вызов yoba1

Проверим. Получается, ты лжешь про «обычные компиляторы»:

int even(int i) { return !(i%2); }

extern void yoba1(int);
extern void yoba2(int);


void test() {
  for (int i = 0; i < 1000; i++){
    for (int j = 0; j < 1000000; j++){
      if (even(i)) yoba1(i); else yoba2(j);
    }
  }
}

LLVM:

define i32 @even(i32 %i) nounwind uwtable readnone ssp {
  %1 = and i32 %i, 1
  %2 = xor i32 %1, 1
  ret i32 %2
}

define void @test() nounwind uwtable ssp {
  br label %.preheader

.preheader:                                       ; preds = %.us-lcssa.us, %0
  %i.02 = phi i32 [ 0, %0 ], [ %5, %.us-lcssa.us ]
  %1 = and i32 %i.02, 1
  %2 = icmp eq i32 %1, 0
  br i1 %2, label %.preheader2, label %.preheader1

.preheader2:                                      ; preds = %.preheader2, %.preheader
  %j.01.us = phi i32 [ %3, %.preheader2 ], [ 0, %.preheader ]
  tail call void @yoba1(i32 %i.02) nounwind
  %3 = add nsw i32 %j.01.us, 1
  %exitcond = icmp eq i32 %3, 1000000
  br i1 %exitcond, label %.us-lcssa.us, label %.preheader2

.preheader1:                                      ; preds = %.preheader1, %.preheader
  %j.01 = phi i32 [ %4, %.preheader1 ], [ 0, %.preheader ]
  tail call void @yoba2(i32 %j.01) nounwind
  %4 = add nsw i32 %j.01, 1
  %exitcond4 = icmp eq i32 %4, 1000000
  br i1 %exitcond4, label %.us-lcssa.us, label %.preheader1

.us-lcssa.us:                                     ; preds = %.preheader1, %.preheader2
  %5 = add nsw i32 %i.02, 1
  %exitcond5 = icmp eq i32 %5, 1000
  br i1 %exitcond5, label %6, label %.preheader

; <label>:6                                       ; preds = %.us-lcssa.us
  ret void
}

declare void @yoba1(i32)

declare void @yoba2(i32)
psikh
()
Ответ на: комментарий от psikh

Ну ты совсем медленный. Повторяю еще раз: (b) раскрывается в label, (c) раскрывается в (go label).

Опять проблемы препроцессоров, ты заебал. Я не говорил про препроцессоры. я говорю про _макросы_.

Итак, что делает (prog (a) (b) (c) (d))?

Я уже ответил - по очереди исполняет формы (a) (b) (c) (d).

> Бред. Смотри пример выше - из контекста ничего не понятно.

Странно, я почему-то все понял. Может, дело не в бобине?

А для функции я из контекста знаю типы аргументов и тип возвращаемого значения.

Правда? Допустим, в нашем языке макросов нет, что делает (prog (a) (b) (c) (d))?

На то они и глобальные.

Ну и макрос может ровно то же самое.

А вот в случае с (let ((a ...)) (f) (g a)) мы не знаем, делает ли f что-то c a.

Если по ссылке передали - тоже не знаем.

И не надо про гигиену - она обходится.

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

Смотри пример выше.

Какой именно? Про prog или про let?

А если без сайд-эффектов, то на кой это говно вообще нужно?

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

Единственный хоть немного оправданный пример применения макросов - вытащить структуру из СУБД и нагенерить boilerplate-кода для доступа. Или прочитать XML Schema и нагенерить из нее классов.

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

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