rfc:println

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
rfc:println [2021/03/13 18:46] – created tandrerfc:println [2021/03/15 13:26] (current) tandre
Line 3: Line 3:
   * Date: 2021-03-13   * Date: 2021-03-13
   * Author: Tyson Andre   * Author: Tyson Andre
-  * Status: Draft+  * Status: Withdrawn
   * First Published at: http://wiki.php.net/rfc/println   * First Published at: http://wiki.php.net/rfc/println
 +  * Implementation: https://github.com/php/php-src/pull/6639
  
 ===== Introduction ===== ===== Introduction =====
 Printing a string followed by a newline to stdout is a commonly performed operation in many applications. Many programming languages provide a helper function to do this specifically, for readability and convenience. The choice of end of line may differ, but many recent programming languages will unconditionally use the unix newline, to avoid unexpected differences in behavior between platforms. Printing a string followed by a newline to stdout is a commonly performed operation in many applications. Many programming languages provide a helper function to do this specifically, for readability and convenience. The choice of end of line may differ, but many recent programming languages will unconditionally use the unix newline, to avoid unexpected differences in behavior between platforms.
  
-- Java has ''System.out.println('hello world')'' +  - Java has ''System.out.println('hello world')'' 
-- Python ''print('hello world')'' prints a newline by default, and a named argument can override that. +  - Python ''print('hello world')'' prints a newline by default, and a named argument can override that. 
-- C has ''puts("hello world")'' +  - C has ''puts("hello world")'' 
-- Golang has ''fmt.Println("hello world")'' +  - Golang has ''fmt.Println("hello world")'' 
-- Rust has ''println!("hello world")'' +  - Rust has ''println!("hello world")'' 
-- And so on.+  - And so on.
  
 However, PHP currently does not yet have a standalone helper method to do this. However, PHP currently does not yet have a standalone helper method to do this.
Line 23: Line 24:
 The behavior is equivalent to the following polyfill but expected to be more efficient due to avoiding concatenation. The behavior is equivalent to the following polyfill but expected to be more efficient due to avoiding concatenation.
  
-Similarly to https://www.php.net/manual/en/function.printf.php#refsect1-function.printf-returnvalues - this returns the number of bytes that were **successfully** output to stdout to be consistent with ''printf''. In the typical case where there was no output error, this returns ''strlen($data) + 1''. (E.g. printf and println may fail if php's standard output was redirected to a file on a disk that filled up)+Similarly to https://www.php.net/manual/en/function.printf.php#refsect1-function.printf-returnvalues - this returns the number of bytes that were **successfully** output to stdout (to be consistent with ''printf''). In the typical case where there was no output error, this returns ''strlen($data) + 1''. (E.g. printf and println may fail if php's standard output was redirected to a file on a disk that filled up)
  
  
Line 98: Line 99:
 ''println(1);'' or ''println(true)'' would have the argument coerced to a string when ''strict_types'' is disabled (the default), but would be a thrown ''Error'' with ''strict_types=1'' (like ''printf'' would for the format string). ''println(1);'' or ''println(true)'' would have the argument coerced to a string when ''strict_types'' is disabled (the default), but would be a thrown ''Error'' with ''strict_types=1'' (like ''printf'' would for the format string).
  
-  * Depending on the application, this may be useful as a runtime assertion or in making it clear to the reader that the argument is expected to be a string.+Depending on the application, this may be useful as a runtime assertion or in making it clear to the reader that the argument is expected to be a string
 + 
 +''<nowiki>println((string) $value);</nowiki>'' should be used when ''strict_types=1'' but you are uncertain of the type.
  
