Схема прохождения по ссылке
Как я могу передать переменную по ссылке в схеме?
Пример функциональности, которую я хочу:
(define foo
(lambda (&x)
(set! x 5)))
(define y 2)
(foo y)
(display y) ;outputs: 5
Кроме того, есть ли способ вернуться по ссылке?
7 ответов
См. http://community.schemewiki.org/?scheme-faq-language вопрос "Есть ли способ эмулировать вызов по ссылке?".
В целом, я думаю, что это противоречит функциональности схемы, поэтому, возможно, есть лучший способ структурировать программу, чтобы сделать ее более похожей на схему.
Как сказал Яри, обычно вы хотите избегать передачи по ссылке в Схеме, поскольку это говорит о том, что вы злоупотребляете побочными эффектами.
Если вы хотите, однако, вы можете заключить все, что вы хотите передать по ссылке в cons
коробка.
(cons 5 (void))
создаст окно, содержащее 5. Если вы передадите это поле процедуре, которая изменит 5 на 6, ваша исходная коробка также будет содержать 6. Конечно, вы должны помнить cons
а также car
когда уместно.
Схема Chez (и, возможно, другие реализации) имеет процедуру под названием box
(и его спутники box?
а также unbox
) специально для этой упаковки / распаковки ерунды: http://www.scheme.com/csug8/objects.html
Вы можете использовать макрос:
scheme@(guile-user)> (define-macro (foo var)`(set! ,var 5))
scheme@(guile-user)> (define y 2)
scheme@(guile-user)> (foo y)
scheme@(guile-user)> (display y)(newline)
5
Лямбда!
(define (foo getx setx)
(setx (+ (getx) 5)))
(define y 2)
(display y)(newline)
(foo
(lambda () y)
(lambda (val) (set! y val)))
(display y)(newline)
Яри прав, это несколько бессмысленно передавать по ссылке, по крайней мере, с переменными. Однако требуемое поведение используется и часто поощряется все время в более похожей схеме с использованием замыканий. Страницы 181 и 182(книги Google) в закаленной схеме лучше, чем я могу объяснить.
Вот ссылка, которая дает макрос, который позволяет вам использовать синтаксис ac like для "передачи по ссылке". Сайт Olegs - золотой рудник для интересных чтений, поэтому обязательно отметьте его, если вы еще этого не сделали.
Вы можете влиять на внешний контекст изнутри функции, определенной в этом внешнем контексте, что дает вам эффект передачи по ссылочным переменным, то есть функциям с побочными эффектами.
(define (outer-function)
(define referenced-var 0)
(define (fun-affects-outer-context) (set! referenced-var 12) (void))
;...
(fun-affects-outer-context)
(display referenced-var)
)
(outer-function) ; displays 12
Это решение ограничивает объем побочных эффектов.
В противном случае есть (определите x (вставка 5)), (снимите флажок x) и т. Д., Как указано в подкомментарии Eli, что совпадает с решением против, предложенным erjiang.
Вы, наверное, слишком много используете C, PHP или что-то еще. В схеме вы не хотите делать что-то вроде прохода мимо *. Сначала поймите, что означает область действия и как ведут себя различные реализации (в частности, попытайтесь выяснить, в чем разница между LISP и Scheme).
По сути, чисто функциональный язык программирования не имеет побочных эффектов. Следовательно, это означает, что передача по ссылке не является функциональной концепцией.