Arc Forumnew | comments | leaders | submitlogin
Multiple Return Values
3 points by jsgrahamus 3159 days ago | 12 comments
Say I have a function, f, to which I pass multiple values and which returns more than 1 value.

One way I have found to do this is as follows:

  (def func1 (a b c) ... (list x y))
  ...
  (= result (func1 a b c))
  (= latitude (pop result))
  (= longitude (pop result))
Is there a better way to do this, where I can pass in the function, its arguments and the variables into which I want the return values stuffed?

TIA, Steve



2 points by jsgrahamus 3159 days ago | link

So say you have some variables to capture the return from one function so you can feed it into another 1 or more functions:

  (with (latitude 0 longitude 0
     result (func1 street-number street city state))
     (= latitude (pop result))
     (= longitude (pop result))
     (make-map latitude longitude)
     (func2 latitude)
     (func3 longitude))
Is there a better way of capturing the results of one function?

-----

2 points by akkartik 3159 days ago | link

  (let (latitude longitude)  (func1 street-number street city state)
     (make-map latitude longitude)
     (func2 latitude)
     (func3 longitude))

-----

3 points by akkartik 3159 days ago | link

The most elegant approach is to keep your func1 unchanged and call it like this:

  (let (latitude longitude) (func1 a b c)
    ..)
In general you want to try to avoid = in Lisp..

-----

2 points by jsgrahamus 3159 days ago | link

Thanks. So, how do you get the 2 results from func1 into latitude and longitude?

-----

2 points by akkartik 3159 days ago | link

My code snippet is doing that. The let is doing a sort of pattern matching and binding latitude to the first element of the result, and longitude to the second.

-----

2 points by zck 3159 days ago | link

I'll explain a little further, because Arc's let is unusual. Unlike most Lisps, the variable-value pairs are not themselves enclosed in parentheses.

In this code:

    (let (latitude longitude) (func1 a b c)
We're not binding latitude to the value of longitude, but binding that whole thing to the return value of (func1 a b c).

A simpler example:

    (let (name score) '("Steve Wiebe" 1064500)
      (prn name " was the first person to score over a million points in Donkey Kong, with a score of " score))
This prints:

    Steve Wiebe was the first person to score over a million points in Donkey Kong, with a score of 1064500

-----

3 points by jsgrahamus 3159 days ago | link

And, of course, the "regular" form of arc has no parentheses:

  arc> (let hat 5 (prn "hat = " hat))
  hat = 5
  "hat = "
  arc>

-----

2 points by jsgrahamus 3159 days ago | link

I thought that let looked odd, because I thought that with a let in arc, you had 1 variable/value pair. Thanks, zck, for pointing out the difference. And thanks, akkartik, for repeatedly telling me this.

-----

2 points by waterhouse 3156 days ago | link

The corresponding macro in Common Lisp has an 18-character name.

  ; SBCL
  * (destructuring-bind (x y) '(1 2) (+ x y))
  3
  ; Arc
  arc> (let (x y) '(1 2) (+ x y))
  3

-----

2 points by jsgrahamus 3159 days ago | link

Why avoid = in lisp/arc?

-----

1 point by akkartik 3159 days ago | link

As long as you use '=' it's easy to keep programming C or MUMPS in Lisp. Avoiding '=' forces you to give up old habits and become fluent with (writing as well as reading) deeply nested calls, 'let' and recursion. Those are some big reasons to use Lisp rather than imperative languages. So if you don't use them you're missing out.

-----

2 points by jsgrahamus 3159 days ago | link

Makes sense. Thanks.

It really does force me to think a different way. Painful sometimes, too.

-----