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

Started by jeremyc, March 08, 2007, 07:31:09 PM

Previous topic - Next topic

jeremyc

I have the follow function:



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


I want to be able to:



(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?

jeremyc

#1
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:



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

Lutz

#2
yes, you can do it that way, but you can also package your list into a name space and then pass it by reference:


(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

cormullion

#3
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:


(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 :-)

Lutz

#4
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