3 ms·
Because print can fail. See the comments in the above code example.
by AndyKelley 8y ago
Because print can fail. See the comments in the above code example.
- lixtra 8y agoAnd warn cannot fail?
- AndyKelley 8y agoCorrect: pub fn warn(comptime fmt: []const u8, args: ...) void { const held = stderr_mutex.acquire(); defer held.release(); const stderr = getStderrStream() catch return; stderr.print(fmt, args) catch return; } The tradeoff, however, is that when the function returns, it is not guaranteed that the warning message made it successfully to stderr. This tradeoff is not appropriate for stdout. Also the decision to use the mutex is not appropriate for stdout. The application may be single-threaded, or have its own synchronization strategy that makes the mutex redundant. Zig is optimal.
- coder543 8y agoIf something bad happened, that seems much more important to ensure it printed than printing output saying that everything is working just fine. This trade-off is not self-evidently correct... it's easily boiled down to personal preference. Consistency would be nicer. Zig is not "optimal" just because someone says it.
- int_19h 8y agoThere's no way to ensure that it is printed, because the environment can prevent you from doing so - stdout/err can be a pipe and it can be closed, for example. So, suppose warn() fails. What can you do about it - try to print a warning that you can't print warnings?
- coder543 8y agoThat's kinda my point. If stdout or stderr fails, what are you going to do about it? The normally correct solution is to panic/terminate the program. Having a simple "print" function that does that is an obvious nicety. If you want something different, use a library or some other parts of the stdlib. Making that super common use case painful is not obviously a good decision.
- AndyKelley 8y agoIf stdout fails and your program's purpose is to print to stdout, for example, if you are `cat`, `less`, `diff`, `ps`, `ls`, etc... then you should print an error message to stderr and exit with an error code. The super common use case is std.debug.warn, not printing to stdout.
- int_19h 8y agoI think it might be helpful if the name of warn() did not imply that the message is actually a warning, i.e. that "something bad happened". There are many legitimate cases for printing purely informational messages to stderr - operation progress, that sort of thing. When someone sees a hello world app in Zig, and there's warn() in it, the first knee-jerk reaction is, "so what are we warning about?". I would actually even argue that the meaning of "print" as printing to stdout by default is an unfortunate historical artifact. For the kind of stuff print is usually used by most of the code, it really should go to stderr, and "print" kinda implies some kind of logging IMO. From that perspective, my suggestion would be to add a no-failure @import("std").debug.print that is an alias for warn. I don't think it's likely that breaking the established convention of print-defaults-to-stdout would cause issues in practice - in programs where this matter (like cat), the developer will quickly discover the issue the moment they try using it in a pipeline. And for programs where it doesn't, defaulting to stderr is actually the right thing. But if you'd rather not break the convention, how about adding debug.log that is an alias for debug.warn? Or debug.say, or something like it.
- v_lisivka 8y ago
- lixtra 8y agoThanks for taking the time to explain. Your argument is reasonable. The software I touch is allowed to crash if stdout fails. Maybe zig is indeed not for me.
- AndyKelley 8y agoor you could just make a helper function that ignores errors and call that. We're just arguing about defaults. Zig is of course a general purpose programming language and you can always build less precise tools on top of more precise tools.
- jbapple 8y agoWhat do you mean by "Zig is optimal"?
- dbaupp 8y agoWhy couldn't the print imported in the hypothetical short example above be made to fail? If all the stdout code is packaged into it, with the same try's, it seems like the code could at least be: pub fn main() !void { try print(...) }