Presenting collections for code generation I've never been too bothered by the lack of present (and thus print) support for Factor collections and other objects, but I've never needed to generate Factor programs from JSON until now.

To that end, I use these methods to turn arrays, hashtables and assocs into roundtrippable strings:

M: f present
  drop "f" ;

M: array present
  [
    [
      dup string? [
        "\"" dup surround
      ] when
      present
    ] map
  ]
  [ length ]
  bi
  [ "%s " ] replicate "" join
  vsprintf "{ " " }"  surround ;

M: assoc present
  { } assoc-clone-like present ;

M: hashtable present
  { } assoc-clone-like present "H" prepend ;


The array method was written rather haphazardly as I tried to find something that seemed robust. The way the elements are finally formatted, using replicate and vsprintf may seem sloppy but it looks better than an until, and sprintf can't be used on non-constant values.

The recursive nature allows it to be cleverly repurposed for other collection types and on arbitrarily deeply nested arrays. Moreover, string literals in arrays preserve their "quotes" so they roundtrip too, which I initially struggled with.

But, can it be improved? The goal is that any collection converts into a string and evals back into its original value (called roundtripping), which it does:

IN: scratchpad { 1 { 2 3 } "4" 5 } present ( -- x ) eval

--- Data stack:
{ 1 ~array~ "4" 5 }
IN: scratchpad H{ { 1 "a" } { 2 3 } { "4" 5 } } present ( -- x ) eval

--- Data stack:
{ 1 ~array~ "4" 5 }
H{ { 1 "a" } { 2 3 } { "4" 5 } }
can it be improved?


Looks good to me.

Ship it.

The program accomplishes its goals, and it is clear. The length seems about right for what it does.