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

Add formatters for built-in values #19

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft

Conversation

lthibault
Copy link
Collaborator

In the spirit of #16, this PR adds formatting options for built-in values.

By convention:

  • %s returns an s-expression
  • %#s returns a human-readable representation

I considered inverting the two, but wanted to stay consistent with error formatting, where # means "pretty".

⏱️ Estimated review time: 15 min.
❌ WIP. Do not merge.

@lthibault lthibault added the enhancement New feature or request label Mar 20, 2021
@lthibault lthibault added this to the v1.0 milestone Mar 20, 2021
@lthibault lthibault requested a review from spy16 March 20, 2021 00:23
@lthibault lthibault self-assigned this Mar 20, 2021
@lthibault lthibault marked this pull request as draft March 20, 2021 00:23
@lthibault
Copy link
Collaborator Author

@spy16 I'm kinda struggling to sensibly define the formatting directives for Slurp values, and would welcome your input.

As I see it, there are basically three special formatting cases for values (as distinct from errors):

  1. Serialization (s-expressions)
    I want an exact representation of the value that can be parsed by a reader. I care about exact correctness.
  2. Pretty-Printing
    When calling (print x), the representation of x's value is intended purely for human consumption. Strings should be printed without quotes (i.e. "foo" and 'foo should both print as foo). Large containers should be output in full, albeit split across multiple lines and indented for readability.
  3. REPL output
    REPL output is a mix between serialization and pretty-printing. I want a convenient, human-readable representation of a value that preserves some information about type and contents. I should notably be able to distinguish a string from a symbol, i.e. "foo" and 'foo should print as "foo" and foo, respectively. It is however desirable to summarize large containers. For example, a very long vector could be shortened to [0 1 2 3 4 5 6 7 8 9 ...].

It seems like we can distill this behavior down to three orthogonal dimensions:

  1. Rendering vs Printing: rendering preserves type information; printing elides it.
  2. Representing vs Summarizing: representing displays the whole value; summarizing displays part of the value.
  3. Minification vs Formatting: minifying produces a compact output; formatting produces a multiline/indented output.

(These labels are a bit awkward, but bear with me...)

So returning to the use-cases at the beginning of this comment:

  • Case 1 requires rendering a minified representation.
  • Case 2 requires printing a formatted representation.
  • Case 3 requires rendering a minified summary.

An edge case would be applying case 2 to a container such as a vector. In this case, it seems like we should not elide type information for members of the container. Thus, rendering ["foo" 'bar] should produce ["foo" bar] and not [foo bar].

Assuming you agree with this assessment, the next question is "how do we encode this in formatting directives?". One approach is:

  • "%s" => print a minified representation => produces an s-expression
  • "%p" => render a minified representation => produces human-readable output with type-elision

From there, we could treat the $ modifier to mean "summarize", thus:

  • "%$s" => print a minified summary => produces a summarized s-expression
  • "%$p" => render a minified summary => produces human-readable summary output with type elision

Formatting can be achieved via #, thus:

  • "%#s" => print a formatted summary => produces a formatted s-expression
  • "%#p" => render a formatted summary => produces human-readable, formatted output with type elision
  • "%#$s" => print a formatted summary => produces a formatted, summarized s-expression
  • "%#$p" => render a formatted summary => produces human-readable, formatted summary output with type elision

Thoughts?

@spy16
Copy link
Owner

spy16 commented May 19, 2021

Sorry for the long delay in getting back.

I am bit confused here to be honest 😅 .. I see only 3 cases like you initially listed down (serialisation, pretty-printing, REPL output).. Even in those cases, serialisation and REPL output are similar except for the fact that REPL output should have some pretty formatting (like shortening long container)..

  1. serialisation -- use %s -- "foo", 'foo, [1 2 3 4 "foo" :bar 'baz] etc. (parsable)
  2. pretty-print -- use %v -- foo, foo, [1 2 3 4 "foo" :bar 'baz] etc. (non-containers are unquoted, values inside containers should be quoted i think)
  3. repl output -- use %#s or %$s -- "foo", 'foo, [1 2 3 ...] etc. -- here $ or # acts as the "pretty" modifier for serialisation.

Note: we could use v for serialisation and s for human readable string as well. in which case, the directives will be %v, %s and %#v respectively. other combination is to use %v which will be shortened serialisation (i.e., REPL output) and %+v which will be non-shortened version (i.e., serialisation) and %s will be human readable.

My only concern with so many combinations of printing is the added complexity & confusion. Hence, the suggestion to not distinguish symbol representation when serialised vs in REPL output (i.e., use 'foo for both)

@lthibault
Copy link
Collaborator Author

Hi @spy16 ! No worries, it's been a busy couple of months for me as well.

I am bit confused here to be honest 😅 .

To be honest ... me too 😝 . It seems I was overthinking this quite a bit, and looking for orthogonality where there is none.

In the hopes of restoring some clarity, let me just restate my wishlist. Using fmt, I want to be able to:

  1. serialize a form into a parseable s-expression.
  2. pretty-print a form so that I can e.g. visually inspect a big container.
  3. print a summary rendering of a form that fits in one line. Losing information is okay here.

My only concern with so many combinations of printing is the added complexity & confusion. Hence, the suggestion to not distinguish symbol representation when serialised vs in REPL output (i.e., use 'foo for both)

I like this. Also, I'm partial to %v for serialization and %s for a pretty-printed string. The v evokes "whole value". I prefer to use # as the modifier, since it's standard.

So in summary:

  1. serialisation -- use %v -- "foo", 'foo, [1 2 3 4 "foo" :bar 'baz] etc. (parsable)
  2. pretty-print -- use %s -- foo, foo, [1 2 3 4 "foo" :bar 'baz] etc. (non-containers are unquoted, values inside containers should be quoted i think)
  3. repl output -- use %#s -- "foo", 'foo, [1 2 3 ...] etc. -- here $ or # acts as the "pretty" modifier for serialisation.

Sound good?

@spy16
Copy link
Owner

spy16 commented May 21, 2021

Yes. That sounds good 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants