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

2017-08-04 23:56 GMT+03:00 Александр Коновалов <a.v.konovalo...@mail.ru>:
> Добрый вечер, Бойко!
>
> Понял вашу мысль. Вы фактически предлагаете аналог указателя «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:boyk...@gmail.com]
> Sent: Friday, August 4, 2017 10:28 AM
> To: refal@botik.ru
> 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, 
> ни в других языках не видел.  (Сам я такое свойство вложил в своем 
> полуреализованном языке, но миру от этого мало пользы :) )
>
> Бойко

Ответить