Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log arbitrary JSON-like object? #17

Closed
chexxor opened this issue May 10, 2018 · 3 comments
Closed

Log arbitrary JSON-like object? #17

chexxor opened this issue May 10, 2018 · 3 comments

Comments

@chexxor
Copy link

chexxor commented May 10, 2018

Looks like traceAny :: a -> Effect Unit was added to this library awhile ago, then later removed.

Some arguments against that type signature:

It violates free theorem which says it ignores its argument
Implementations not violating such derived theorems is generally assumed of APIs
For example:
f :: forall a b. Tuple a b -> Tuple b a swaps the elements of the tuple given
f :: forall a. List a -> List a all elements in the output also exist in the input
f :: forall a b. a -> List b ignores its argument and returns the empty list
It’s something you can say about a (polymorphic) function given only its type
@rightfold

There's also the argument that it's possibly not referentially transparent.

I think it should exist here, though, in some form.

The console.log docs on MDN says it accepts any JS object. All PS types are JS objects at runtime, so we could say that a -> Effect Unit is a good description.

On the other hand, we could describe it as Json -> Effect Unit, where Json is a type which represents a data structure of "idiomatic primitive JSON types" in JavaScript, like plain-old objects (not classes), arrays, numbers, and strings.

We could do a constraint on a and implement that constraint like justinwoo/simple-json did: Json a => a -> Effect Unit.

@chexxor chexxor changed the title Log arbitrary JSON object? Log arbitrary JSON-like object? May 10, 2018
@garyb
Copy link
Member

garyb commented May 10, 2018

Is there ever a good reason to log the representation of a value unless you're debugging? (In which case traceAny and friends live in purescript-debug).

@hdgarrood
Copy link
Contributor

I'm not convinced that it should exist here. This function would necessarily expose runtime representations of data, which, more often than not, are private implementation details (consider Map, for instance), and therefore likely to change in between, say, patch-level upgrades in your dependencies, which means a patch-level upgrade could become a breaking change.

If you want to print out a representation of some data at runtime for consumption by other tools, there are better options for this, such as simple-json or argonaut. If you want to just print any old representation for a data type which doesn't necessarily have a Show instance or whatever, for the sake of debugging, there are functions in purescript-debug for that (as you know).

@chexxor
Copy link
Author

chexxor commented May 10, 2018

Because @garyb asked for a case in which one would want to do this:

For practical motivations behind this topic, I am using a logging system which says "Structured logging: Single-line JSON objects written to standard output or standard error will be read into Stackdriver as structured log entries." So, I need to send an object to stdout, right? Well, after doing some testing, I discovered this documentation is wrong, and I need to send a JSON-formatted string to stdout. (I send them a support ticket to update that misleading doc.)

After discovering that stdout only accepts strings (duh, in hindsight), I decided to dig into how console.log works and how it could accept a JS object as an object. I found its source code in nodejs/node#v10.1.0 lib/console.js and discovered that it turns the arg into a string before putting it on stdout by using the seemingly non-standard formatWithOptions function in nodejs/node#v10.1.0 lib/util.js. That function uses the util.inspect function a lot, whose docs say it is very much intended for debug purposes.

So for my purposes, I think I no longer need a logAny function, as I'll just be doing the equivalent of console.log(JSON.stringify(a)) in PureScript. It looks like it works, and I'd like to have a bit more control over the serialization.

If the formatting starts doing differently than I expect, I'll just switch to process.stdout.write(JSON.stringify(a) + "\n").

So, for people who come to this issue later: Do you really want to use logAny in a "production worthy" purpose? If so, did you know that the console.log(a :: AnyType) function actually does a non-standard serialization into a String? Knowing that, are you sure you want to logAny? If you want reliable, machine-consumable logs, you'll want to log as a standard JSON-formatted string.

@chexxor chexxor closed this as completed May 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants