fenekku / moustachu

Mustache templating for Nim
65 stars 8 forks source link

feature proposal: a ".copy()" proc #14

Closed JohnAD closed 5 years ago

JohnAD commented 5 years ago

A copy of a Context creates a linked version. For example:

import moustachu

var a = newContext()
a["test"] = "hello"
var b = a

echo "a[test]=" & a["test"].toString()
echo "b[test]=" & b["test"].toString()

b["test"] = "world"

echo "change to only b made"

echo "a[test]=" & a["test"].toString()
echo "b[test]=" & b["test"].toString()

produces the following output:

a[test]=hello
b[test]=hello
change to only b made
a[test]=world
b[test]=world

In and of itself, I think this is okay. Such is the nature of pointers to complex structures. But it would be convenient if there were a function that operated like either this:

var b = a.copy()

or perhaps:

var b = newContext(a)

where a brand new Context is created by parsing the full tree copying it's individual elements.

I'd be happy to write it. Interested?

JohnAD commented 5 years ago

It turned out to be easy to write. If interested, it looks like this in usage:

import moustachu

var a = newContext()
a["test"] = "hello"

var b = a
var c = newContext(a)

echo "a[test]=" & a["test"].toString()
echo "b[test]=" & b["test"].toString()
echo "c[test]=" & c["test"].toString()

b["test"] = "world"

echo "change to only b made"

echo "a[test]=" & a["test"].toString()
echo "b[test]=" & b["test"].toString()
echo "c[test]=" & c["test"].toString()

producing the following output:

a[test]=hello
b[test]=hello
c[test]=hello
change to only b made
a[test]=world
b[test]=world
c[test]=hello

The code is recursive, so not ideal, but it works:

proc newContext*(c: Context): Context =
  new(result)
  if c == nil:
    result.kind = CObject
    result.fields = initTable[string, Context](4)
  else:
    result.kind = c.kind
    case c.kind
    of CValue:
      result.val = c.val
    of CArray:
      result.elems = @[]
      for item in c.elems:
        result.elems.add(newContext(item))
    of CObject:
      result.fields = initTable[string, Context](4)
      for key, val in pairs(c.fields):
        result.fields[key] = newContext(val)
fenekku commented 5 years ago

Works for me 👍 (the newContext(c: Context) variant)