The following example _almost_ works but I seem to be missing the **magic 
incantation** to get a **safe** reference to a _non-ref_ content.

The following examples illustrates my conundrum:
    
    
    # I am trying to generate record references of already existing objects in 
sequence
    # (as to not duplicate the objects).  I am having difficulty figuring out 
how to set
    # store reference to non-ref items (Things) in a seq of references 
(RefThings).
    
    import algorithm, std/typeinfo
    
    const WORKING = false
    
    type
      Thing = object
        name: string
        word: string
        originalAddr: string
      
      RefThing = ref Thing
    
    var thingRefs: seq[RefThing]
    
    template memAddr(thing: untyped): string = $cast[uint](thing)
    
    proc showRefThings(title: string) =
      echo "\n", title
      for thingRef in thingRefs.mitems:
        echo memAddr thingRef, ": ", thingRef[]
    
    template showStruct(thing: untyped) =
      let name = thing.name
      echo "\n", name, " structure:"
      echo "Address: ", thing.memAddr
      echo "kind:    ", thing.toAny.kind
      echo "size:    ", thing.toAny.size
      echo "content: ", thing[]
    
    template makeRef(dest: untyped, source: untyped) =
      var dest: RefThing; new dest
      #***********************************
      when WORKING:
        dest[] = source # Actually allocates a new copy? :-(
      when not WORKING:
        dest = cast[RefThing](addr source)
      #***********************************
      dest.originalAddr = source.addr.memAddr
      showStruct dest
    
    
    # *** Minimal failing test case ***
    
    var # Setup Non-ref originals
      original1 = Thing(name: "Thing1", word: "CCC")
      original2 = Thing(name: "Thing2", word: "BB")
      original3 = Thing(name: "Thing3", word: "A")
    
    # Setup references to original items
    makeRef thing1, original1
    makeRef thing2, original2
    makeRef thing3, original3
    
    var things = [thing1, thing2, thing3] # references
    
    # Store reversed refs in the the sequence
    for thing in things.reversed: thingRefs.add thing
    
    # Simple payload on sequece of refs
    showRefThings "Reversed:"
    sort thingRefs
    showRefThings "Sorted:"
    
    
    Run

when **WORKING = true** the code **works as desired** but **makes needless 
copies** of the _originals_.
    
    
    Thing1 structure:
    Address: 4399796320
    kind:    akRef
    size:    8
    content: (name: "Thing1", word: "CCC", originalAddr: "4399656576")
    
    Thing2 structure:
    Address: 4399796384
    kind:    akRef
    size:    8
    content: (name: "Thing2", word: "BB", originalAddr: "4399656624")
    
    Thing3 structure:
    Address: 4399796448
    kind:    akRef
    size:    8
    content: (name: "Thing3", word: "A", originalAddr: "4399656672")
    
    Reversed:
    4399796448: (name: "Thing3", word: "A", originalAddr: "4399656672")
    4399796384: (name: "Thing2", word: "BB", originalAddr: "4399656624")
    4399796320: (name: "Thing1", word: "CCC", originalAddr: "4399656576")
    
    Sorted:
    4399796320: (name: "Thing1", word: "CCC", originalAddr: "4399656576")
    4399796384: (name: "Thing2", word: "BB", originalAddr: "4399656624")
    4399796448: (name: "Thing3", word: "A", originalAddr: "4399656672")
    
    
    Run

Changing **WORKING = false** generates the following:
    
    
    Thing1 structure:
    Address: 4523363968
    kind:    akRef
    size:    8
    content: (name: "Thing1", word: "CCC", originalAddr: "4523363968")
    
    Thing2 structure:
    Address: 4523364016
    kind:    akRef
    size:    8
    content: (name: "Thing2", word: "BB", originalAddr: "4523364016")
    
    Thing3 structure:
    Address: 4523364064
    kind:    akRef
    size:    8
    content: (name: "Thing3", word: "A", originalAddr: "4523364064")
    
    Reversed:
    4523364064: (name: "Thing3", word: "A", originalAddr: "4523364064")
    4523364016: (name: "Thing2", word: "BB", originalAddr: 
"4523364016\x00ng1\", 
\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x004523364064\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00")
    4523363968: (name: "Thing1", word: "CCC", originalAddr: 
"4523363968\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x004523363968\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00")
    
    Sorted:
    4523363968: (name: "Thing1", word: "CCC", originalAddr: 
"4523363968\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x004523363968\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00")
    4523364016: (name: "Thing2", word: "BB", originalAddr: 
"4523364016\x00ng1\", 
\x00\x00\x00\x00\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x004523364064\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\n\x00")
    4523364064: (name: "Thing3", word: "A", originalAddr: "4523364064")
    
    
    Run

BTW: _I have no idea where the extra null bytes are coming from_

**So my question is:**

  1. Can _ref_ variables reference _non-ref_ data?
  2. If possible, how do I get **safe** references to the _non-ref_ data.
    _( I.e. what do I do in the star highlighted code above)_



Hopefully something like this is possible/availalbe as it permits operating on 
both _ref_ and _non-ref_ data in generic utility methods without having to make 
unnecessary copies of the originals, while still preserving type safety.

Thanks for any assistance :-)

Reply via email to