Page 1 of 1

nth-set in side a function, affecting parameter value?

Posted: Fri Mar 09, 2007 3:31 am
by jeremyc
I have the follow function:

Code: Select all

(define (seg-name seg val) (if val (nth-set 0 seg val)) (seg 0))
I want to be able to:

Code: Select all

(set 'seg '("NM1" "85" "DEF"))
(println (seg-name seg)) ;; "NM1"
(seg-name seg "HL2")
(println (seg-name seg)) ;; "HL2" ---- that's what I want
(println (seg-name seg)) ;; "NM1" ---- is what I actually get
Is there any way to accomplish this? nth-set is a destructive operation, however, it appears to only be working on "seg" inside of the function, not the "seg" in the parent namespace.

Any thoughts?

Posted: Fri Mar 09, 2007 3:58 am
by jeremyc
Ok, I figured out this to make things work, but not sure if it's the right or best or even only way to do it:

Code: Select all

(define-macro (seg-name seg val)
  (if val (nth-set 0 (eval seg) val)) 
  ((eval seg) 0))

Posted: Fri Mar 09, 2007 8:45 am
by Lutz
yes, you can do it that way, but you can also package your list into a name space and then pass it by reference:

Code: Select all

(set 'seg:seg '("NM1" "85" "DEF")) 


(define (seg-name s val)
    (if val (nth-set (s 0) val)) (s 0)) 


> (seg-name seg "NEW-NAME")
"NEW-NAME"
> seg:seg
("NEW-NAME" "85" "DEF")
> (seg 0)
"NEW-NAME"
> (seg 1)
"85"
> 

this works when using set-nth/nth-set with implicit indexing as in: (s 0)

Lutz

Posted: Fri Mar 09, 2007 6:49 pm
by cormullion
My understanding - which may be unreliable - is this. Your seg inside the function is a local symbol, which masks any global symbol with the same name, so you can't access it. To safely get a symbol into a function definition, make sure it stays unevaluated until the function runs:

Code: Select all

(define (seg-name _seg _val)
  (if _val 
    (nth-set 0 (eval _seg) _val)
    ((eval _seg) 0)))

(set 'seg '("NM1" "85" "DEF")) 
(println (seg-name 'seg)) 
;-> NM1

(seg-name 'seg "HL2") 
(println (seg-name 'seg))
;-> HL2
There's more about this in the manual under Passing objects by reference... Lutz shows a better way to do it, of course :-)

Posted: Fri Mar 09, 2007 10:16 pm
by Lutz
Yes this is all correct. With your last example we have now all three methods together to pass by reference:

(1) pass parameter as a quoted symbol into a 'define' function (cormullions example)

(2) pass parameter as an un-quoted symbols into 'define-macro' function (jermyc example)

(3) package data in namesspace using default symbol i.e. pass 'foo' 'foo:foo' and use implicit indexing (lutz example, see manual for variations)

Lutz