Михаил, спасибо!

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

Я не проблем вижу проблем с ТСО для такого расширенного лямбда-выражения,
потому и удивился. Это было мое недопонимание. Спасибо, вопрос закрыт.

Всего наилучшего,
Андрей


2017-08-07 14:11 GMT+03:00 Mike Potanin <[email protected]>:

> Потому что от того, была выполнена эта оптимизация или нет, зависит
> семантика неконстантных методов объекта-функции. В исходном
> джаваскрипте TCO не было. Сейчас она допускается и для этого, как
> минимум, метод arguments у объектов-функций объявлен deprecated.
>
> 2017-08-07 13:04 GMT+03:00 Andrei Klimov <[email protected]>:
> > Михаил,
> >
> > А я не понял: почему обсуждаемые конструкции мешают Tail Call
> Optimization?
> > По идее, если вызов действительно хвостовой (поверх него ничего нет), то
> что
> > мешает это заметить и преобразовать в цикл?
> >
> > Андрей
> >
> > 7 авг. 2017 г. 11:20 пользователь "Mike Potanin" <[email protected]>
> > написал:
> >
> >> На мой взглад доступ с фреймам вызова функции через специальный объект
> >> в джаваскрипте - решение неудачное, так как оно не позволяет
> >> производить TCO. В функциональном языке какие-то варианты TCO очень
> >> важны, так как руками рекурсию в цикл превратить не получится.
> >>
> >> 2017-08-04 23:56 GMT+03:00 Александр Коновалов <[email protected]
> >:
> >> > Добрый вечер, Бойко!
> >> >
> >> > Понял вашу мысль. Вы фактически предлагаете аналог указателя «this»
> (или
> >> > «self») применительно к безымянным функциям. Идея интересная, но у
> меня
> >> > затык не с синтаксической конструкцией, а с представлением во время
> >> > выполнения. Хоть с именами, хоть с this’ом взаимная рекурсия с
> возвратом
> >> > указателя неизбежно конфликтует (а) с требованиями к равенству двух
> >> > указателей на функцию, (б) с использованием простого счётчика ссылок
> для
> >> > управления памятью.
> >> >
> >> > Почему нет такой конструкции в большинстве языков программирования?
> >> > Во-первых, инертность мышления (а что, и так тоже можно?), во-вторых,
> нужна
> >> > редко. Обычно ко вложенной безымянной функции относятся не как к
> функции, а
> >> > как к блоку кода, который воспринимается как некий фрагмент устойчивой
> >> > конструкции, функции map, играющей роль цикла. Вложенные безымянные
> функции
> >> > обычно небольшие и играют роль части выражения. Если нужно выразить
> более
> >> > сложную логику, то её оформляют как отдельную функцию, которой уже
> логично
> >> > дать соответствующее имя (независимо от наличия рекурсии внутри).
> Вообще,
> >> > лучший способ прокомментировать блок кода — не писать комментарий
> перед ним,
> >> > а вынести его в отдельную функцию и дать ей ясное понятное название.
> >> >
> >> >
> >> > Не могу не поделиться одной историей. В этом году я разрешил студентам
> >> > сдавать лабораторные на необычных языка программирования, при этом
> одна
> >> > лабораторная засчитывалась за три. Среди таких языков был Smalltalk.
> Порог
> >> > вхождения у него низкий: посмотрев на примеры кода и найдя
> документацию по
> >> > стандартной библиотеке, уже можно писать немаленькие (сотни строк
> кода)
> >> > работающие программы. При этом вникать в устройство языка не
> обязательно.
> >> >
> >> > Так вот. «Условный оператор» в Smalltalk выглядит так: (x < y) ifTrue:
> >> > […] ifFalse: […]., «цикл» — [x < y] whileTrue: […].. Так вот. Это не
> >> > условный оператор и не цикл. Текст в квадратных скобках — это не блок
> кода
> >> > (как {…} в C++), а лямбда. Безымянная функция (вернее, безымянный
> класс с
> >> > методом call, если я ничего не путаю). Булевский класс имеет двух
> потомков,
> >> > соответственно, True и False. У первого метод ifTrue: f1 ifFalse f2.
> >> > выполняет замыкание f1, у второго — f2. У самого класса замыкания,
> помимо
> >> > метода call, есть метод whileTrue: func., который вычисляет себя и
> свой
> >> > аргумент в цикле, пока сам себе возвращает значение True.
> >> >
> >> > А значит, вместо (x < y) ifTrue: […] ifFalse: [……]. можно написать: f1
> >> > := […]. f2 := [……]. (x < y) ifTrue: f1 ifFalse f2. Аналогично с
> «циклом»
> >> > whileTrue: f3 := [x < y]. f4 := […]. f3 whileTrue: f4..
> >> >
> >> > Когда я это объяснял студентам (и делал замены из предыдущего абзаца),
> >> > только что написавшим (и правильно написавшим) лабораторную, они
> удивлялись.
> >> > Оказывалось, что в языке нет управляющих конструкций кроме создания
> блока,
> >> > вызова метода и ^ (так обозначается возврат из метода). Ветвление и
> цикл —
> >> > методы библиотечных классов.
> >> >
> >> > Это я рассказал к тому, что безымянные функции вкупе с функциями
> >> > стандартной библиотеки (map, fold, filter и другие) воспринимаются как
> >> > цельные синтаксические конструкции, фактически, как встроенные
> операторы
> >> > языка. Помимо Smalltalk’а (а он позиционируется как
> >> > объектно-ориентированный, а не функциональный), могучая синтаксическая
> >> > поддержка таких конструкций есть в Ruby и Kotlin’е (не
> программировал, могу
> >> > что-то путать ошибаться). В последнем, например, если функция/метод
> >> > принимает последним аргументом функцию, то её можно записывать как
> просто
> >> > блок в фигурных скобках _вне_ круглых скобок: вместо foo(x, y, {…})
> можно
> >> > писать foo(x, y) {…}. Если аргумент единственный — скобки не нужны:
> foo({…})
> >> > эквивалентно foo {…}. Что и позволяет писать конструкции, выглядящие
> почти
> >> > как нативные синтаксические конструкции (типа if(…) {…}).
> >> >
> >> > -----Original Message-----
> >> > From: Boyko Bantchev [mailto:[email protected]]
> >> > Sent: Friday, August 4, 2017 10:28 AM
> >> > To: [email protected]
> >> > Subject: Re: FW: Рефал умер?
> >> >
> >> > Здравствуйте, Александр!
> >> >
> >> >> Вы не могли бы пояснить, что вы имеете ввиду под «цитированием себя и
> >> >> охватывающей функции при помощи … стандартной пары знаков или имён»?
> >> >
> >> > Имею ввиду возможность, заложенную в языке, любой функции вызывать
> себя
> >> > через какое-то фиксированное, универсальное для этой роли имя.
> >> > Ну, или передавать свой адрес кому-то еще.  Подобно местоимениям «я»
> или
> >> > «себя»/«себе» в человеческой речи — человек говорит о себе, не
> нуждаясь в
> >> > имени.  Местоимение одно и то же, но относится к разным людям в
> зависимости
> >> > от того, кто говорит.  Конкретный синтаксис неважен.
> >> >
> >> > Один из совсем немногих языков, где это имеется — это JavaScript.
> >> > Дам пример на нем.
> >> >
> >> > В этом языке у каждой функций имеется (составная) переменная
> arguments,
> >> > а у arguments имеется часть callee.  Так вот, arguments.callee — это
> то, о
> >> > чем я говорю.  В результате можно написать, скажем, анонимный
> рекурсивный
> >> > факториал:
> >> >
> >> > function(n) {return n<2 ? 1 : n*arguments.callee(n-1)}
> >> >
> >> > и вызвать его можно так:
> >> >
> >> > (function(n) {return n<2 ? 1 : n*arguments.callee(n-1)})(5)
> >> >
> >> > (или передать кому-нибудь как значение, а вызывать будет уже он сам).
> >> >
> >> > Еще пример: обращение связанного списка функцией reverse.
> >> > reverse создает вложенную функцию с двумя аргументами (из первого она
> >> > накапливает результат во второй) и тут же ее вызывает.  Вложенная
> функция
> >> > рекурсивна и анонимна.
> >> >
> >> > function reverse(x) {
> >> >   return (function(x,y) {
> >> >     if (x) {
> >> >       var r = x
> >> >       x = x.next
> >> >       r.next = y
> >> >       return arguments.callee(x,r)
> >> >     }
> >> >     return y
> >> >   })(x,null)
> >> > }
> >> >
> >> > (А список может быть, скажем, такой:
> >> >
> >> > list = {data:1}
> >> > list = {data:2, next:list}
> >> > list = {data:3, next:list}
> >> > )
> >> >
> >> > Иногда полезно подобным стандартным анонимным образом вызывать и
> >> > охватывающую функцию, возможно даже и ту, которая, в свою очередь, ее
> >> > охватывает — это позволяет уже взаимную анонимную рекурсию, но таких
> средств
> >> > ни в JavaScript, ни в других языках не видел.  (Сам я такое свойство
> вложил
> >> > в своем полуреализованном языке, но миру от этого мало пользы :) )
> >> >
> >> > Бойко
>

Ответить