rfc:readable_var_representation

Differences

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

Link to this comparison view

Next revision
Previous revision
rfc:readable_var_representation [2021/01/23 00:05] – created tandrerfc:readable_var_representation [2021/02/19 15:19] (current) – vote declined tandre
Line 1: Line 1:
 ====== PHP RFC: var_representation() : readable alternative to var_export() ====== ====== PHP RFC: var_representation() : readable alternative to var_export() ======
-  * Version: 0.1+  * Version: 0.3
   * Date: 2021-01-22   * Date: 2021-01-22
   * Author: Tyson Andre, tandre@php.net   * Author: Tyson Andre, tandre@php.net
-  * Status: Draft+  * Status: Declined
   * First Published at: http://wiki.php.net/rfc/readable_var_representation   * First Published at: http://wiki.php.net/rfc/readable_var_representation
   * Implementation: https://github.com/php/php-src/pull/6619 (currently using another name)   * Implementation: https://github.com/php/php-src/pull/6619 (currently using another name)
Line 20: Line 20:
   - Unconditionally return a string instead of printing to standard output.   - Unconditionally return a string instead of printing to standard output.
   - Use ''null'' instead of ''NULL'' - the former is recommended by more coding guidelines [[https://www.php-fig.org/psr/psr-2/|such as PSR-2]].   - Use ''null'' instead of ''NULL'' - the former is recommended by more coding guidelines [[https://www.php-fig.org/psr/psr-2/|such as PSR-2]].
 +  - Escape control characters including tabs, newlines, etc., unlike var_export()/var_dump(). See the appendix [[#comparison_of_string_encoding_with_other_languages|Comparison of string encoding with other languages]] to learn more.
   - Change the way indentation is done for arrays/objects. Always add 2 spaces for every level of arrays, never 3 in objects, and put the array start on the same line as the key for arrays and objects)   - Change the way indentation is done for arrays/objects. Always add 2 spaces for every level of arrays, never 3 in objects, and put the array start on the same line as the key for arrays and objects)
   - Render lists as ''"['item1']"'' rather than ''"array(\n  0 => 'item1',\n)"''.   - Render lists as ''"['item1']"'' rather than ''"array(\n  0 => 'item1',\n)"''.
   - Always render empty lists on a single line instead of two lines.   - Always render empty lists on a single line instead of two lines.
   - Prepend ''\'' to class names so that generated code snippets can be used in namespaces without any issues.   - Prepend ''\'' to class names so that generated code snippets can be used in namespaces without any issues.
-  - Support the bit flag ''VAR_REPRESENTATION_SINGLE_LINE=1'' in a new optional parameter ''int $flags = 0'' accepting a bitmask. If the value of $flags includes this flags, ''var_representation()'' will return a single-line representation for arrays/objects, though strings with embedded newlines will still cause newlines in the output.+  - Support the bit flag ''VAR_REPRESENTATION_SINGLE_LINE=1'' in a new optional parameter ''int $flags = 0'' accepting a bitmask. If the value of $flags includes this flags, ''var_representation()'' will return a single-line representation for arrays/objects.
  
 <code php> <code php>
Line 48: Line 49:
 php > echo var_representation([]);  // always print zero-element arrays without a newline php > echo var_representation([]);  // always print zero-element arrays without a newline
 [] []
 +// lines are indented by a multiple of 2, similar to var_export but not exactly the same
 +php > echo var_representation([(object) ['key' => (object) ['inner' => [1.0], 'other' => new ArrayObject([2])], 'other' => false]]);
 +[
 +  (object) [
 +    'key' => (object) [
 +      'inner' => [
 +        1.0,
 +      ],
 +      'other' => \ArrayObject::__set_state([
 +        2,
 +      ]),
 +    ],
 +    'other' => false,
 +  ],
 +]
 </code> </code>
  
Line 61: Line 77:
   'x' => null,   'x' => null,
 ] ]
 +
 +
 </code> </code>
  
Line 84: Line 102:
 === Encoding binary data === === Encoding binary data ===
 This does a better job at encoding binary data in a form that is easy to edit. This does a better job at encoding binary data in a form that is easy to edit.
