Closed AlexDaniel closed 6 years ago
Should Nil ~ Nil return an empty Str at all?
I seem to remember there was something related to that kind of operator working on empty lists... It's kind of a more general thing if I remember correctly. Also, since when do we have the trap label?
I think this is basically the consequence of putting Nil or Any in a string context. ~ becomes the string contextualizer then. But... that's rightfully a trap, the problem is that I don't know how general will that be. My hunch is that any empty list will get the same treatment.
@JJ AlexDaniel created the trap label a few hours ago: https://github.com/perl6/doc/issues/1603#event-1697561775
It has nothing to do with Nils. It's just that calling &infix:<~>()
with no args returns an empty string. You can do this kind of stuff with other ops, like *
returns 1, +
returns 0, min
returns Inf.
But my point is that the trap would be concatenating anything that is concatenated with ~. Come to think of it, it might be only Blob/Bufs and Strs...
Please also note that @chunks
above is an empty Positional, not an empty Blob...
In fact:
my Blob $chunks;
say $chunks.^name;
say ([~] $chunks).^name;
# OUTPUT: «BlobUse of uninitialized value of type Blob in string context.
Methods .^name, .perl, .gist, or .say can be used to stringify it to something meaningful.
Str in block <unit> at /tmp/S2dkUqd2ea line 1»
So the traps is unrelated to Blob/Buf, as far as I can see...
No trap was added?
Well, the whole thing is mentioned but not as a trap. I don't really see it as a trap, but I can add an entry there pointing to the explanation in the contexts page.
I don't think it's entirely right, and I don't think that the issue mentioned in this ticket is covered. To recap, the issue here is that the identity element for concatenation is an empty String, it has nothing to do with concatenating Bufs/Blobs with other types. I'll edit it later myself.
@AlexDaniel I think it does. The problem is that ~ concats either Bufs or Strings. Not everything can be converted to Buf, but most stuff can be converted to Str. So as long as there's something that's not Buf, the first form kicks in, trying to convert a Buf into a String.
I mean, in your example above, $x is already a String. Of course any Buf operation fails, it's not a Buf.
The problem is that ~ concats either Bufs or Strings
Correct.
[…] So as long as there's something that's not Buf
The problem is that when there's nothing (no Bufs, no Strs), it gives its identity element ""
(which isn't obviously what you expect when you're working with Bufs/Blobs).
I mean, in your example above, $x is already a String. Of course any Buf operation fails, it's not a Buf.
Correct, but I never intended it to be a Str. That's what this trap is about. I was working with array of Blobs, and I didn't think of an edge case when my array of Blobs was actually empty (so it's an array of nothing, I understand).
Let me see if I follow you. What you are saying is that we reduce an empty array via the concat operator. It's empty, so it could be either strings or bufs so it could opt for returning an empty string or an empty Buf. However, it opts for the former, and that's a trap. Is that it?
Also, this reduce operator on an empty list should return identity for the operation. But that's old, and a lot has rained since then...
Ping...
Yeah, it's much better now. But there's a way to go for perfection, I'll do some finishing touches during the squashathon.
Ping...
Let's say you have a bunch of Bufs or Blobs in array
@chunks
, and you want to concat them:This will work fine as long as you have something in
@chunks
. However, if it happens that@chunks
is empty, then[~]
returns an empty Str (""
).Further operations with
$x
may fail because you don't necessarily expect a Str there. For example, doing$x.decode
will not work.The shortest way to get what you actually want (with all inputs) is
Blob.new: |«@chunks
, or alternatively you can call.append
on a Buf in a loop.