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-us...@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.
>

Reply via email to