Я хотел бы реализовать функциональный стек в схеме. Это моя попытка:
(define make-stack
(letrec ((do-op
(lambda (stack op . val)
(cond ((eq? op 'push)
(lambda (op . v)
(do-op (cons (car val) stack) op v)))
((eq? op 'pop)
(lambda (op . v)
(do-op (cdr stack) op v)))
((eq? op 'print)
(begin (display stack)
(newline)
(lambda (op . v)
(do-op stack op v))))))))
(lambda (op . val)
(do-op '() op val))))
Стек можно использовать, как в этом примере:
(define s make-stack)
((((((s 'push 1) 'push 2) 'push 3) 'print) 'pop) 'print)
Результат этого примера:
((3) (2) (1))
((2) (1))
Не совсем то, что я хотел, но не так уж и плохо. Хотел тут спросить у опытных схемщиков, есть ли способ заставить стек вести себя более естественно, например вот так:
(define s make-stack)
(s 'push 1)
(s 'push 2)
(s 'pop)
...
сохраняя при этом его функциональность (поэтому нет изменчивости, нет set!
).
Первое, о чем я подумал, это продолжать возвращать функцию без аргументов, но меняя каждые lambda (op . v)
с помощью:
(lambda ()
(lambda (op . v)
...
но это не работает, так как нам все еще нужно захватить возвращаемую функцию:
> (define s make-stack)
> ((s) 'push 1)
#<procedure>
cons
,car
иcdr
эквивалентныpush
,peek
иdelete
:-opop
равноpeek
+delete
, но в функциональном стеке это невозможно, - person Sylwester   schedule 25.10.2020