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

RFC: Add println(string $data = ''): int #6639

Closed
wants to merge 1 commit into from

Conversation

TysonAndre
Copy link
Contributor

@TysonAndre TysonAndre commented Jan 26, 2021

What this does

This function behaves similarly to this userland code

function println(string $data = ''): int {
    return printf("%s\n", $data);
}
println("test");
println();  // moderately useful to not switch to echo or pass the empty string to print a blank line
println("third line");
/*
test

third line
*/

Similarly to printf("%s\n", $data);. in this proposal,

  • println is NOT a keyword. (e.g. functions named println can continue to be
    declared outside of the global namespace)

  • It returns the number of bytes that were successfully written to standard
    output. In the unlikely event that there was an error writing,
    this and printf return a smaller number.

  • This deliberately always prints the unix newline (\n)
    instead of PHP_EOL.

    I would find it very unexpected if println were to behave
    differently based on the web server was running it,
    e.g. if you moved a website's backend from/to a linux server
    to/from a windows server, responses generated by println would
    suddenly be different. (Content-Length, hashes(e.g. sha256sum) of output, etc.)

    Additionally, https://www.php-fig.org/psr/psr-2/ recommends that all php
    source files contain unix line endings.
    If those files contain inline html/text snippets mixed with php+println(),
    or if they contain strings using <<<EOT heredoc,
    it would be inconsistent to have \r\n in the lines printed by
    println() and \n anywhere else.

    This is same choice of line ending as var_dump, debug_zval_dump,
    and var_export use for dumping output.
    Otherwise, println("myArray=" . var_export($myArray, true));
    would be a mix of multiple line ending choices.

    PHP's interactive shell (php -a) prints a single newline character if the output does not end in a newline.

      	if (!pager_pipe && php_last_char != '\0' && php_last_char != '\n') { // ext/readline/readline_cli.c
      		php_write("\n", 1);
      	}

    Many new languages have elected to always use only the unix newlines,
    e.g. https://golang.org/pkg/fmt/#Println and
    https://doc.rust-lang.org/std/macro.println.html

    Overall, editors do a much better job of detecting newline choices and
    displaying different newline choices than they did decades ago.

    My opinion is that this anything generating files targeting a specific OS's
    line endings should continue to use PHP_EOL or continue to base
    the newline choice on the OS of the user requesting the output.

    This newline choice differs from the implementation PR for a similar proposal
    made 2 years ago https://externals.io/message/104545 ,
    for which an RFC was never written.

Differently from printf's argument list, echo, and print,
the argument $data is type checked based on the file's strict_types setting.
This is consistent with handling of $data in
fwrite($stream, string $data): int or the way format strings($format)
of printf are checked.

println((string)$value) should be used when strict_types=1 but you are uncertain
of the type.

Reasons to add this

  1. This is useful for self-contained scripts and a useful helper function to
    have overall. E.g. phpt tests of php itself print multiple lines for the
    --EXPECT-- section, and var_dump can be overused even for known strings known not to have special characters or spaces
    because var_dump(some_function())
    is a bit simpler to write than echo some_function() . "\n";, but not as simple as println(some_function())

  2. Even if codebases add userland helper equivalents that do exactly this,
    If you are new to a codebase, or contribute to multiple
    codebases, it is inconvenient to use xyz_println,
    ABCUtils::println(), echo X, "\n", etc., and remember if those different
    functions actually use the line endings you think they do.

    Additionally, the prefixing is much more verbose.

  3. In tutorials or language references that teach a developer
    how to use php functionality, it is often preferable to use
    functions that append a newline when multiple snippets would be evaluated
    together to keep examples simple.

    println("Hello $name"); would be useful to have for introducing PHP
    to a new developer before echo "Hello $name\n";
    (requires explaining escaping first)
    or var_dump("Hello $name"); (that debug representation is rarely useful
    for string(11) "Hello world")

    E.g. var_dump is frequently used instead of
    var_export, echo, or print in the manual even for printing strings
    with no control characters such as
    https://www.php.net/manual/en/function.json-encode.php#example-3972

TODO: Write an rfc document, gather existing counterarguments for/against
naming choices and newline choices, gather examples of other languages that put
a println equivalent in the standard library and their choices.
See https://externals.io/message/104545#104548 and prior PRs

println was deliberately chosen over puts - the name puts could be argued to be unfamiliar to
anyone without a C background and some 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 does not (exactly the same as it does in C) may be a cause of confusion if that name were to be chosen.
(e.g. changing puts("test") to fputs(STDERR, "test") would not print a terminating newline to STDERR (fputs is an alias of fwrite))

RFC(withdrawn): https://wiki.php.net/rfc/println

@dwgebler
Copy link
Contributor

dwgebler commented Feb 2, 2021

FWIW, I'm not sure I like this or see the value in adding it.

