fmtlib / fmt

A modern formatting library
https://fmt.dev
Other
20.9k stars 2.52k forks source link

Why is `println` missing? #428

Closed jiri closed 8 years ago

jiri commented 8 years ago

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

foonathan commented 8 years ago

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

vitaut commented 8 years ago

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);
}
jiri commented 8 years ago

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

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

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

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

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

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

foonathan commented 6 years ago

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

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


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

slonm commented 5 years ago

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

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

eliaskosunen commented 5 years ago

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

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

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

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

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

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')
narodnik commented 5 years ago

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

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

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

jiri commented 4 years ago

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

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

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

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

hellow554 commented 3 years ago

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

Vox-Ben commented 2 years ago

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

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

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

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

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

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

technic commented 2 years ago

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

Would it be reconsidered if implementers add println with P2093?

vitaut commented 2 years ago

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

emailstorbala commented 8 months ago

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

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

hellow554 commented 8 months ago

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

emailstorbala commented 8 months ago

@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 commented 8 months ago

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.