Croc icon indicating copy to clipboard operation
Croc copied to clipboard

Provide means to dump objects similar to tables (json)

Open ligustah opened this issue 13 years ago • 12 comments

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?

ligustah avatar Aug 17 '12 06:08 ligustah

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?

JarrettBillingsley avatar Aug 17 '12 20:08 JarrettBillingsley

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.

ligustah avatar Aug 17 '12 20:08 ligustah

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.

JarrettBillingsley avatar Aug 18 '12 07:08 JarrettBillingsley

Wouldn't allFieldsOf get the job done then? Or would it be better to simply ignore unset fields? Or provide both?

ligustah avatar Aug 18 '12 08:08 ligustah

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.

JarrettBillingsley avatar Aug 18 '12 08:08 JarrettBillingsley

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
        }
}

ligustah avatar Aug 19 '12 07:08 ligustah

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!

JarrettBillingsley avatar Aug 19 '12 09:08 JarrettBillingsley

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

ligustah avatar Aug 19 '12 10:08 ligustah

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!

JarrettBillingsley avatar Aug 19 '12 11:08 JarrettBillingsley

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.

ligustah avatar Aug 19 '12 12:08 ligustah

Hmm! HMMMMMMMMMM!

Hmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm

JarrettBillingsley avatar Aug 19 '12 23:08 JarrettBillingsley

:O

ligustah avatar Aug 22 '12 17:08 ligustah