Return multiple values from a function.

For the Compleat Fan
Locked
netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Return multiple values from a function.

Post by netytan »

Hi guys,

I'm kinda new to Lisp in general so please forgive my ignorance here. I'm having a few problems with one function I'm writing, I can get it working by using append, and in theory i know what append does but i cant replicate this using (cons).

Somewhat annoying since it means i dont understand as much as i thought ;).

Code: Select all

(define positive-binary
  (lambda (number)
  "This function simply returns a list containing the binary
  representation of number."
    (cons
      (if (= (remainder number 2) 0)
        0
        1)
      (if (= number 1) ()
        (positive-binary
            (truncate (/ number 2)))))))
Please don't tell me the answer but any hints would be great. As you might of guessed this isn't newlisp but is in fact Scheme. All I'm after here is to construct a list from the numbers returned with new numbers added to the beginning of the list, like a reverse append i guess ;).

when putting 10 into the function the result should be 1010 but right now I'm getting 0101. Its not a reversal problem :) am just putting things onto the wrong end of the list it seems.

Thank in advance guys,

Mark.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

There is no fuction 'remainder' or 'truncate' in newLISP, use "%" or "mod" and 'floor' instead. The result of 'cons' will always be a list and 'cons' always adds the elements in front. Why not use 'append' it also works on strings and you can put the things to append in either order.

Lutz

Ps: if you insist on doing this in Scheme, you should put your questions in a Scheme users group.
Last edited by Lutz on Tue Dec 06, 2005 8:47 pm, edited 2 times in total.

eddier
Posts: 289
Joined: Mon Oct 07, 2002 2:48 pm
Location: Blue Mountain College, MS US

Post by eddier »

