You are misunderstanding what `put` does. It does not print the internal representation.
What it does do is turn the value into a `Str` object, then print it with a trailing newline. It just so happens that objects will by default return something that looks like an internal representation when you coerce it to a `Str`. class Point { has ($.x, $.y); } put Point.new( x => 1, y => 2 ).Str # Point<94102525076384> put Point.new( x => 1, y => 2 ).gist # Point.new(x => 1, y => 2) put Point.new( x => 1, y => 2 ).raku # Point.new(x => 1, y => 2) Unless they have a `.Str` method that returns something more sensible. class Point { has ($.x, $.y); method Str () { "[$!x,$!y]" } } put Point.new( x => 1, y => 2 ).Str # [1,2] put Point.new( x => 1, y => 2 ).gist # Point.new(x => 1, y => 2) put Point.new( x => 1, y => 2 ).raku # Point.new(x => 1, y => 2) Note that the default of `.gist` is do the same thing as calling `.raku`. (Many/Most built-in objects have a `.gist` method that returns something different.) --- `s///` and `S///` are both intended as working on `Str` objects. So when you give them something that is not a `Str`, they turn it into a `Str` first. Actually all operations that are `Str` operations will turn it into a `Str` first. Like `.starts-with`, `.ends-with`, `.chars`, `.codes`, `.index`, `.substr`, `print`, and `put` What `say` does, is that instead of calling `.Str` it calls `.gist` `.gist` is defined as giving enough information for a human to be able to figure out what object was printed. (Which is why the default is to return the same thing as `.raku` for defined objects) Actually almost all operations are intended for one type of object, and will coerce to that type. > say ['a', 'b', 'c'] + %( d => 10, e => 20 ) 5 --- Many objects will throw an error if you call `.Str` on them when they are undefined. > Bool.Str Use of uninitialized value of type Bool in string context. Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful. in block <unit> at <unknown file> line 1 > Nil.Str Use of Nil in string context in block <unit> at <unknown file> line 1 Which means they also throw an error if you try to use one of the methods intended for `Str` objects on them. > Bool.substr(0,1) Use of uninitialized value of type Bool in string context. Methods .^name, .raku, .gist, or .say can be used to stringify it to something meaningful. in block <unit> at <unknown file> line 1 > Bool.^name.substr(0,1) B The reason for it generating an error is that generally when you try to turn an undefined object into a Str, there is likely a bug somewhere. --- Since `.gist` is for a human, it doesn't matter if the returned value is a little wrong, so it doesn't fail. (A human can notice if something is wrong. A program that only does what you told it to, generally doesn't.) > Bool.gist (Bool) Note that the reason it puts ( and ) around the name of the object is so that you know that you might have a problem somewhere in your code. --- Further, Nil is actually the most basic of the Failure objects. > for Failure.^mro { say .^name } Failure Nil Cool Any Mu If you get a Nil, there is probably some sort of failure somewhere. > say ( 1, 2, 3, 4 ).first( 'one' ) Nil Which means that if you try to use a Nil as a Str, there is definitely a bug in your code. On Mon, May 18, 2020 at 2:00 AM William Michels via perl6-users < perl6-users@perl.org> wrote: > Hello, > > I'm interested in knowing the differences between the return values > when "say" is used compared to "put". My understanding is that "put" > returns Raku's internal representation of a value held by a variable, > while "say" is merely "put" with the .gist method called on it (a > "human readable", often-abbreviated return value). > > Below I do "S///" (non-destructive) and "s///" (destructive) text > replacement on a three line text file in bash line [1]. In bash line > [2], the full substituted text file is correctly returned; in bash > line [3] using "say" only the $/ match string is returned. So far so > good. However, a virtually-identical call in bash line [4] using "put" > instead of "say" returns an error for the first line of the target > text file: "Use of Nil in string context in block at -e line 1". > > [1] homedir$ cat demo1.txt > this is a test, > I love Unix, > I like Linux too, > > [2] homedir$ perl6 -ne 'say S/love|like/admire/;' demo1.txt > this is a test, > I admire Unix, > I admire Linux too, > > [3] homedir$ perl6 -ne 'say s/love|like/admire/;' demo1.txt > Nil > 「love」 > 「like」 > > [4] homedir$ perl6 -ne 'put s/love|like/admire/;' demo1.txt > Use of Nil in string context > in block at -e line 1 > > love > like > > [5] homedir$ > > I'm really trying to understand this error message: doesn't Raku know > that this is a text replacement operation? How can a 'Nil' be > correctly represented when called by "say", but throw an error when > called by "put"? If the value is absent at the Raku representational > level and throws an error, wouldn't it be reasonable to assume that > the same case would hold for "say"? And finally, does this "say / put" > difference mean that some textual information will be lost from return > values (because "say" will have to be used instead of "put" to avoid > errorring-out)? > > Any enlightenment appreciated, > > TIA, Bill. >