Fmt: Why is `println` missing?

Created on 23 Nov 2016  路  22Comments  路  Source: fmtlib/fmt

fmt::println seems like a natural addition to the API. Is there a reason why it's missing?

Most helpful comment

I agree that println should be implemented as well. Many other programming
languages offer such a method. For example C:

~~~c

include

int main() {
puts("abcde");
}
~~~

C#:

~c
using System;
class Program {
static void Main() {
Console.WriteLine("abcde");
}
}
~

Go:

~go
package main
import "fmt"
func main() {
fmt.Println("abcde")
}
~

Rust:

~rust
fn main() {
println!("abcde");
}
~

Nim:

~nim
echo "abcde"
~

Python:

~py
print('abcde')
~

All 22 comments

What's wrong with fmt::print("...\n")?

I think that println is of limited use because you can always specify the newline explicitly as @foonathan showed. But fmt provides sufficient infrastructure to easily and efficiently build this and similar methods without making them the part of the core library. In particular println can be written in five lines of code:

template <typename... Args>
void println(fmt::CStringRef format, const Args&... args) {
  fmt::print(format, args...);
  std::putc('\n', stdout);
}

Sure, and you could always use stdout explicitly, but it's the default file for convenience. One could as well argue "What's wrong with fmt::print(stdout, "...\n").

Having to include an explicit newline everywhere is noisy and prone to forgetting them. There's a reason why many languages include println in their core libraries ;) Moreover, I thought that the point of a formatting library is eliminating the reason for all those non-newline terminated prints, since I could just format them into the strings, but nevertheless, you seem to be pretty set on not including it, so feel free to keep this closed.

Cheers.

The difference from fmt::print overload taking stdout is that the latter saves a bit of typing

fmt::print("foo");
fmt::print(stdout, "foo");

and directly corresponds to std::printf. But you are right, it's somewhat redundant too.

It's true that println would save exactly zero characters. What's the approach to printing a foreign string? E.g., is something like

void foo(std::string s) {
    fmt::print(s);
}

considered bad form or bad api usage? println(s) can make the intention clearer than print("{}\n", s) or god forbid print(s + "\n").

is something like ... considered bad form or bad api usage?

Yes. As with printf, it's better to write

void foo(std::string s) {
    fmt::print("{}", s);
}

Otherwise s will be parsed as a format string and will need to be escaped.

What's wrong with fmt::print("...\n")?

For Windows it's: fmt::print("...\r\n")
Howto to hide this difference?
I'm vote for API extension

You can use fmt::print("...\n") on Windows as well.

The underlying streams will translate newlines, as long as they are not binary streams. stdout by default is not, so it will properly translate newlines.

Ummmm... I like fmt::println()


UPDATE:
maybe some day it will become std::println()

What's wrong with fmt::print("...\n")?

It does not flush stream like it do std::endl

Although not mandated by the C standard, stdout is line-buffered by default on many implementations. This means, that a call to fflush is not necessary after printf("...\n") or puts("..."), and thus, fmt::print("...\n") would indeed flush the stream.

The same applies for std::cout, which _is_ mandated to be line-buffered, so writing a '\n' would flush the stream no matter what.

stdout is line buffered only if a stream refers to a terminal. As soon as you redirect it to a pipe or to a file, it will be block buffered.
Verified on Windows

It does not flush stream like it do std::endl

That's a feature. Even with hypothetical println you wouldn't want to always flush.

Still why don't have flushing println()?
It doesn't break anything, and if it is really unneeded nobody will use it (and vise versa).

That's a feature. Even with hypothetical println you wouldn't want to always flush.

fmt::print("...\n") could be used if flush is not need.

I agree that println should be implemented as well. Many other programming
languages offer such a method. For example C:

~~~c

include

int main() {
puts("abcde");
}
~~~

C#:

~c
using System;
class Program {
static void Main() {
Console.WriteLine("abcde");
}
}
~

Go:

~go
package main
import "fmt"
func main() {
fmt.Println("abcde")
}
~

Rust:

~rust
fn main() {
println!("abcde");
}
~

Nim:

~nim
echo "abcde"
~

Python:

~py
print('abcde')
~

I honestly was shocked this isn't the default behaviour of fmt::print()

Usually if you don't want a newline, you can be explicit about this.

stdout is line buffered only if a stream refers to a terminal. As soon as you redirect it to a pipe or to a file, it will be block buffered.
Verified on Windows

Also verified on Linux Mint. When I do this for example in a Qt application using iostream, i have to put std::endl to be sure that it outputs immediately, otherwise it will arbitrarily show up.

Yeah it's annoying to explicitly flush the buffer...

I'd also like to point out that absence of such a basic ergonomic feature in the presence of features like the literal based API is kinda funny 馃槃

The more common use case is println and it is so trivial it should be baked in. typing \n everywhere adds too much noise.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AlbertoEAF picture AlbertoEAF  路  3Comments

hbsnmyj picture hbsnmyj  路  6Comments

gnzlbg picture gnzlbg  路  3Comments

stryku picture stryku  路  4Comments

ugenehan picture ugenehan  路  3Comments