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

Why is println missing? #428

Closed
jiri opened this issue Nov 23, 2016 · 39 comments · Fixed by #3267
Closed

Why is println missing? #428

jiri opened this issue Nov 23, 2016 · 39 comments · Fixed by #3267

Comments

@jiri
Copy link

jiri commented Nov 23, 2016

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

@foonathan
Copy link
Contributor

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

@vitaut
Copy link
Contributor

vitaut commented Nov 24, 2016

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);
}

@vitaut vitaut closed this as completed Nov 24, 2016
@jiri
Copy link
Author

jiri commented Nov 24, 2016

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.

@vitaut
Copy link
Contributor

vitaut commented Nov 24, 2016

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.

@jiri
Copy link
Author

jiri commented Nov 24, 2016

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").

@vitaut
Copy link
Contributor

vitaut commented Nov 24, 2016

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.

@slonm
Copy link

slonm commented Jun 7, 2018

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

@vitaut
Copy link
Contributor

vitaut commented Jun 7, 2018

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

@foonathan
Copy link
Contributor

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.

@micfan
Copy link

micfan commented Mar 28, 2019

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


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

@slonm
Copy link

slonm commented Mar 28, 2019

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

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

@eliaskosunen
Copy link
Contributor

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.

@slonm
Copy link

slonm commented Mar 28, 2019

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

@vitaut
Copy link
Contributor

vitaut commented Mar 28, 2019

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.

@egor10257
Copy link

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).

@slonm
Copy link

slonm commented Mar 29, 2019

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.

@ghost
Copy link

ghost commented May 28, 2019

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

#include <stdio.h>
int main() {
   puts("abcde");
}

C#:

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

Go:

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

Rust:

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

Nim:

echo "abcde"

Python:

print('abcde')

@ghost ghost mentioned this issue May 28, 2019
@narodnik
Copy link

narodnik commented Aug 4, 2019

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.

@theIDinside
Copy link

theIDinside commented Feb 12, 2020

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.

@elvisdukaj
Copy link

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

@jiri
Copy link
Author

jiri commented Apr 14, 2020

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 😄

@yesudeep
Copy link

yesudeep commented Aug 2, 2020

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

@hellow554
Copy link

I would speak against an implicit newline within print, because that's disturbing. But an extra println function wouldn't hurt. As you said, that can be easily done, so what's the reason not to do it?
After all, it's all about ergonomics in a library @vitaut .

@jm4R
Copy link

jm4R commented Dec 16, 2020

What's the proper way to flush the buffer in current {fmt}? std::fflush from cstdio?

@hellow554
Copy link

@jm4R why do you hijack this thread instead of opening a new issue/question?

@Vox-Ben
Copy link

Vox-Ben commented Jan 6, 2022