-var_export() passes through everything except ''\\'', ''\''', and ''\0'',  +var_export() does not contain any bytes except for ''\\'', ''\''', and ''\0'',  
-even control characters such as tabs, vertical tabs, backspaces, carriage returns, etc.+not even control characters such as tabs, vertical tabs, backspaces, carriage returns, newlines, etc.
  
 <code php> <code php>
 php > echo var_representation("\x00\r\n\x00"); php > echo var_representation("\x00\r\n\x00");
 "\x00\r\n\x00" "\x00\r\n\x00"
 +// var_export gives no visual indication that there is a carriage return before that newline
 php > var_export("\x00\r\n\x00"); php > var_export("\x00\r\n\x00");
 '' . "\0" . ' '' . "\0" . '
 ' . "\0" . '' ' . "\0" . ''
 +// Attempting to print control characters to your terminal with var_export may cause unexpected side effects
 +// and unescaped control characters are unreadable
 +php > var_export(implode('', array_map('chr', range(0, 0x1f))));
 +'' . "\0" . '
  
-// bytes above \x80 are passed through with no modification or encoding checks. + 
-// PHP strings are internally just arrays of bytes.+hp > // (first character and closing ' was hidden by those control characters) 
 +php > echo var_representation(implode('', array_map('chr', range(0, 0x1f)))); 
 +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 
 + 
 + 
 +// Bytes \x80 and above are passed through with no modification or encoding checks. 
 +// PHP strings are internally just arrays of bytes and 
 +// different php applications use different encodings. 
 +// E.g. for this interactive shell session in a terminal expecting output with the utf-8 encoding:
 php > echo var_representation('pi=π');  php > echo var_representation('pi=π'); 
 'pi=π' 'pi=π'
Line 103: Line 134:
 'π' 'π'
 </code> </code>
 +
 +=== Cleaner output ===
 +
 +This omits array keys when none of the array keys are required (i.e. when ''array_is_list()'' is true), and puts array values on the same line as array keys.
 +Additionally, this outputs null or unrepresentable values as ''null'' instead of ''NULL'', following [[https://www.php-fig.org/psr/psr-2/|modern coding guidelines such as PSR-2]]
  
 === Supporting namespaces === === Supporting namespaces ===
Line 135: Line 171:
 </code> </code>
  
-Without the backslash, using ''var_export'' to build a snipppet such as ''<nowiki>NS\Something::__set_state([])</nowiki>'' will have the class be relatively resolved as ''OtherNS\NS\Something'' if the output of var_export is used as part of a php file generated using anything other than the global namespace.+Without the backslash, using ''var_export'' to build a snipppet such as ''<nowiki>NS\Something::__set_state([])</nowiki>'' will have the class be incorrectly resolved to ''OtherNS\NS\Something'' if the output of var_export is used as part of a php file generated using anything other than the global namespace.
  
 <code php> <code php>
Line 152: Line 188:
 </code> </code>
  
-=== Cleaner output ===+===== When would a user use var_representation? =====
  
-This omits array keys when they are not required, and puts array values on the same line as array keys+https://externals.io/message/112967#112968 
-Additionallythis outputs ''null'' instead of ''NULL'', following [[https://www.php-fig.org/psr/psr-2/|modern coding guidelines such as PSR-2]]+ 
 +<blockquote> 
 +My hesitation remains that this is just duplicating existing 
 +functionality with only cosmetic differences. 
 + 
 +As a user of PHP 8.1, how would I decide whether to use print_r, 
 +var_dump, var_export, or var_representation? 
 + 
 +And under what circumstances would I bother to write 
 +"var_representation($var, VAR_REPRESENTATION_SINGLE_LINE);"? 
 +</blockquote> 
 + 
 +An end user may wish to use these functions in the following situations: 
 +(These are the personal opinions of the RFC's author) 
 + 
 +==== Use var_representation when: ==== 
 + 
 +var_representation returns a parsable string representation of a variable that is easier to read than var_export. 
 + 
 +It may be useful when any of the following apply: 
 + 
 +  * You are generating a snippet of code to ''eval()'' in a situation where the snippet will occasionally or frequently be read by a human - see the section [[#supporting_namespaces|Supporting Namespaces]](If the output never needs to be read by a human, ''return unserialize(' . var_export(serialize($data), true) . ');'' can be used) 
 +  * The output is occasionally or frequently read by humans (e.g. CLI or web app output, a REPL, unit test output, etc.).  
 +  * The output contains control characters such as newlines, tabs, ''\r'' or ''\x00'' and may be viewed or edited by other users in a text editor/IDE. Many IDEs may convert from windows line endings (''\r\n'') to unix line endings(''\n'') (or vice versa) automatically. 
 +  * You want to unambiguously see control characters in the raw output regardless of how likely they are (e.g. dumping php ini settingsdebugging mysterious test failures, etc) 
 +  * You are writing unit tests for applications supporting PHP 8.1+ (or a var_representation polyfill) that test the exact string representation of the output (e.g. phpt tests of php-src and PECL extensions) - see the section [[#printing_to_stdout_by_default_or_configurably|Printing to stdout by default or configurably]]. 
 +  * You need to copy the output into a codebase that'following a modern coding style guideline such as [[https://www.php-fig.org/psr/psr-2/|modern coding guidelines such as PSR-2]] - see the section [[#cleaner_output|Cleaner Output]]. It saves time if you don't have to remove array keys of lists and convert ''array()'' to ''[]''
 + 
 +==== Use VAR_REPRESENTATION_SINGLE_LINE when: ==== 
 + 
 +This flag may be useful when any of the following apply: 
 + 
 +  * You are writing or modifying tests of exact variable representation and want to write the equivalent of 
 +    <code php> 
 +    $this->assertSame("[\\NS\\MyClass::__set_state(['prop' => true]), 2]", $repr) 
 +    // instead of the much longer and harder to type 
 +    $this->assertSame("[\n  \\NS\\MyClass::__set_state([\n    prop' => true,\n  ],\n  2,\n]", $repr) 
 +    </code> 
 +  * You are generating human-readable output and expect the output to be a small object/array - see the section [[#printing_to_stdout_by_default_or_configurably|Printing to stdout by default or configurably]] 
 +  * You want the output to be as short as possible while still being somewhat human readable, e.g. sending an extremely long array representation over the network, or are saving it to a file/cache/external service, or you're using var_representation($mixed) as an array key for thousands of objects. 
 + 
 +==== Use var_export when: ==== 
 + 
 +var_representation returns a parsable string representation of a variable (that has the limitations described in this RFC) 
 + 
 +  * You are writing an application or library that would benefit from behaving the exact same way in php 8.0 and 8.1, and polyfilling is impractical (e.g. for performance reasons or packaging requirements such as being distributed without additional dependencies (e.g. a single-file script)) 
 +  * You prefer string output escaped with single quotes mixed with newlines, tabs, and embedded control characters (especially if control characters are unlikely), or want to render NULL as an uppercase scalar. 
 +  * You need to generate output that can be ''eval()''ed even in PHP versions [[https://wiki.php.net/rfc/shortsyntaxforarrays|5.3 or older]]. 
 + 
 +==== Use var_dump when: ==== 
 + 
 +  * You do not need valid php code. 
 +  * You need to inspect a datastructure to determine if it contains references or recursive data structures such as recursive objects or recursive array references. 
 +  * You need a human-readable representation of data, don't need valid php syntax, and want to distinguish between  
 + 
 +==== Use debug_zval_dump when: ==== 
 + 
 +[[https://www.php.net/manual/en/function.debug-zval-dump.php|debug_zval_dump]] dumps a string representation of an internal zend value to output. 
 + 
 +  * You do not need valid php code. 
 +  * You are looking into bugs in the internals of php (e.g. incorrect reference counting of php values leading to memory leaks or premature freeing) and need to know exact reference counts 
 +  * You are generating a test case for a PECL extension or php-src validating that a reference counting bug is fixed. 
 + 
 +<code php> 
 +php > $y = [new stdClass()]; $y[1] = &$y[0];  
 +php > debug_zval_dump($y); 
 +array(2) refcount(2){ 
 +  [0]=> 
 +  &object(stdClass)#1 (0) refcount(1){ 
 +  } 
 +  [1]=> 
 +  &object(stdClass)#1 (0) refcount(1){ 
 +  } 
 +
 +php > var_dump($y); 
 +array(2) { 
 +  [0]=> 
 +  &object(stdClass)#1 (0) { 
 +  } 
 +  [1]=> 
 +  &object(stdClass)#1 (0) { 
 +  } 
 +
 +php > var_export($y);  // here, you get valid php code but don't see the object ids and can't tell if they're different objects 
 +array ( 
 +  0 =>  
 +  (object) array( 
 +  ), 
 +  1 =>  
 +  (object) array( 
 +  ), 
 +
 +</code> 
 + 
 +==== Use print_r when: ==== 
 + 
 +[[https://www.php.net/print_r|print_r]] prints human-readable information about a variable - it is like print() but recursive. 
 + 
 +  * You do not need valid php code. 
 +  * You want human-readable output, string escaping isn't a concern for your use case, and differentiating between strings, integers, floats, booleans, and null doesn't need to happen (printed the same way as print()). This can be useful if keys and values are almost always the same types. 
 + 
 +The below snippet is an example of where you may not want to use print_r(). 
 + 
 +<code php> 
 +php > print_r([['key' => 'first', 'other' => 'second', 'third' => '1'], '1', 1, 1.0, true, false, null, '']); 
 +Array 
 +
 +    [0] => Array 
 +        ( 
 +            [key] => first 
 +            [other] => second 
 +            [third] => 1 
 +        ) 
 + 
 +    [1] => 1 
 +    [2] => 1 
 +    [3] => 1 
 +    [4] => 1 
 +    [5] =>  
 +    [6] =>  
 +    [7] =>  
 +
 +</code>
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 189: Line 347:
  
 Adding more flags here would increase the scope of the rfc and complexity of implementing the change and for reviewing/understanding the implementation. Adding more flags here would increase the scope of the rfc and complexity of implementing the change and for reviewing/understanding the implementation.
 +
 +=== Supporting an indent option ===
 +
 +This was left out since I felt it would increase the scope of the RFC too much.
 +
 +If  an ''indent'' option might be supported by also allowing ''var_representation(value: $value, flags: ['flags' => VAR_REPRESENTATION_SINGLE_LINE, 'indent' => "\t"])'' or by bitmask flags such as ''VAR_REPRESENTATION_INDENT_FOUR_SPACES''/''VAR_REPRESENTATION_INDENT_TABS''/''VAR_REPRESENTATION_INDENT_NONE''.
 +
 +The fact that embedded newlines are now no longer emitted as parts of strings makes it easier to efficiently convert the indentation to spaces or tabs using ''preg_replace'' or ''preg_replace_callback''
 +
 +<code php>
 +php > echo var_representation([[['key' => 'value  with  space']]]);
 +[
 +  [
 +    [
 +      'key' => 'value  with  space',
 +    ],
 +  ],
 +]
 +php > echo preg_replace('/^((  )+)/m', '\1\1', var_representation([[['key' => 'value  with  space']]]));
 +[
 +    [
 +        [
 +            'key' => 'value  with  space',
 +        ],
 +    ],
 +]
 +</code>
 +````
  
 ==== Adding magic methods such as __toRepresentation() to PHP ==== ==== Adding magic methods such as __toRepresentation() to PHP ====
Line 207: Line 393:
 However, I don't know if there's widespread interest in that, and this would increase the scope of this RFC. However, I don't know if there's widespread interest in that, and this would increase the scope of this RFC.
  
-===== Proposed Voting Choices ===== +==== Emitting code comments in result about references/types/recursion ==== 
-Yes/No, requiring 2/3 majority.+ 
 +Adding a comment such as ''/* resource(2) of type (stream) */ null'' to the var_representation output with an opt-in flag (e.g. ''VAR_REPRESENTATION_ADD_TYPE_COMMENTS'') to add this information may be useful to explore in follow-up work (to meet more use cases of ''var_dump''). 
 + 
 +(Or ''/* RECURSION  */ NULL'', or ''[/* reference */ 123, /* reference */ 123]'', etc.) 
 + 
 +===== Discussion ===== 
 + 
 +==== PHP already has a lot of ways to dump variables ==== 
 + 
 +https://externals.io/message/112924#112943 
 + 
 +<blockquote> 
 +While I agree that all the suggestions in this thread would improve 
 +var_export, I worry that it is failing a "smell test" that I often apply: 
 + 
 +"If you're struggling to come up with the appropriate name for something 
 +that you're creating, maybe you're creating the wrong thing." 
 + 
 +In this case, the reason it's difficult to name is that PHP already has 
 +rather a lot of different ways to produce a human-readable string from a 
 +variable. The synopses in the manual aren't particularly enlightening: 
 + 
 +print_r — Prints human-readable information about a variable 
 +var_dump — Dumps information about a variable 
 +var_export — Outputs or returns a parsable string representation of a 
 +variable 
 +Then there's the slightly more exotic (and rather less useful than it 
 +once was) debug_zval_dump; serialization formats that are reasonably 
 +human-friendly like json_encode; and any number of frameworks and 
 +userland libraries that define their own "dumper" functions because they 
 +weren't satisfied with any of the above. 
 + 
 +The name of any new function in this crowded space needs to somehow tell 
 +the user why they'd use this one over the others - and, indeed, when 
 +they wouldn't use it over the others. 
 + 
 +Should we be aiming for a single function that can take over from some 
 +or all of the others, and deprecate them, rather than just adding to the 
 +confusion? 
 +</blockquote> 
 + 
 +https://externals.io/message/112924#112953 
 + 
 +<blockquote> 
 +<blockquote> 
 +IMO print_r/var_dump should be kept out of this discussion. Those are human 
 +readable outputs for human consumption. var_export() is about a machine 
 +readable output for recreating initial state within a runtime. The 
 +requirements presented are wholly different. 
 + 
 +-Sara 
 +</blockquote> 
 + 
 +If the goal of var_export is only to have some machine-readable output, the following will do it: 
 + 
 +<code php> 
 +<?php 
 +function my_var_export(mixed $x): string { 
 +$serialized = \base64_encode(\serialize($x)); 
 +return "\unserialize(\base64_decode('$serialized'))"; 
 +
 +?> 
 +</code> 
 + 
 +In reality, the output of var_export() is both machine-readable and human-readable. 
 + 
 +—Claude 
 +</blockquote> 
 + 
 +I believe that the improvements of var_representation make adding a new function worth it. See the section [[#use_var_representation_when|"Use var_representation when"]]. 
 + 
 +As mentioned earlier, a lot of existing php code depends on the exact default output of var_export() (e.g. unit tests of php-src itself and otherwise), which was introduced in php 4.2 and predates namespaces and short arrays. 
 +Changing it would result in a lot of work in php-src, PECL, and projects written in PHP to support both old and new syntaxes for var_export. 
 + 
 +The last time ''var_export()'' changed was from ''<nowiki>stdClass::__set_state(array())</nowiki>'' to ''(object) []'' in PHP 7.3.0, but that was something that had a clearer reason to fix - ''<nowiki>stdClass::__set_state</nowiki>'' is an undeclared function and many users were inconvenienced by being unable to generate code for stdClass instances. 
 + 
 +===== Vote ===== 
 +This is a Yes/No vote, requiring 2/3 majority. Voting started on 2021-02-05 and ended 2021-02-19. 
 + 
 +<doodle title="Add var_representation($value, int $flags=0): string to php?" auth="tandre" voteType="single" closed="true"> 
 +   * Yes 
 +   * No 
 +</doodle>
  
 ===== References ===== ===== References =====
-Links to external referencesdiscussions or RFCs+ 
 +  * https://externals.io/message/112967 "[RFC] var_representation() : readable alternative to var_export()" 
 +  * https://externals.io/message/112924 "Proposal: short_var_export($valuebool $return=false, int $flags=0)" 
 +  * https://externals.io/message/109415 "[RFC][DISCUSSION] Change var_export() array syntax to use short hand arrays" (A competing RFC that started discussion 9 months ago in March 2020). See quote in the section [[#printing_to_stdout_by_default_or_configurably|Printing to stdout by default or configurably]] about previous discussions not being particularly open to changing var_export behavior. 
 +  * https://wiki.php.net/rfc/var-export-array-syntax "PHP RFC: Change var_export() array syntax to use shorthand arrays" (A competing RFC that started discussion 9 months ago in March 2020) 
 + 
 +===== Appendix ===== 
 +==== Comparison of string encoding with other languages ==== 
 + 
 +See https://man7.org/linux/man-pages/man7/ascii.7.html for details about ascii 
 +<blockquote> 
 +ASCII is the American Standard Code for Information Interchange. 
 +It is a 7-bit code (with 128 characters).  Many 8-bit codes (e.g., ISO 8859-1) contain 
 +ASCII as their lower half.  The international counterpart of 
 +ASCII is known as ISO 646-IRV. 
 +</blockquote> 
 + 
 +If there are any control characters (in the ranges \x00-\x1f and \x7f), ''var_representation()'' uses double quotes instead of single quotes. 
 +If there are no control characters, strings are represented the way ''var_export()'' currently represents them. 
 + 
 +<code php> 
 +php > echo var_representation(implode('', array_map('chr', range(0, 0x1f)))), "\n"; // ascii \x00-0x1f 
 +"\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" 
 +php > echo var_representation(implode('', array_map('chr', range(0x20, 0x7f)))), "\n"; // ascii \x20-0x7f 
 +" !\"#\$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f" 
 +</code> 
 + 
 +Python appears to have the same inner representation with shorter representations only for ''\t\n\r'' (Python allows escaping inside of single quoted strings). 
 + 
 +<code python> 
 +# \x00-\x1f 
 +print(repr(''.join(chr(c) for c in range(0, 0x20))))                           
 +'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' 
 +# \x20-\x7f 
 +print(repr(''.join(chr(c) for c in range(0x20, 0x80))))                        
 +' !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f' 
 +</code> 
 + 
 + 
 +JSON escapes a wider range of control characters, but the format does not require escaping backspaces(\x7f), which are permitted in string literals. 
 + 
 +<code javascript> 
 +> console.log(JSON.stringify("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f")); 
 +"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f" 
 +> console.log(JSON.stringify(" !\"#$%&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f")); 
 +" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" 
 +</code> 
 + 
 +Ruby has additional shorter escapes for ''\a\b\v\f'' and also escapes backslashes. For many users, ''\a\b\v\f'' are obscure terminal/text file functionality and the hex representation may be more useful. 
 + 
 +<code ruby> 
 +puts("\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f".inspect) 
 +"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\a\b\t\n\v\f\r\u000E\u000F\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001A\e\u001C\u001D\u001E\u001F" 
 +puts(" !\"#$%&'()*+,-.\/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f".inspect) 
 +" !\"\#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007F" 
 +</code>
  
 ===== Rejected Features ===== ===== Rejected Features =====
  
-==== Printing to stdout by default/configurably ====+==== Printing to stdout by default or configurably ====
  
 Printing to stdout and creating a string representation are two distinct behaviors, which some would argue should not be combined into the same function. Printing to stdout and creating a string representation are two distinct behaviors, which some would argue should not be combined into the same function.
Line 310: Line 633:
   - This may be much slower and end users may not expect that - a lot of small stream writes with dynamic C function calls would be something I'd expect to take much longer than converting to a string then writing to the stream.  (e.g. I assume a lot of small echo $str; is much faster than ''\fwrite(\STDOUT, $str);'' in the internal C implementation) (if we call ''->serialize()'' first, then there's less of a reason to expose ''->serializeFile()'' and ''->serializeStream()'')   - This may be much slower and end users may not expect that - a lot of small stream writes with dynamic C function calls would be something I'd expect to take much longer than converting to a string then writing to the stream.  (e.g. I assume a lot of small echo $str; is much faster than ''\fwrite(\STDOUT, $str);'' in the internal C implementation) (if we call ''->serialize()'' first, then there's less of a reason to expose ''->serializeFile()'' and ''->serializeStream()'')
   - Adding even more ways to dump to a stream/file. Should that include stream wrappers such as http://?  For something like XML/YAML/CSV, being able to write to a file makes sense because those are formats many other applications/languages can consume, which isn't the case for var_export.   - Adding even more ways to dump to a stream/file. Should that include stream wrappers such as http://?  For something like XML/YAML/CSV, being able to write to a file makes sense because those are formats many other applications/languages can consume, which isn't the case for var_export.
 + 
 +==== Changing var_dump ====
 +
 +var_dump is a function which I consider to have goals that are incompatible ways.
 +If an exact representation of reference cycles, identical objects, and circular object data is needed, the code snippet ''unserialize("....")'' can be generated using ''var_representation(serialize($value))'' (or var_export).
 +
 +In particular, var_dump() dumps object ids, indicates objects that are identical to each other, shows recursion, and shows the presence of references. It also redundantly annotates values with their types, and generates output for types that cannot be evaluated (e.g. ''resource(2) of type (stream)'').
 +
 +Adding a comment such as ''/* resource(2) of type (stream) */ null'' to the var_representation output with an opt-in flag to add this information may be useful to explore in follow-up work.
 +
 +https://externals.io/message/112967#112970
  
 +===== Changelog =====
  
 +  * 0.2: Add the section "When would a user use var_representation?". Add a comparison with other languages.
 +  * 0.3: Add more examples, add discussion section on indent
rfc/readable_var_representation.1611360336.txt.gz · Last modified: 2021/01/23 00:05 by tandre