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

Q&A's, tips, howto's
Locked
jeremyc
Posts: 33
Joined: Wed Dec 06, 2006 3:33 am

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

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

jeremyc
Posts: 33
Joined: Wed Dec 06, 2006 3:33 am

Post 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))

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

Post 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

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

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

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

Post 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

Locked