I've just been banging my head off this, I have a legacy logging system that I'm converting to use fmt, and I can't find any way to insert a newline at the end of log statements automatically. The problem is that @vitaut 's five-line println above (which is what I'd tried before finding this) doesn't work where it's being compiled into a library for use by other code. The compiler creates all the function signatures used by my logging code itself, and then as soon as some other piece of code imports the library and tries to pass something to the logger with a combination of types it didn't see during compilation of the logging library, the linker barfs saying it's got an undefined symbol.

So yeah. Absent a println it seems I have a choice between requiring all users of the library to start putting their newlines in themselves, or not porting it to fmt.

@realnc
Copy link

realnc commented Apr 19, 2022

I have a legacy logging system that I'm converting to use fmt, and I can't find any way to insert a newline at the end of log statements automatically.

Just write your logging functions using perfect forwarding like this:

template <typename... Args>
void logWarn(fmt::format_string<Args...>&& fmt_str, Args&&... args)
{
    fmt::print(stderr, "warning: {}\n", fmt::format(
        std::forward<fmt::format_string<Args...>>(fmt_str), std::forward<Args>(args)...));
}

template <typename... Args>
void logInfo(fmt::format_string<Args...>&& fmt_str, Args&&... args)
{
    fmt::print("info: {}\n", fmt::format(
        std::forward<fmt::format_string<Args...>>(fmt_str), std::forward<Args>(args)...));
}

C++20 automatic compile-time argument checking still works fine with these, and so does manual compile-time checking with FMT_STRING.

@technic
Copy link

technic commented May 6, 2022

I think println should be added. In any case many code-bases using this fmt library would write their own println one-liner. So why not to add it here? I've read this thread and didn't find any reasonable argument against it.

@jiri
Copy link
Author

jiri commented May 8, 2022

Given that this discussion has been ongoing for 6 years now and that the developers behind fmtlib have shown zero interest in listening, I'd suggest any future commenters to either use the provided workaround, or just move onto other libraries with more active development.

I suggest @vitaut locks this issue, as any attempt to further convince you on this issue just adds noise in the repository activity at this point.

@vitaut
Copy link
Contributor

vitaut commented May 8, 2022

I've read this thread and didn't find any reasonable argument against it.

To add a feature there should be strong arguments for it not against not adding it. And so far the arguments have been somewhat lacking and some even became invalid with compile-time checks.

@jiri, no plans to lock this issue but at least please stop adding noise yourself.

@jiri
Copy link
Author

jiri commented May 9, 2022

@vitaut Please refrain from mentioning me again, I don't wish to continue this discussion with you. Thank you!

@technic
Copy link

technic commented May 10, 2022

I've read this thread and didn't find any reasonable argument against it.

To add a feature there should be strong arguments for it not against not adding it. And so far the arguments have been somewhat lacking and some even became invalid with compile-time checks.

I completely disagree to this approach of feature management.

@tryfinally
Copy link

  1. its all about readability and explicit intention.
    println : I want to output sequence of chars ending with a new line,
  2. commonality and principle of least astonishment, especially for us polyglots. ( C# , Java. to name a few)

@OnurKader
Copy link

Would it be reconsidered if implementers add println with P2093?

@vitaut
Copy link
Contributor

vitaut commented May 24, 2022

Yeah, if P2093 gets adopted it would make sense to be consistent.

facebook-github-bot pushed a commit to facebook/hhvm that referenced this issue Nov 1, 2022
Summary:
I noticed that `watchman debug-status` seems to be missing from a lot of `watchman-diags` on macOS. turns out its missing from `watchmanctl rage` too.

I discovered that when stdout is piped watchman --pretty debug-status prints nothing. Some more digging and it looks like when stdout is a terminal, its line buffered. So every \n effectively flushes the output. But when stdout is piped or captured by a calling process, its "block buffered". So stdout needs to be manually flushed. I would have thought it would be flushed at the end of the process, but evidently not on macOS?

fmt also does not manually flush stdout when you use fmt::print. see: vgc/vgc#519 and fmtlib/fmt#428 (didn't know println was so controversial 😛).

We need to manually flush stdout for now to ensure that fmt::print works. Eventually, we can use fmt::flush (because vgc/vgc#519). but that does not seem available in the version of fmt we use today.

Reviewed By: genevievehelsel

Differential Revision: D40881110

fbshipit-source-id: d417b9c4f932ea08905fd125847c8dd30751eeec
facebook-github-bot pushed a commit to facebook/watchman that referenced this issue Nov 1, 2022
Summary:
I noticed that `watchman debug-status` seems to be missing from a lot of `watchman-diags` on macOS. turns out its missing from `watchmanctl rage` too.

I discovered that when stdout is piped watchman --pretty debug-status prints nothing. Some more digging and it looks like when stdout is a terminal, its line buffered. So every \n effectively flushes the output. But when stdout is piped or captured by a calling process, its "block buffered". So stdout needs to be manually flushed. I would have thought it would be flushed at the end of the process, but evidently not on macOS?

fmt also does not manually flush stdout when you use fmt::print. see: vgc/vgc#519 and fmtlib/fmt#428 (didn't know println was so controversial 😛).

We need to manually flush stdout for now to ensure that fmt::print works. Eventually, we can use fmt::flush (because vgc/vgc#519). but that does not seem available in the version of fmt we use today.

Reviewed By: genevievehelsel

Differential Revision: D40881110

fbshipit-source-id: d417b9c4f932ea08905fd125847c8dd30751eeec
ckerr added a commit to transmission/transmission that referenced this issue Feb 18, 2024
fmtlib/fmt#428 (comment)
> You can use fmt::print("...\n") on Windows as well.

Use this mechanism instead of tr_sys_file_write_line()
ckerr added a commit to transmission/transmission that referenced this issue Feb 25, 2024
fmtlib/fmt#428 (comment)
> You can use fmt::print("...\n") on Windows as well.

Use this mechanism instead of tr_sys_file_write_line()
ckerr added a commit to transmission/transmission that referenced this issue Feb 25, 2024
…6619)

* refactor: use fmt::print in log.cc

fmtlib/fmt#428 (comment)
> You can use fmt::print("...\n") on Windows as well.

Use this mechanism instead of tr_sys_file_write_line()

* refactor: use FILE* in daemon

* refactor: remove unused tr_sys_file_flush_possible()

* refactor: remove unused tr_sys_file_write_line()

* refactor: remove unused tr_sys_file_get_std()

* refactor: remove unused tr_std_sys_file_t
@emailstorbala
Copy link

Seems C++23 has included the println().

https://en.cppreference.com/w/cpp/io/println

@hellow554
Copy link

@emailstorbala fmt also now has println
This issue is finally implemented

@emailstorbala
Copy link

@emailstorbala fmt also now has println This issue is finally implemented

oh thank you @hellow554 ! I am using Debian/trixie with libfmt9 (9.1.0+ds1-2). Is this available in this version? Can you kindly point me to its documentation as I am unable to find it.

@tupaschoal
Copy link
Contributor

oh thank you @hellow554 ! I am using Debian/trixie with libfmt9 (9.1.0+ds1-2). Is this available in this version? Can you kindly point me to its documentation as I am unable to find it.

As far as I can see on git blame, it was implemented for fmt 10.0.0, but not documented.

Schlossgeist pushed a commit to Schlossgeist/transmission that referenced this issue Mar 23, 2024
…ransmission#6619)

* refactor: use fmt::print in log.cc

fmtlib/fmt#428 (comment)
> You can use fmt::print("...\n") on Windows as well.

Use this mechanism instead of tr_sys_file_write_line()

* refactor: use FILE* in daemon

* refactor: remove unused tr_sys_file_flush_possible()

* refactor: remove unused tr_sys_file_write_line()

* refactor: remove unused tr_sys_file_get_std()

* refactor: remove unused tr_std_sys_file_t
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

Successfully merging a pull request may close this issue.