random_namedtuple
cscherrer opened this issue · 1 comments
cscherrer commented
Hi @JeffreySarnoff , I'd like to contribute some of the things I've been working on lately. First up:
"""
random_namedtuple(width, depth; names='a':'z')
Generate a random nested named tuple. This is useful for tests.
Example:
julia> randnt(3,3)
(e = (o = (l = :l, e = :e, s = :s), d = (x = :x, e = :e, a = :a), a = (i = :i, u = :u, d = :d)),
f = (b = (y = :y, k = :k, o = :o), a = (b = :b, f = :f, k = :k), z = (j = :j, b = :b, u = :u)),
t = (b = (q = :q, k = :k, s = :s), c = (d = :d, u = :u, a = :a), h = (u = :u, c = :c, m = :m)))
"""
function random_namedtuple(width, depth; names='a':'z')
k = unique(Symbol.(rand(names, width)))
if depth ≤ 1
return namedtuple(k)(k)
else
nts = Tuple((randnt(width, depth-1; names=names) for _ in 1:length(k)))
return namedtuple(k)(nts)
end
end
Any thoughts on this? If you like it, where should it go?
JeffreySarnoff commented
Thank you. Some thoughts:
We should strive to comport with the interface to Random.rand
.
To generate symbols that serve as names, we can do something like
const LCASE = collect('a':'z');
function symbol(nchars::Int=1, offset::Int=0)
nchars = max(1, min(26, nchars))
ofs = max(0, min(offset, 26-nchars))
return Symbol(join(LCASE[1+ofs:nchars+ofs]))
end
symbols(n ,width; randwidth::Bool=false) =
randwidth ? [symbol(rand(1:width), i) for i=0:n-1] : [symbol(width, i) for i=0:n-1]
if the values are the same as the names (for simplicity)
function rand(::Type{NamedTuple}, n::Int)
nchars = (div(n, 26) + 1)
syms = Tuple(symbols(n, nchars))
return NamedTuple{syms}(syms)
end
however also using Ints for values should be supported, at minimum
rand(NamedTuple, n; nesting::Int=0, randnest::Bool=false)
should be built on above