This deliberately always prints the unix newline (\n) instead of PHP_EOL.
I would find it very unexpected if println were to behave differently based on the web server was running it,
e.g. if you moved a website's backend from/to a linux server to/from a windows server, responses generated by println would
suddenly be different.

Newlines are meaningless in a browser context, though. Some might say it would be surprising if running a console or writing logs on Windows and println didn't print a Windows EOL.

Additionally, https://www.php-fig.org/psr/psr-2/ recommends that all php source files contain unix line endings.

This is not really relevant; the PSR standard refers to PHP source files, not what is output by a script.

@TysonAndre TysonAndre changed the title Proposal: Add println(string $data = ''): int RFC: Add println(string $data = ''): int Mar 13, 2021
What this does
--------------

This function behaves similarly to this userland code

```
function println(string $data = ''): int {
    return printf("%s\n", $data);
}
```

Similarly to `printf("%s\n", $data);`.

- `println` is NOT a keyword. (e.g. functions named println can continue to be
  declared outside of the global namespace)
- It returns the number of bytes that were successfully written to standard
  output. In the unlikely event that there was an error writing,
  this and printf return a smaller number.
- This deliberately always prints the unix newline (`\n`)
  **instead of PHP_EOL**.

  I would find it very unexpected if println were to behave
  differently based on the web server was running it,
  e.g. if you moved a website's backend from/to a linux server
  to/from a windows server, responses generated by `println` would
  suddenly be different.

  Additionally, https://www.php-fig.org/psr/psr-2/ recommends that all php
  source files contain unix line endings.
  If those files contain inline html/text snippets mixed with php+println(),
  it would be inconsistent to have `\r\n` in the lines printed by
  println() and `\n` anywhere else.

  This is same choice of line ending as var_dump, debug_zval_dump,
  and var_export use for dumping output.
  Otherwise, `println("myArray=" . var_export($myArray, true));`
  would be a mix of multiple line ending choices.

  Many new languages have elected to always use only the unix newlines,
  e.g. https://golang.org/pkg/fmt/#Println and
  https://doc.rust-lang.org/std/macro.println.html

  Overall, editors do a much better job of detecting newline choices and
  displaying different newline choices than they did decades ago.

  My opinion is that this anything generating files targeting a specific OS's
  line endings should continue to use PHP_EOL or continue to base
  the newline choice on the OS of the user requesting the output.

  This newline choice differs from the implementation PR for a similar proposal
  made 2 years ago https://externals.io/message/104545 ,
  for which an RFC was never written.

Differently from printf's argument list, echo, and print,
the argument $data is type checked based on the file's `strict_types` setting.
This is consistent with handling of $data in
`fwrite($stream, string $data): int` or the way format strings($format)
of `printf` are checked.

`println((string)$value)` should be used when strict_types=1 but you are uncertain
of the type.

Reasons to add this
-------------------

1. This is useful for self-contained scripts and a useful helper function to
   have overall. E.g. phpt tests of php itself print multiple lines for the
   `--EXPECT--` section, and var_dump can be overused even for known strings
   because `var_dump(some_function())`
   is shorter than `echo some_function() . "\n";`

2. Even if codebases add userland helper equivalents that do exactly this,
   If you are new to a codebase, or contribute to multiple
   codebases, it is inconvenient to use `xyz_println`,
   `ABCUtils::println()`, `echo X, "\n"`, etc., and remember if those different
   functions actually use the line endings you think they do.

   Additionally, the prefixing is much more verbose.
3. In tutorials or language references that teach a developer
   how to use php functionality, it is often preferable to use
   functions that append a newline when multiple snippets would be evaluated
   together to keep examples simple.

   `println("Hello $name");` would be useful to have for introducing PHP
   to a new developer before `echo "Hello $name\n";`
   (requires explaining escaping first)
   or `var_dump("Hello $name");` (that debug representation is rarely useful
   for `string(11) "Hello world"`)

   E.g. `var_dump` is frequently used instead of
   `var_export`, `echo`, or `print` in the manual even for printing strings
   with no control characters such as
   https://www.php.net/manual/en/function.json-encode.php#example-3972

TODO: Write an rfc document, gather existing counterarguments for/against
naming choices and newline choices, gather examples of other languages that put
a println equivalent in the standard library and their choices.
@Ayesh
Copy link
Contributor

Ayesh commented Mar 14, 2021

Thank you for this. I think this will be a very handy addition.

On scan of ~350K repos, I came across ~30 positive hits for [\r\n]function println(, and 4 out of them that will hit a println re-declaration error. This being a notable one with 1.5K GitHub stars. I'd happily volunteer to send PRs to notable repos to minimize the obstruction. Packagist top 1000 downloaded packages are safe already.

@TysonAndre TysonAndre closed this Mar 15, 2021
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 this pull request may close these issues.

None yet

3 participants