Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stringy feels over-engineered, partially implemented and bitrotted #445

Open
lizmat opened this issue Oct 8, 2024 · 9 comments
Open

Stringy feels over-engineered, partially implemented and bitrotted #445

lizmat opened this issue Oct 8, 2024 · 9 comments
Labels
language Changes to the Raku Programming Language

Comments

@lizmat
Copy link
Collaborator

lizmat commented Oct 8, 2024

And it would make things a lot simpler if it were to be removed.

Or at least have better documentation about its functionality.

@lizmat lizmat added the language Changes to the Raku Programming Language label Oct 8, 2024
@lizmat
Copy link
Collaborator Author

lizmat commented Oct 8, 2024

Inspired by rakudo/rakudo#2548

@alabamenhu
Copy link

I appreciate the attempt at Stringy. Conceptually, it makes sense:

Specific Generic
Int
Num
Rat
Complex
Numeric
List
Array
Positional
Map
Hash
Associative
Str
Blob
Uni
Stringy

But a few things throw this off. Blob and Uni are simultaneously Stringy and Positional. But I don't recall seeing anyone ever treat Blob in a string-like manner, only Positional. After all, Buf's methods almost all mirror those seen in other Positional classes, not those in Str.

I could envision someone potentially using Uni in stringy contexts but importantly, Uni is not Str and no one ever asks for the generic role, making it fairly useless (now if Uni were a Blob that was a subclass of Str, I could see more utility coming out of it, but I think we might be too far out to change anything there, though I rarely if ever see Uni so maybe not)

Ultimately, we as a community have chosen to use Str as Stringy, and Blob and Uni as Positional. If Str is the only class that implements Stringy, and accordingly everyone only uses Str when type checking, wherefore is Stringy?

@librasteve
Copy link

I have come across Stringy in my various explorations of Allomorphs.
https://docs.raku.org/type/Stringy#typegraphrelations

Conceptually, I would say that there is value in differentiating the Role and Class aspects of a raku datatype:

For example, we have:

RatStr
is Allomorph
is Rat is Cool
is Str is Cool
does Stringy
does Rational
does Real
does Numeric

So seems to me that the raku type system is dogfooding roles and classes in a good way.

The class isa relationships go to Cool which is a thing that has real functions and instances take memory
The role does relationships are more abstract and help to associate common aspects - eg Rat and FatRat do Rational

So I would be fine to drop Blob and Uni from the Stringy role (I am not sure why that was considered a good design in the first place)

But, I would be sad if there were no Stringy <=> Numeric level of conceptual distinction as distinct from the Str <=> Int level of implementation distinction.

One benefit of this is that the number world has more layers and branches vs. the stringy world and I can imagine this changing or that I would like to consume these roles for my own custom types.

@alabamenhu
Copy link

Agreed -- conceptually it makes sense.

But in practice, what is the practical difference for those allomorphs? They're all ultimately Stringy only by virtue of being Str, which gets us back to the question of the purpose of Stringy.

One of the values of the Positional and Associative roles is that I can create a drop in replacement for anything that functionally works just a List/Hash/etc. All of the methods, indexing, splicing, iterating, etc, are all fundamentally based around all of just a handful of core methods that must be implemented by anything wanting those roles.

But Stringy neither requires nor provides anything. So where as I can do a lot with the following sub:

sub foo(Numeric $a, Numeric $b) { ... }

Doing a generic

sub bar(Stringy $a, Stringy $b) { ... }

I can't really do anything. The only methods I can call on them are those inherited from Any, at which point, I might as well avoid that type information entirely. I can't even do $a ~ $b (and ~ is literally stringy concatenation), because:

my $a = blob8.new: 97, 98, 99;  
my $b = "ABC";
say $a ~ $b; 
# Cannot use a Buf as a string, but you called the Stringy method on it

The latter one is REALLY bad because you would think the following code would work and return a blob of sorts and thus you'd be safe to concat the results of two separate calls to foo

sub foo(*@a where .all ~~ Blob) { return [~] |@a }
my $b = blob8.new: 42;
say foo($b) ~ foo($b, $b); # Good
say foo() ~ foo($b, $b); # Nope

But in the second call with no args, the identity is used (e.g. 1 for multiplication, or 0 for addition), which in this case is the empty Str! And as we just saw, we can't concat a Str with a Blob so.... unexpected blowup.

I think the best thing to do is going to be to retire Stringy, unless there's some way to fully rescue it. I can think of some ways but they'd probably definitely be major breaking changes. Removing Stringy, though, would be easy, and if someone wanted to restore the functionality, they could easily do:

role Stringy { ; }
augment class Str { also does Stringy } 

This would probably require some reworking on Blob and Bluf, as those are roles that are, afaict, punned which makes it difficult to augment.

@kjpye
Copy link

kjpye commented Oct 15, 2024

The problem with alabamhenu's example using a Stringy identity is that the identity is an empty string, rather than a more generic empty Stringy object.

It is quite easy to fix rakudo to make [~] work for Blobs and Bufs—just add the line

multi sub infix:<~>('', Buf:D $a) { $a }

near the other definitions of infix:<~> in Buf.rakumod. (Somewhere line 1430 at the moment). Last I looked this doesn't break spectest.

A better solution would be to define a more generic Stringy empty object and add the relevant definitions for infix:<~> in the source for strings and blobs.

(I am assuming that deleting the Stringy role would keep ~ as the concatenation operator for Blobs.)

@alabamenhu
Copy link

@kjpye: while on the surface, it might look like it could fix it, I'd be hesitant to say that defining '' ~ $blob as resulting in $blob. That feels hacky at best, and probably will have some implications elsewhere (does '' ~ blob8.new result in an empty Str or blob8? what about blob8.new ~ '' or blob8.new ~ 'foo'? What if in my code above I did (foo() ~ foo()).head? For a Blob I should get Nil -- falsey and undefined, but for the empty string, I get the empty string -- falsey but defined!

The generic stringy empty object will run into other issues. Imagine I pass the result of a [~] operation to a function that type checks for Str (or Blob). Now we have a non-Str, non-Blob option. We could maybe make it an allomorph, but there may be other implications for having that type of a thing floating around.

(I'm not opposed to such an allomorph, I've thought it would be good if the various Uni classes were exactly that, but then we'd have to figure out the mechanics of their ops which is non-trivial. OTOH it would feel hacky to have it for a single empty-object use case).

The only simple thing is getting rid of Stringy :) Going much past that, and things get more complicated quickly.

@jubilatious1
Copy link

I'd love to continue the conversation I started with @thoughtstream about formalizing Ternary Logic in Raku, for Data Science purposes.

Not sure if Stringy fits that role, but you'll need a value (probably Nil) that is never equivalent to itself ("an unknown can never logically equal another unknown").

Oh yes, and an operator that goes along with it, maybe =t= ?

> Nil =t= Nil
Nil

@antononcube

@thoughtstream

This comment was marked as off-topic.

@raiph
Copy link

raiph commented Oct 18, 2024

@thoughtstream, @jubilatious1

I suggest we hide our comments about ternary logic in this thread, then continue here until there's clarity about a more appropriate place to discuss it.

(This comment will self-destruct be hidden by me once you've both commented in the linked gist.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Changes to the Raku Programming Language
Projects
None yet
Development

No branches or pull requests

7 participants