-''println((string)$value);'' should be used when ''strict_types=1'' but you are uncertain of the type. 
 (or other alternatives such as ''echo $arg, "\n"'', ''echo "$arg\n";'', or ''printf("%s\n", $arg)'' (or other alternatives such as ''echo $arg, "\n"'', ''echo "$arg\n";'', or ''printf("%s\n", $arg)''
  
Line 110: Line 112:
  
 ===== Unaffected PHP Functionality ===== ===== Unaffected PHP Functionality =====
-Other printing functions or statements are unaffected. ''println'' is NOT a keyword (e.g. functions named println can continue to be declared outside of the global namespace).+Other printing functions or statements are unaffected.
  
-===== Future Scope ===== +''println'' is deliberately NOT a keyword (e.g. functions named println can continue to be declared outside of the global namespace). 
-This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC.+ 
 +===== Discussion ===== 
 + 
 +==== This could go in a Composer/PECL package instead ==== 
 + 
 +https://externals.io/message/104545#104548 
 + 
 +<blockquote> 
 +<code php> 
 +<?php 
 + 
 +function println(string $x): void { 
 +    echo $x, PHP_EOL; 
 +
 +</code> 
 + 
 +I hereby grant a public domain license to the above code and wish you 
 +godspeed bundling it into a composer package to be enjoyed by users of 
 +every active version of PHP. 
 + 
 +-Sara 
 +</blockquote> 
 + 
 +In practice, I haven't seen many widely used composer packages that contain a small number of functions - PHP tends to be a batteries included language. 
 +Additionally, this increases startup times in situations where opcache and/or opcache preloading isn't feasible to set up (especially due to the lack of function autoloading). 
 + 
 +A new contributor to a project might not even be aware the helper method is available in a dependency, or of the choice of newline used in a helper method. 
 + 
 +If multiple composer packages were published and declared println (in the global namespace) with different behaviors, that would lead to confusion and bugs, which could be avoided by declaring println in PHP itself. 
 + 
 +==== This may not be commonly used for HTML ==== 
 + 
 +https://externals.io/message/104545#104560 
 + 
 +<blockquote> 
 +> 3. Add a new method, perhaps "echoln", "println", "say" or similar, that outputs a newline by default 
 + 
 +Of the suggestions put forward, this is the only one I can see having 
 +any chance of succeeding. 
 + 
 +However, I think the big reason this doesn't already exist is one that'
 +been touched on by other responses: PHP started as, and is still 
 +primarily regarded as, a language for building websites. In that 
 +context, newline characters are generally considered "insignificant 
 +whitespace"; the closest equivalent would be appending '<br>' or '<br />' (depending on the dialect of HTML in use), but you're as likely to 
 +want "<p>$foo</p>", or "<li>$foo</li>", etc - and that's before we get 
 +into the tricky topic of escaping. 
 + 
 +Even in CLI scripts, as soon as you're building anything intended for 
 +reuse, you're likely to write a function like log_string() which adds 
 +information like timestamp, category, severity. The use cases for a new 
 +function / keyword may therefore be rather limited. 
 + 
 +Regards, 
 + 
 +-- 
 +Rowan Collins 
 +[IMSoP] 
 +</blockquote> 
 + 
 +Some CLI scripts would use a specialized helper, but not all of them, and a helper may be used in some places but not others. Some CLI scripts are distributed without any external dependencies and the addition of ''println'' would simplify them and make them easier to read. 
 + 
 +Even when used as a web server, PHP would also serve resources with non-HTML content types such as ''Content-Type: text/plain'' (e.g. health checks). 
 +Within HTML, there are elements such as ''<pre>'', ''<textarea>'', ''<script>'', etc. where newlines are needed and used instead of ''<br>'' 
 + 
 +==== Choice of println for the name ==== 
 + 
 +Naming was discussed in a different user's proposal to add a "puts" function that was never brought to a vote. https://github.com/php/php-src/pull/3918#issuecomment-502241701 
 + 
 +<blockquote> 
 +nikic commented on 14 Jun 2019 
 + 
 +> Inspiration from Rust: https://doc.rust-lang.org/std/macro.println.html 
 + 
 +Speaking of ... I think it would make a lot more sense to call this function println rather than puts. The fact that puts() is like print but with a newline will not be obvious to anyone without a C background. (Or even to someone with a C background for that matter, I haven't ever used this function and wouldn't know that it adds a newline.) 
 +</blockquote> 
 + 
 +As stated in that comment, new languages such as golang/rust (and older languages like java(different semantics)) have gone with ''println'' instead. 
 +Additionally, the fact that ''puts'' would append newlines and ''fputs'' [[https://www.php.net/fputs|does not]] (exactly the same as it does in C) is something that I'd expect to be a source of confusion if the name ''puts'' was used. 
 + 
 +(e.g. changing ''puts("test")'' to ''fputs(STDERR, "test")'' would unexpectedly not print a terminating newline to STDERR (''fputs'' is an alias of ''fwrite'')) 
 + 
 +==== Choice of Unix newline(\n) ==== 
 + 
 +Some programming languages such as Java use a platform-specific or configurable newline https://docs.oracle.com/javase/6/docs/api/java/io/PrintStream.html#println%28%29 
 +Others, such as rust and golang, always use a unix newline. 
 + 
 +There have been some comments in favor of Unix newlines, and other comments in favor of PHP_EOL or configurable settings - e.g. https://externals.io/message/104545 
 + 
 +My reasons for unconditionally choosing the Unix newline are documented in the section [[#the_unix_newline_is_always_used|The Unix Newline is always used]]. 
 + 
 +==== Should this be a language construct instead ==== 
 + 
 + 
 +https://github.com/php/php-src/pull/3918#issuecomment-502012735 
 + 
 +<blockquote> 
 +Should't this be a language construct instead of a function, so it can be used without parenthesis just like echo or print? 
 + 
 +It would feel a little weird being able to do: 
 + 
 +<code php> 
 +echo 'hello world'; 
 +print 'hello world'; 
 +</code> 
 +... but not: 
 + 
 +<code php> 
 +puts 'hello world'; 
 +</code> 
 +</blockquote> 
 + 
 +Adding this as a language construct (i.e. new statement type) is something I'd expect to be contentious, and this is deliberately NOT done. Adding a new keyword would 
 + 
 +  - Cause a larger BC break. 
 +  - Increase the complexity of the language specification and make the language a bit harder to learn; I'd prefer simplicity by using an ordinary global function in this case. 
 +  - Be impossible to polyfill (when brackets weren't added) for older php versions. 
 + 
 +==== PHP already has a lot of ways to print a string ==== 
 + 
 +https://externals.io/message/113504#113530 
 + 
 +<blockquote> 
 +This isn't solving any problem that anyone is actually having. 
 +Yes, that includes you. You're not having this problem because it doesn'
 +exist. 
 + 
 +We already have twice as many ways to output a string as any language needs 
 +and you want to add another because you'd rather type "LN" than "\N"
 +Hard, negative ten thousand no on this. 
 +This is genuinely absurd. 
 +</blockquote>
  
 ===== Proposed Voting Choices ===== ===== Proposed Voting Choices =====
-Yes/No, requiring 2/3 majority.+Yes/No, requiring 2/3 majority.
  
 ===== References ===== ===== References =====
 https://externals.io/message/104545 "print with newline" https://externals.io/message/104545 "print with newline"
  
-===== Rejected Features ===== +https://github.com/php/php-src/pull/3918 "ext/standard/basic_functions.c: add puts function" has discussion on a similar proposal by a different author. My RFC uses ''\n'', while the other author's RFC proposed ''PHP_EOL''.
- +
-==== Alternate names ==== +
rfc/println.1615661176.txt.gz · Last modified: 2021/03/13 18:46 by tandre