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

Automatically call toString if it exists? #21

Open
ciscoheat opened this issue Dec 27, 2015 · 14 comments
Open

Automatically call toString if it exists? #21

ciscoheat opened this issue Dec 27, 2015 · 14 comments

Comments

@ciscoheat
Copy link
Contributor

Would it be possible to automatically use toString for an object if that method is defined (as Java does), so you can make things like:

ComplexNumber a = new ComplexNumber(1.0, -2.0);
System.out.println(a); // outputs 1.0-2.0im
@jcoplien
Copy link
Owner

Den 27/12/2015 kl. 04.15 skrev Andreas notifications@github.com:

Would it be possible to automatically use toString for an object if that method is defined (as Java does), so you can make things like:

ComplexNumber a = new ComplexNumber(10, -20);
Systemoutprintln(a); // outputs 10-20im
Maybe. For this particular approach I might prefer:

    ComplexNumber a = new ComplexNumber(10, -20);
System.out.println((String)a)

You of course can define the toString method and then just do this;

ComplexNumber a = new ComplexNumber(10, -20);
System.out.println(a.toString())

But I/O in general may require more careful thinking. I don’t like the whole Java approach. The C++ approach is more ideologically sound but it’s quite complicated. I suspect that in the long term I may end up trying something along the lines of multiple dispatch (on a PrintStream and an object), which borrows heavily from the C++ approach (but which is complex in part because C++ doesn’t support multi-methods).

@ciscoheat
Copy link
Contributor Author

It's convenient to have a string representation of any object. What's the difference here that makes this code "unsurprising"?

int i = 123;
int o = new Something();

System.out.println(i.toString()); // Works
System.out.println(i); // Works

System.out.println(o.toString()); // Works
System.out.println(o); // Doesn't work, surprise?

@jcoplien
Copy link
Owner

Den 31/12/2015 kl. 11.56 skrev Andreas notifications@github.com:

It's convenient to have a string representation of any object. What's the difference here that makes this code "unsurprising"?

int i = 123;
int o = new Something();

System.out.println(i.toString()); // Works
System.out.println(i); // Works

System.out.println(o.toString()); // Works
System.out.println(o); // Doesn't work, surprise?

Reply to this email directly or view it on GitHub #21 (comment).

The difference is that I/O in trygve (inspire by Java) knows only about built-in types. And you are misled by a bit of coincidence. It is a total coincidence that:

System.out.println(i.toString()); // Works
System.out.println(i); // Works

print the same thing; in fact, the logic for the two is almost totally unrelated.

In summary, Java I/O is broken and, as a consequence, trygve I/O is broken. To do this right will take some thought.

@ciscoheat
Copy link
Contributor Author

Ok thanks, keeping this open then.

@jcoplien
Copy link
Owner

jcoplien commented Jan 7, 2016

There is a more general issue of promotion here. If String has a toInt method, should we automatically promote a String to an integer in a context where a String appears and an integer is expected? That is, is this an I/O issue or a broader generosity issue?

@jcoplien
Copy link
Owner

Is there any Java precedent for such behavior?

@ciscoheat
Copy link
Contributor Author

I haven't seen any previously, or when searching around now. It gets a bit more messy, since Java objects like StringBuffer uses toString to return the buffer as a String, which kind of conflicts with the idea of a user/programmer-defined textual representation of an object.

@ciscoheat
Copy link
Contributor Author

Closing this as well, no problem for me as it is right now.

@jcoplien
Copy link
Owner

jcoplien commented Mar 7, 2016

Thanks again!

Den 07/03/2016 kl. 02.40 skrev Andreas notifications@github.com:

Closed #21 #21.


Reply to this email directly or view it on GitHub #21 (comment).

@jcoplien
Copy link
Owner

jcoplien commented Mar 8, 2016

I think I will solve this in 1.6.7. I sent a mail to Andreas with the proposed solution. If he likes it, we'll close this.

@jcoplien jcoplien reopened this Mar 8, 2016
@jcoplien
Copy link
Owner

jcoplien commented Mar 8, 2016

This is another one of those that maybe should have been left open.

I just hacked PrintStream.format() into trygve yesterday and have greatly (!) refined it today. Where things now stand is that you can declare a toString() operation on your object:

class Person {
public Person(String name) {
assert(
name.length() > 0,
"Existence comes with a nameth upon thy should'rs"
);

    name_ = name.clone;
    gifts_ = new List<String>();
}

public String name() const { return name_ }
public List<String> gifts() const { return gifts_ }

public String toString() {
   return "(" + name() + ", " + "(name))"
}

private String name_;
private List<String> gifts_;

}

and then do something like this:

System.out.format("%s%n", new Person("Celeste”))

I was pretty amazed — I put together a kit of pieces of code I had used to implement compareTo, and a few other things, and it worked first time.

It was inspired by something I read in the Java documentation as I was going over it to make sure I had all the format directives covered. I found (https://docs.oracle.com/javase/7/docs/api/java/util/Formatter.html):

's', 'S' general If the argument arg is null, then the result is "null". If arg implements Formattable https://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html, then arg.formatTo https://docs.oracle.com/javase/7/docs/api/java/util/Formattable.html#formatTo(java.util.Formatter,%20int,%20int,%20int) is invoked. Otherwise, the result is obtained by invoking arg.toString().

Does this address your desire?

Den 07/03/2016 kl. 09.28 skrev James O Coplien cope@gertrudandcope.com:

Thanks again!

Den 07/03/2016 kl. 02.40 skrev Andreas <notifications@github.com mailto:notifications@github.com>:

Closed #21 #21.


Reply to this email directly or view it on GitHub #21 (comment).

jcoplien added a commit that referenced this issue Mar 8, 2016
… "[trygve] Automatically call toString if it exists? (#21)"

A lot of integrity stuff put into the formatting code, including a much
broader coverage of formatting types, invalid format exception
handling, and a facility to invoke a user-supplied toString operation,
if supplied. for the %s format.

All tests pass and FindBugs is clean.
@ciscoheat
Copy link
Contributor Author

It's very nice, though I usually prefer to use concatenation instead of having to remember format strings. It's so rare that I actually use the real formatting stuff.

System.out.println(person + "is " + age + " years old");

// Compared to
System.out.format("%s is %i years old\n", person, age);

...where I just forgot that %i should be %d. :)

Some mini-templating in strings makes it even simpler, for example as Haxe does it, when using single-quote strings:

trace('$person is $age years old');

So I'm not sure that my desire to make a simpler string output is addressed...! But again, it's not something that stops me at all.

@runefs
Copy link
Collaborator

runefs commented Mar 8, 2016

I use formatting quite a lot. The upside is that you can almost read the entire string. I find it unfortunate that curly brace languages has a "how" more than a "what" approach as haze and ruby has. I think that approach would fit better with the readability concerns of DCI/trygve

Mvh
Rune

Den 8. mar. 2016 kl. 16.16 skrev Andreas notifications@github.com:

It's very nice, though I usually prefer to use concatenation instead of having to remember format strings. It's so rare that I actually use the real formatting stuff.

System.out.println(person + "is " + age + " years old");

// Compared to
System.out.format("%s is %i years old\n", person, age);
...where I just forgot that %i should be %d. :)

Some mini-templating in strings makes it even simpler, for example as Haxe does it, when using single-quote strings:

trace('$person is $age years old');
So I'm not sure that my desire to make a simpler string output is addressed...! But again, it's not something that stops me at all.


Reply to this email directly or view it on GitHub.

@jcoplien
Copy link
Owner

jcoplien commented Mar 8, 2016

I think I’m going to leave it as it is as I think everyone is equally unhappy :-) And I want to get back to focusing on the DCI stuff.

Den 08/03/2016 kl. 16.52 skrev Rune Funch Søltoft notifications@github.com:

I use formatting quite a lot. The upside is that you can almost read the entire string. I find it unfortunate that curly brace languages has a "how" more than a "what" approach as haze and ruby has. I think that approach would fit better with the readability concerns of DCI/trygve

Mvh
Rune

Den 8. mar. 2016 kl. 16.16 skrev Andreas notifications@github.com:

It's very nice, though I usually prefer to use concatenation instead of having to remember format strings. It's so rare that I actually use the real formatting stuff.

System.out.println(person + "is " + age + " years old");

// Compared to
System.out.format("%s is %i years old\n", person, age);
...where I just forgot that %i should be %d. :)

Some mini-templating in strings makes it even simpler, for example as Haxe does it, when using single-quote strings:

trace('$person is $age years old');
So I'm not sure that my desire to make a simpler string output is addressed...! But again, it's not something that stops me at all.


Reply to this email directly or view it on GitHub.


Reply to this email directly or view it on GitHub #21 (comment).

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