jcoplien / trygve

The trygve language project - Building a DCI-centric language from the ground up
GNU General Public License v2.0
104 stars 15 forks source link

Automatically call toString if it exists? #21

Open ciscoheat opened 8 years ago

ciscoheat commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 https://github.com/jcoplien/trygve/issues/21#issuecomment-168169803.

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 commented 8 years ago

Ok thanks, keeping this open then.

jcoplien commented 8 years ago

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 commented 8 years ago

Is there any Java precedent for such behavior?

ciscoheat commented 8 years ago

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 commented 8 years ago

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

jcoplien commented 8 years ago

Thanks again!

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

Closed #21 https://github.com/jcoplien/trygve/issues/21.

— Reply to this email directly or view it on GitHub https://github.com/jcoplien/trygve/issues/21#event-579532001.

jcoplien commented 8 years ago

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 commented 8 years ago

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 https://github.com/jcoplien/trygve/issues/21.

— Reply to this email directly or view it on GitHub https://github.com/jcoplien/trygve/issues/21#event-579532001.

ciscoheat commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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 https://github.com/jcoplien/trygve/issues/21#issuecomment-193834047.