Hi internals,
I've created a new RFC https://wiki.php.net/rfc/println
This proposes adding a global function to PHP to
print a string followed by a unix newline (\n
).
Printing a string followed by a newline to stdout is a commonly performed operation in many applications and programming languages.
Many programming languages provide a helper function to do this specifically, for readability and convenience.
The choice of end of line string may differ, but many recent programming languages will unconditionally use the unix newline,
to avoid unexpected differences in behavior between platforms.
I've looked over prior related discussions such as https://externals.io/message/104545,
and I've written down the reasons for my name choice and newline choice in the RFC.
Any other feedback or elaboration on discussions?
Thanks,
- Tyson
Hi Tyson,
I like this proposal, but why is the main argument optional? Wouldn't it
make sense to always require a string as an argument?
Regards,
Kamil
Hi Tyson,
I like this proposal, but why is the main argument optional? Wouldn't it
make sense to always require a string as an argument?Regards,
Kamil
I initially considered making it required, but then I felt like there wasn't a compelling reason to force end users
to write println('')
instead of println()
to print a single newline in code surrounded by other println statements.
Printing an empty blank line would be common enough in CLI output or plaintext HTTP responses for this proposal to make it easier to do.
- This differs from echo/print/printf statements, where not including an argument wouldn't make sense to support, because it would not output anything
- This proposed println behavior is similar to python, where
print()
with no arguments would print a single newline
https://wiki.php.net/rfc/println#proposal
println("test");
println(); // moderately useful to not switch to echo or pass the empty string to print a blank line
println("third line");
/*
Output:
test
third line
*/
Thanks,
- Tyson
I've created a new RFC https://wiki.php.net/rfc/println
This proposes adding a global function to PHP to
print a string followed by a unix newline (\n
).
Hi Tyson,
I'm on the fence on this one: I've certainly had occasions when it would
be useful, but mostly in quick prototypes and demo code, and just as
often in HTML context (where I'd want it to add '<br>') as plain text
context.
I am not keen, however, on the proposed implementation details, and
would prefer it to much more closely match either print or echo.
-
Until reading this RFC, I would not have guessed that
printf()
returned the number of bytes written; I guess it's useful in C, where
you're managing string buffers, but in PHP it feels very arbitrary. I
would also not particularly associate this new function withprintf()
so
my immediate guess would be the same return value as print (even though
that return value, int(1), is equally arbitrary). -
You explicitly state that this function would depend on strict_types
mode, but echo and print do not. I can't see any particular advantage to
doing so, and 'println((string)$foo)' would be longer than 'print
$foo,"\n"' rather defeating the purpose. -
Most importantly, I accept your points about a function being more
forward- and backward-compatible, but worry that not making it a keyword
will lead to further confusion about how parentheses interact with echo
and print. There is a common misconception that they have some kind of
"optional parentheses", because they are usually used with a single
expression, so wrapping it in parentheses usually doesn't change the
outcome; but this is not the case, and it does sometimes matter.
As currently proposed, I can see people getting nasty surprises from
these inconsistencies. For instance:
print (1+2)*3; // prints "9"
println (1+2)*3; // prints "3\n"; unless strict_types=1 is in effect, in
which case TypeError
print ($foo ?? 'Foo') . ($bar ?? 'Bar'); // prints "FooBar" if both vars
are null
println ($foo ?? 'Foo') . ($bar ?? 'Bar'); // never prints $bar or
"Bar", because they are not passed to println()
if ( something() && println($foo) && somethingElse() ) // does what it
looks like, if println is a normal function
if ( something() && print($foo) && somethingElse() ) // does not print
$foo, because the expression passed is actually ($foo)&&somethingElse()
Regards,
--
Rowan Tommins
[IMSoP]
Hi Rowan,
Hi Tyson,
I'm on the fence on this one: I've certainly had occasions when it would
be useful, but mostly in quick prototypes and demo code, and just as
often in HTML context (where I'd want it to add '<br>') as plain text
context.I am not keen, however, on the proposed implementation details, and
would prefer it to much more closely match either print or echo.
- Until reading this RFC, I would not have guessed that
printf()
returned the number of bytes written; I guess it's useful in C, where
you're managing string buffers, but in PHP it feels very arbitrary. I
would also not particularly associate this new function withprintf()
so
my immediate guess would be the same return value as print (even though
that return value, int(1), is equally arbitrary).
There's also the alias fputs of https://www.php.net/manual/en/function.fwrite.php
which also returns the byte count.
I'd considered just returning void, but then you'd have a mix of standard library
functions that did/didn't return void and users would need to remember which did what.
If someone actually had a need to use the result of println, it would likely be to count bytes,
rather than to get a hardcoded constant such as 1/null.
(or expression chaining, but println('Starting') or die(2); // somehow failed to output
also has a use case)
- You explicitly state that this function would depend on strict_types
mode, but echo and print do not. I can't see any particular advantage to
doing so, and 'println((string)$foo)' would be longer than 'print
$foo,"\n"' rather defeating the purpose.
I could change it to accept mixed
and convert it to a string inside of the function.
(or object|string|float|int|bool|null
and throw or return false if an object could not be converted to a string).
Throwing/warning for bool/null in strict mode may be worth it but may be more convenient to detect with external static analyzers)
It initially seemed consistent with the behavior of https://www.php.net/fwrite to only accept a string
and forcing callers to do so would catch unexpected edge cases with bool/null (''/'1'),
floats, etc. in strict mode.
Surprisingly, some output functions in PHP do accept mixed
.
https://www.php.net/file_put_contents accepts mixed
and casts non-resources
and non-arrays to strings (php-src/ext/standard/file.c)
(handling of arrays/resources is different)
case IS_NULL:
case IS_LONG:
case IS_DOUBLE:
case IS_FALSE:
case IS_TRUE:
convert_to_string(data);
case IS_STRING:
Annoyingly, any decision I make would be inconsistent with something,
e.g. file_put_contents currently doesn't even emit a notice for a failure to convert to string.
php > var_dump(file_put_contents('test.txt', new stdClass()));
bool(false)
It definitely would be longer to use println((string)$foo)
,
but there may be cases where that would be done,
e.g. if you are writing a script that would be reviewed/modified/used by
programmers that are more familiar with languages that aren't PHP.
(It'd be more readable using 1 output method than 3)
There's also println("$foo");
- Most importantly, I accept your points about a function being more
forward- and backward-compatible, but worry that not making it a keyword
will lead to further confusion about how parentheses interact with echo
and print. There is a common misconception that they have some kind of
"optional parentheses", because they are usually used with a single
expression, so wrapping it in parentheses usually doesn't change the
outcome; but this is not the case, and it does sometimes matter.As currently proposed, I can see people getting nasty surprises from
these inconsistencies. For instance:print (1+2)*3; // prints "9"
println (1+2)*3; // prints "3\n"; unless strict_types=1 is in effect, in
which case TypeError
print ($foo ?? 'Foo') . ($bar ?? 'Bar'); // prints "FooBar" if both vars
are null
println ($foo ?? 'Foo') . ($bar ?? 'Bar'); // never prints $bar or
"Bar", because they are not passed to println()
Static analyzers for PHP such as Phan warn about the unused result of multiplication
to catch cases like this, and other analyzers can easily add this check if they don't already check for it.
https://github.com/phan/phan/wiki/Issue-Types-Caught-by-Phan#phannoopbinaryoperator
if ( something() && println($foo) && somethingElse() ) // does what it
looks like, if println is a normal function
if ( something() && print($foo) && somethingElse() ) // does not print
$foo, because the expression passed is actually ($foo)&&somethingElse()
The fact that print
doesn't require parenthesis is something that surprised me initially,
though changing it to force it to use function syntax would be a much larger bc break
more suitable for a major version, that I don't expect to pass.
It may be possible to start deprecating print
if the expression didn't contain a parenthesis
(like the change in precedence of +
and -
did), but I'm not planning to work on that.
(Python converted print
from a statement in Python 2 to a call in Python 3)
Regards,
Tyson
There's also the alias fputs ofhttps://www.php.net/manual/en/function.fwrite.php
which also returns the byte count.
Notably, like printf()
, that is borrowed directly from C, and probably
dates from a time when most PHP programmers were also C programmers.
That time is long past.
Annoyingly, any decision I make would be inconsistent with something
I'm not sure why you're casting your net so wide. The name and use cases
for this function put it squarely next to "print" and "echo" in my mind,
and it would never occur to me to ask if it was consistent with most of
the functions you've mentioned.
It definitely would be longer to use
println((string)$foo)
,
but there may be cases where that would be done,
e.g. if you are writing a script that would be reviewed/modified/used by
programmers that are more familiar with languages that aren't PHP.
(It'd be more readable using 1 output method than 3)
Sorry, I'm not sure what you mean here. What 3 output methods are you
talking about, and how does println((string)$foo) make a difference to them?
There's also
println("$foo");
Which is still marginally longer than the existing print "$foo\n";
Static analyzers for PHP such as Phan warn about the unused result of multiplication
to catch cases like this, and other analyzers can easily add this check if they don't already check for it.
https://github.com/phan/phan/wiki/Issue-Types-Caught-by-Phan#phannoopbinaryoperator
That doesn't stop it being a nasty surprise. People will want to use
"print" and "println" interchangeably, and making that difficult because
they have different syntax is going to end up on lists of "things I hate
about PHP", no matter how easily tools can spot it.
if ( something() && println($foo) && somethingElse() ) // does what it
looks like, if println is a normal function
if ( something() && print($foo) && somethingElse() ) // does not print
$foo, because the expression passed is actually ($foo)&&somethingElse()
The fact that
Just to be clear, it is not that print doesn't require parentheses,
it's that print does not have parentheses, ever.
though changing it to force it to use function syntax would be a much larger bc break
more suitable for a major version, that I don't expect to pass.
It hadn't even occurred to me to suggest that. I was suggesting the
opposite: if we add something called "println", it should have identical
syntax and behaviour to "print". The only difference should be the extra
newline character in the output.
Regards,
--
Rowan Tommins
[IMSoP]
Hi,
I have two questions regarding the RFC.
- Why not provide an another optional attribute that allows to
specify the end of line eliminator? - Why don't you configure Unix end of line in INI file?
These additional steps will help users choose their favorite end of
line for their projects. The INI settings should be INI_ALL, so
libraries for various contexts can alter the attitude. For example,
those who learn PHP in web browsers can use <BR>. Those who use it on
shell will pick \r|\r\n|\n or simply \R. So, web server environments,
such as XAMPP, can set <br> end of line eliminator in the INI file
that they provide.
Example:
<?php
ini_set('println.eol', EOL_UNIX);
println('Hi PHP,');
println();
println('Regards');
?>
Besides, Let me give a strange circumstance that gives inappropriate
result if Unix end of line is used on old windows machine.
Observe the following lines written to shell.
php test.php>test.txt&test.txt
The contents of test.php file:
<?php
$content = file_get_contents(FILE);
foreach (str_split($content) as $index => $char):
printf("$index=$char\n");
endforeach;
?>
Test.txt file will open in windows notepad. Here comes a bug that did
not display Unix end of lines properly in old 7 machines and 8.1
machines. It was fixed in the recent tweaks to Notepad. Will PHP
developers support only windows 10 and ignore the privious OSs?
I also suggest creating end of line constants as integer's, so nobody
could mistakenly write following:
println('Hae, this is my test message.', '');
As for naming constants, I suggest using the following scheme:
EOL_DEFAULT, EOL_PHP, EOL_CR, EOL_LF, EOL_CRLF, and EOL_HTML. Because
there appeared an RFC that requested to Rename T_PAAMAYIM_NEKUDOTAYIM
to T_DOUBLE_COLON. Why not fix this issue before it emerges?
Additionally, multiple constants can be provided, too. EOL_UNIX and
EOL_LF may have same value. The similar case applies to EOL_MAC and
EOL_WINDOWS.
Regards
There's also the alias fputs
ofhttps://www.php.net/manual/en/function.fwrite.php
which also returns the byte count.Notably, like
printf()
, that is borrowed directly from C, and probably
dates from a time when most PHP programmers were also C programmers.
That time is long past.Annoyingly, any decision I make would be inconsistent with something
I'm not sure why you're casting your net so wide. The name and use cases
for this function put it squarely next to "print" and "echo" in my mind,
and it would never occur to me to ask if it was consistent with most of
the functions you've mentioned.It definitely would be longer to use
println((string)$foo)
,
but there may be cases where that would be done,
e.g. if you are writing a script that would be reviewed/modified/used by
programmers that are more familiar with languages that aren't PHP.
(It'd be more readable using 1 output method than 3)Sorry, I'm not sure what you mean here. What 3 output methods are you
talking about, and how does println((string)$foo) make a difference to
them?There's also
println("$foo");
Which is still marginally longer than the existing print "$foo\n";
Static analyzers for PHP such as Phan warn about the unused result of
multiplication
to catch cases like this, and other analyzers can easily add this check if
they don't already check for it.
https://github.com/phan/phan/wiki/Issue-Types-Caught-by-Phan#phannoopbinaryoperatorThat doesn't stop it being a nasty surprise. People will want to use
"print" and "println" interchangeably, and making that difficult because
they have different syntax is going to end up on lists of "things I hate
about PHP", no matter how easily tools can spot it.if ( something() && println($foo) && somethingElse() ) // does what it
looks like, if println is a normal function
if ( something() && print($foo) && somethingElse() ) // does not print
$foo, because the expression passed is actually ($foo)&&somethingElse()
The fact that
surprised me initially,Just to be clear, it is not that print doesn't require parentheses,
it's that print does not have parentheses, ever.though changing it to force it to use function syntax would be a much
larger bc break
more suitable for a major version, that I don't expect to pass.It hadn't even occurred to me to suggest that. I was suggesting the
opposite: if we add something called "println", it should have identical
syntax and behaviour to "print". The only difference should be the extra
newline character in the output.Regards,
--
Rowan Tommins
[IMSoP]--
To unsubscribe, visit: https://www.php.net/unsub.php
On Sat, Mar 13, 2021 at 1:54 PM tyson andre tysonandre775@hotmail.com
wrote:
I've created a new RFC https://wiki.php.net/rfc/println
This proposes adding a global function to PHP to
print a string followed by a unix newline (\n
).
This isn't solving any problem that anyone is actually having.
Yes, that includes you. You're not having this problem because it doesn't
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.
-Sara
On Sat, Mar 13, 2021 at 1:54 PM tyson andre tysonandre775@hotmail.com
wrote:I've created a new RFC https://wiki.php.net/rfc/println
This proposes adding a global function to PHP to
print a string followed by a unix newline (\n
).This isn't solving any problem that anyone is actually having.
Yes, that includes you. You're not having this problem because it doesn't
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.
My opinion matches Sara's, though maybe I wouldn't put it quite in those
words ;)
The difference between these two lines is one character:
echo foo(), "\n";
println(foo());
I don't think this one character is worth adding another way to output
strings, next to the two we already have (echo, print). Especially once you
take into account the not entirely unambiguous semantics of printlln().
echo foo(), "\n" is entirely clear, and distinct from both echo foo(),
PHP_EOL
and echo foo(), "<br />\n".
Regards,
Nikita
On Sat, Mar 13, 2021 at 1:54 PM tyson andre tysonandre775@hotmail.com
wrote:I've created a new RFC https://wiki.php.net/rfc/println
This proposes adding a global function to PHP to
print a string followed by a unix newline (\n
).This isn't solving any problem that anyone is actually having.
Yes, that includes you. You're not having this problem because it doesn't
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.My opinion matches Sara's, though maybe I wouldn't put it quite in those
words ;)The difference between these two lines is one character:
echo foo(), "\n";
println(foo());I don't think this one character is worth adding another way to output
strings, next to the two we already have (echo, print). Especially once you
take into account the not entirely unambiguous semantics of printlln().
echo foo(), "\n" is entirely clear, and distinct from both echo foo(),
PHP_EOL
and echo foo(), "<br />\n".
Apparently I am incapable of counting in the absence of a monospace font.
The difference is actually two characters, but I think the point still
stands... And in some cases it will actually be the other way around,
because echo "foo\n"; is two characters shorter than println("foo");.
Nikita