Схема прохождения по ссылке - PullRequest
8 голосов
/ 16 июля 2010

Как передать переменную по ссылке в схеме?

Пример функциональности, которую я хочу:

(define foo
  (lambda (&x)
    (set! x 5)))

(define y 2)

(foo y)

(display y) ;outputs: 5

Кроме того, есть ли способ вернуть по ссылке?

Ответы [ 7 ]

10 голосов
/ 16 июля 2010

См. http://community.schemewiki.org/?scheme-faq-language вопрос «Есть ли способ эмулировать вызов по ссылке?».

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

3 голосов
/ 16 июля 2010

Как сказал Яри, обычно вы хотите избегать передачи по ссылке в Схеме, поскольку это говорит о том, что вы злоупотребляете побочными эффектами.

Однако, если вы хотите, вы можете заключить все, что хотите пройтиссылка в поле cons.

(cons 5 (void))

приведет к созданию поля, содержащего 5. Если вы передадите это поле процедуре, которая изменит 5 на 6, ваша исходная коробка также будет содержать 6. изКонечно, вы должны помнить cons и car, когда это уместно.

Схема Чеза (и, возможно, другие реализации) имеет процедуру с именем box (и ее компаньоны box? и unbox)специально для этой упаковки / распаковки ерунды: http://www.scheme.com/csug8/objects.html#./objects:s43

2 голосов
/ 25 января 2012

Вы можете использовать макрос:

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
2 голосов
/ 17 июля 2010

Яри прав, это несколько бессмысленно передавать по ссылке, по крайней мере, с переменными.Однако требуемое поведение используется и часто поощряется все время в более похожей схеме с использованием замыканий. Страницы 181 и 182 (google books) в закаленной схеме лучше, чем я могу объяснить это.

Вот ссылка, которая дает макрос, который позволяет вам использовать ac каксинтаксис «передать по ссылке».Сайт Olegs - золотой рудник для интересных чтений, поэтому обязательно отметьте его, если вы еще этого не сделали.

http://okmij.org/ftp/Scheme/pointer-as-closure.txt

2 голосов
/ 16 июля 2010

лямбда!

(define (foo getx setx)
  (setx (+ (getx) 5)))

(define y 2)
(display y)(newline)

(foo
 (lambda () y)
 (lambda (val) (set! y val)))

(display y)(newline)
1 голос
/ 29 октября 2014

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

(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)), (unbox x) и т. Д., Как указано в подкомментарии Eli, что совпадает с решением против, предложенным erjiang.

0 голосов
/ 16 июля 2010

Возможно, вы слишком много используете C, PHP или что-то еще.В схеме вы не хотите делать что-то вроде pass-by- *.Сначала поймите, что означает область действия и как ведут себя различные реализации (в частности, попытайтесь выяснить, в чем отличие LISP от Scheme).

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

...