Other ways to pass variable by reference

Q&A's, tips, howto's
Locked
Fritz
Posts: 66
Joined: Sun Sep 27, 2009 12:08 am
Location: Russia

Other ways to pass variable by reference

Post by Fritz »

I`m trying to find some easy way to cut lists to the limited size.

Code: Select all

(0 100 '("Some" "long" "list"))
returns me first 100 dwellers of the list.

(By the way, expression

Code: Select all

(-100 100 '("Some" "long" "list"))
says: "ERR: list index out of bounds" if the list is not long enough. But same expression works ok with strings).

Then I have tried to create a function, that will push an item to the list and cut it to the size I need.

Code: Select all

(define (push-cut what where how-long)
  (push what where)
  (if (> (length where) how-long)
    (set 'where (0 how-long where)))
  0)
And... it won`t work. I have found some method in "Code Patterns": make a context and transfer variables like db:db.

But I`m pretty sure, there should be some other way to expain to the function, which variable I want to be pushed.

Kazimir Majorinc
Posts: 388
Joined: Thu May 08, 2008 1:24 am
Location: Croatia
Contact:

Re: Other ways to pass variable by reference

Post by Kazimir Majorinc »

Your error is that you assume that, if you call

(push-cut 7 L 3)


L and variable where can have *same* value. They cannot. It is ORO, one reference only. So, where is the solution? You must pass original reference, L, to the function, so function will "work" with original reference.

Code: Select all

(define (push-cut what where how-long)
  (push what (eval where))
  (if (> (length (eval where)) how-long)
      (set where (0 how-long (eval where)))
     0))
  
(set 'L '(1 2 3 4))
(push-cut 7 'L 3) 
(println L) ;(7 1 2)
If you do not like that apostrophe in (push-cut 7 'L 3) you can use macro

Code: Select all

(define-macro (push-cut what where how-long)
  (push (eval what) (eval where))
  (if (> (length (eval where)) (eval how-long))
      (set (eval 'where) (0 (eval how-long) (eval where)))
      0))

(set 'L '(1 2 3 4))
(push-cut (+ 1 6) L (+ 1 2))
(println L) ;(7 1 2)
And this is if you want it to work with more general references:

Code: Select all

(define-macro (push-cut what where how-long)
  (eval (expand '(begin (push (eval what) where)
                        (if (> (length where (eval how-long)))
                            (setf where (0 (eval how-long) where))
                            0))
                'where)))

(set 'L '(1 2 3 4))
(push-cut (+ 1 6) L (+ 1 2))
(println L) ;(7 1 2)

(set 'L '((1 2 3 4)(3 4 5 6) (5 6 7 8)))
(push-cut 12 (L 1) 2)
(println L) ;((1 2 3 4) (12 3) (5 6 7 8))
(exit)
Heavy use of eval might look strange, but, in my opinion, it is how it should be in Newlisp. If you do not use contexts.

Fritz
Posts: 66
Joined: Sun Sep 27, 2009 12:08 am
Location: Russia

Re: Other ways to pass variable by reference

Post by Fritz »

Thank you. I`ll try these variants now.

Locked