Scheme pass-by-reference
Asked Answered
G

7

11

How can I pass a variable by reference in scheme?

An example of the functionality I want:

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

(define y 2)

(foo y)

(display y) ;outputs: 5

Also, is there a way to return by reference?

Gravelblind answered 16/7, 2010 at 5:17 Comment(0)
I
12

See http://community.schemewiki.org/?scheme-faq-language question "Is there a way to emulate call-by-reference?".

In general I think that fights against scheme's functional nature so probably there is a better way to structure the program to make it more scheme-like.

Iconography answered 16/7, 2010 at 5:33 Comment(2)
Cool, thanks. Good to know, but it looks like I should probably figure out a better way to do what I'm trying to do :)Gravelblind
That's a good reference on emulating a "by-reference" argument using boxes -- and note that the result of using box, unbox and set-box! is very close to using an explicit pointer in C. Also, it's rare to use such a thing, but it can be useful on some occasions -- Scheme encourages functional programming and discourages mutation, but it doesn't have some fundamental objection to doing so. (But in most cases it is likely that newbie-code doing this needs some rethinking.)Nasa
L
4

Like Jari said, usually you want to avoid passing by reference in Scheme as it suggests that you're abusing side effects.

If you want to, though, you can enclose anything you want to pass by reference in a cons box.

(cons 5 (void))

will produce a box containing 5. If you pass this box to a procedure that changes the 5 to a 6, your original box will also contain a 6. Of course, you have to remember to cons and car when appropriate.

Chez Scheme (and possibly other implementations) has a procedure called box (and its companions box? and unbox) specifically for this boxing/unboxing nonsense: http://www.scheme.com/csug8/objects.html#./objects:s43

Loleta answered 16/7, 2010 at 5:40 Comment(0)
U
4

You can use a macro:

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
Urogenous answered 25/1, 2012 at 5:1 Comment(0)
N
2

lambda!

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

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

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

(display y)(newline)
Neoplatonism answered 16/7, 2010 at 15:52 Comment(1)
this seems different than what the question asked for (i.e. foo here takes two arguments, not one)Urogenous
C
2

Jari is right it is somewhat unscheme-like to pass by reference, at least with variables. However the behavior you want is used, and often encouraged, all the time in a more scheme like way by using closures. Pages 181 and 182(google books) in the seasoned scheme do a better job then I can of explaining it.

Here is a reference that gives a macro that allows you to use a c like syntax to 'pass by reference.' Olegs site is a gold mine for interesting reads so make sure to book mark it if you have not already.

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

Cowbell answered 16/7, 2010 at 20:17 Comment(0)
C
2

You can affect an outer context from within a function defined in that outer context, which gives you the affect of pass by reference variables, i.e. functions with side effects.

(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

This solution limits the scope of the side effects.

Otherwise there is (define x (box 5)), (unbox x), etc. as mentioned in a subcomment by Eli, which is the same as the cons solution suggested by erjiang.

Chilblain answered 29/10, 2014 at 7:9 Comment(0)
N
0

You probably have use too much of C, PHP or whatever. In scheme you don't want to do stuff like pass-by-*. Understand first what scope mean and how the different implementation behave (in particular try to figure out what is the difference between LISP and Scheme).

By essence a purely functional programming language do not have side effect. Consequently it mean that pass-by-ref is not a functional concept.

Neomineomycin answered 16/7, 2010 at 11:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.