Provide means to dump objects similar to tables (json)
Having to transform any object to table before I can use dumpVal or toJSON on it seems like too much work. Shouldn't there be enough information to do that automatically?
Well dumpVal is more or less a debugging tool. It will call toString methods on class instances if they exist. I'd like to expand its capabilites though.
But toJSON.. I dunno, how would that even work?
I guess it would just call fieldsOf, then dump them recursively, like it does with tables. That's how PHP's print_r handles this at least.
The only problem with doing that is that it would only show those fields which have been assigned in the instance since it was created (since fields are lazily created). But hm.
Wouldn't allFieldsOf get the job done then? Or would it be better to simply ignore unset fields? Or provide both?
Well the thing about allFieldsOf is that it gets ALL the fields, including the methods.. which you can't exactly dump to JSON.
What would be a more robust solution would be to expand the json library to have something that calls user-defined methods in objects that take a callback and call the callback with the names and values of fields it wants to be serialized to JSON. So a class might have:
function opToJSON(sink: function)
{
sink("x", :x)
sink("y", :y)
}
Such a method is kinda boilerplatey and could be automatically generated with decorators.
Really the question is: just how far do you want to go with serializing stuff to JSON? Which fields do you and don't you serialize? It starts turning into an entire serialization framework which seems more like the domain of a third-party library.
I think it should really only serialize everything returned by fieldsOf, because why would I want to serialize implicit fields? Maybe do that as default, and use opToJSON if that one is found.
EDIT: Poor mans toJSON: https://gist.github.com/3393886 That one outputs:
C:\Users\Andre\Documents\GitHub\CrocHTML>croci tojson.croc
{
"e": "bla",
"f": {
"a": 1,
"b": 3
}
}
Well you won't necessarily always initialize every class field in the constructor. Consider something like:
class Thing
{
someCounter = 0
this() {}
function someAction()
{
:someCounter++
}
}
Here someCounter doesn't actually exist in the instance until you call someAction() on it at least once.
I mean if your thing works for your code, then that's great, but it isn't a general-purpose solution, which is what I'd prefer to have in the standard library :) And this is what second- and third-party libraries are for -- if you can come up with something really useful and general-purpose-ish, then you can make it into a library!
I see what you mean. Another thing though, toJSON currently fails for tables containing functions. Shouldn't it just ignore those? And if so, I wouldn't see a problem with applying the same logic to objects and allFieldsOf, right?
Edit: Slightly off-topic, but that initialization thingy got me taking care anyways, since I had used something like this:
class Thing
{
someList = []
this() {}
function someAction()
{
:someList ~= "foo"
}
}
Which by design ended up with me having a static list, which was not what I had expected. So I always initialize my fields in the constructor now! :P
Now you're getting into what sounds like really custom behavior X) Again, more the domain of an optional library, not the stdlib.
And yeah, that's .. an issue. I've never been quite satisfied with how that works. I could get rid of class field declarations but then you lose documentability. I could enforce initialization of the fields in the constructor but that could get real complex real fast and defeats the purpose of the lazy field creation (to save memory on fields which aren't modified). I could get rid of lazy field creation and just copy fields over to the new instance upon creation but then you don't know what to copy and what not to (not all function fields are necessarily methods!) and it still doesn't solve the reference field problem. Sigh!
I'm not sure if that's really custom behavior. JavaScript does the same actually: http://jsfiddle.net/kS6rG/ It just dumps everything it can, and ignores the rest.
About the initialization, I just started doing that, because it looks cleaner to me, and less error-prone.
Hmm! HMMMMMMMMMM!
Hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
:O