Since the digits are reverse order, try and change the order of the (if statements below the (cons

Code: Select all

  (cons
    (if (= number 1)
      ()
    (positive-binary
...
Just a guess! There is also a xcons (reverse cons) function in the "srfi 1" library.

Eddie

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

I'm not using NewLisp since Im required to do this in Scheme however this said general Lisp so i didnt think it would be a problem :). Very greatful for the fast reply, that really did suprise me.

When i reverse the order of them i get a list but its in reverse order. Maybe somone could produce an example append function so I can see how it works.

I don't want to use append because it requires another call to (list) and I'm trying to do this in the most efficient way I can :).

Code: Select all

|(positive-binary 10)
| (positive-binary 5)
| |(positive-binary 2)
| | (positive-binary 1)
| | (() . 1)
| |((() . 1) . 0)
| (((() . 1) . 0) . 1)
|((((() . 1) . 0) . 1) . 0)
so what i need to do is put them at the end of the previous version of the list, in its CDR place, in effect sticking another cons on the end.

Thanks again guys,

Mark.

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

I don't know Scheme. But this is how it works with newLisp:

Code: Select all

#!/usr/bin/newlisp

(define (binary x)
	"This function simply returns a list containing the binary representation of number."
	(cons
		(if (= (% x 2) 0)
			0
			1
		)
		(if (> x 1)
			(binary (/ x 2))
			'()
		)
	)
)

(println (reverse (binary 66)))
(exit)
Maybe it helps. Just convert it to Scheme.

Peter

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

Hey pete :).

Thanks for the help, thats what I have working at the moment, using (reverse) but ideally i wanted to get it working inside the function, I guess I'm just not thinking recusively yet.

Will take a closer look and see if I can gain something here,

Thanks again.

Mark.

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

OK this is an annoying problem indeed. I thought I had the solution but this was too hasty. Since I have nothing else to do:

Code: Select all

#!/usr/bin/newlisp

(define (binary x)
	"This function simply returns a list containing the binary representation of number."
  	(flat
		(cons
			(if (> x 1)
				(binary (>> x 1))
				'()
			)
			(if (= (% x 2) 0)
				0
				1
			)
		)
	)
)

(println (binary 66))
(exit)
This should work. You basically switch around the return values and flatten it out.

Peter

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

Thanks a lot Peter, I can see how that works :). I've decided to go with the (reverse) method though, I think it'd be more effiencent in the long run :). If i do it like this way i'd be calling another functions repretedly, alternatively calling reverse once should do it :).

Ideally i could just put the CAR of the recursive value in the first part of the list and put the new value in CDR however it doesn't want to play that way.

Does anyone know of a better way to collect and return multiple values?

Thanks a lot!

Mark.

Sammo
Posts: 180
Joined: Sat Dec 06, 2003 6:11 pm
Location: Loveland, Colorado USA

Post by Sammo »

My two cents:

Mark wrote: "Ideally I could just put the CAR of the recursive value in the first part of the list and put the new value in CDR however it doesn't want to play that way."

In newLisp as well as Scheme, a reasonable approach is to write in the language you wish you had, and then implement that language. (I think that's a rough quote of something Fred Brooks wrote.)

The language element you're missing -- namely, (rcons a b) -> (b a) -- is readily implemented in newLisp.

Code: Select all

(define (rcons a b)
  (reverse (cons a (reverse b))) )
With this function, you can write 'positive-binary' as you want to think about it. Following Peter's lead:

Code: Select all

(define (positive-binary x) 
  (rcons
    (if (= (% x 2) 0) 0 1)
    (if (<= x 1) '() (positive-binary (/ x 2))) )) 
Examples:
> (positive-binary 10)
(1 0 1 0)
> (positive-binary 0)
(0)
> (positive-binary 1)
(1)
> (positive-binary 66)
(1 0 0 0 0 1 0)
> (positive-binary 0x7FFF)
(1 1 1 1 1 1 1 1 1 1 1 1 1 1 1)

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

Thanks so much, thats just what I needed. However I was wondering if this would not better be implemented as a Macro, I'm not sure how NewLisps support for Macros is but Schemes really suck, it seems like very paper that talks about them and how to utilize them just doesn't work :(.

Just curious,

Thanks again :),

Mark.

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

Oh, really liked the advice about how you should write in the language you wish you had :). Haven't heard it put quite like that.

Mark.

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

This one doesn't need to reverse things:

Code: Select all

(define (binary x) 
   (append 
      (if (> x 1) (binary (/ x 2)) '()) 
      (if (= (% x 2) 0) '(0) '(1) ) 
   ) 
) 
and it is really short ;)

Lutz

netytan
Posts: 19
Joined: Tue Dec 06, 2005 8:22 pm

Post by netytan »

Lol yes :) tried that code right at the beginning however Scheme is a little bitch in this sense and you have to make sure that what your trying to append is also a list it throws.

The one I'm using right now simply does a (cons) to collect all of the results in positive-binary; i imagine negative-binary will do the same. I have this nice little function which does a conditional function call and reverses the results before returning.

Code: Select all

(define binary
  (lambda (number)
    "This function provides a simple generic front end to our
    positive/negative binary functions."
    (reverse
      ((if (> number 0)
        positive-binary
        negative-binary) number))))
As always please feel free to criticize I could really use any suggestions you guys could give while I'm getting to grips with Lisp :).

Very tidy in NewLisp. How does NewLisp compare for performance with Scheme and CL guys?

Lutz
Posts: 5289
Joined: Thu Sep 26, 2002 4:45 pm
Location: Pasadena, California
Contact:

Post by Lutz »

Even shorter!

Code: Select all

(define (binary x) 
   (append 
      (if (> x 1) (binary (/ x 2)) '()) 
      (list (% x 2))
   ) 
) 
Lutz

ps: didn't see your last post when I wroten this ;)

Fanda
Posts: 253
Joined: Tue Aug 02, 2005 6:40 am
Contact:

Post by Fanda »

Slower and uglier, but shows a different way:

Code: Select all

(define (log2 x)
  (div (log x) (log 2)))

(define (binary x)
  (let (mask 1 N (+ (log2 x) 1) result '())
    (dotimes (i N)
      (push (>> (& x mask) i) result)
      (setq mask (<< mask 1)))
    result))
Fanda

PS: This is what I remember from school ;-)

pjot
Posts: 733
Joined: Thu Feb 26, 2004 10:19 pm
Location: The Hague, The Netherlands
Contact:

Post by pjot »

Thanks so much, thats just what I needed. However I was wondering if this would not better be implemented as a Macro, I'm not sure how NewLisps support for Macros is but Schemes really suck, it seems like very paper that talks about them and how to utilize them just doesn't work :(.
There is such a thing as a macro in newLisp, but this may not be the same as with Scheme. Please read the newLisp docs at

http://www.newlisp.org/downloads/newlisp_manual.html
Very tidy in NewLisp.
One more reason to switch to newLisp immediately! ;-)

Peter

cormullion
Posts: 2038
Joined: Tue Nov 29, 2005 8:28 pm
Location: latiitude 50N longitude 3W
Contact:

Post by cormullion »

netytan wrote:Very tidy in NewLisp. How does NewLisp compare for performance with Scheme and CL guys?
There's benchmarking data out there and elsewhere on this site, but little real information, and even less knowledge or wisdom... :-)

http://shootout.alioth.debian.org/sandb ... &lang2=mzc

Presumably it's generally true that compiled languages are better for performance than interpreted ones? (I'm no expert so I wouldn't know...)

Locked