lmi
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [lmi] Why have all relational operators for containers?


From: Vadim Zeitlin
Subject: Re: [lmi] Why have all relational operators for containers?
Date: Wed, 24 Mar 2021 15:27:00 +0100

On Wed, 24 Mar 2021 12:20:41 +0000 Greg Chicares <gchicares@sbcglobal.net> 
wrote:

GC> I was surprised that this is not an error:
GC> 
GC> #include <algorithm>
GC> #include <vector>
GC> 
GC> int main(int, char*[])
GC> {
GC>     std::vector<int> v0 {4, 5, 6};
GC>     std::vector<int> v1 {3, 9};
GC>     std::vector<int> v2 = max(v0, v1); // Not an error.
GC>     std::cout << v2.size() << std::endl;
GC>     std::cout << v2[0] << ", " << v2[1] << ", " << v2[2] << std::endl;
GC>     return 0;
GC> }
GC> 
GC> I thought that would be an error. Instead, it prints "4, 5, 6",
GC> because v0 lexicographically precedes v1.
GC> 
GC> For what reason would the standard provide containers with relational
GC> operators other than '==' and '!='? So that we can sort a vector of
GC> vectors? Is there a stronger rationale that I don't see?

 Sorting a vector of vectors is not a bad rationale, but you also wouldn't
be able to have a set of vectors without operator<(), which would seem
strange, wouldn't it?

 Generally speaking, this is a natural operation for vectors satisfying all
the expected total ordering constraints (unlike, say, the same operation
for doubles!) and while it does result in not very intuitive behaviour
here, I don't feel like having it was really a bad mistake. As you already
said, C++ just doesn't provide vector operations. What you really want is
Raku (nรฉe Perl 6), where you can do

$ raku
Welcome to ๐‘๐š๐ค๐ฎ๐๐จโ„ข v2020.12.
Implementing the ๐‘๐š๐ค๐ฎโ„ข programming language v6.d.
Built on MoarVM version 2020.12.

To exit type 'exit' or '^D'
> my $x0=[4,5,6]
[4 5 6]
> my $x1=[3,9]
[3 9]
> max $x0, $x1 # Same as in C++
[4 5 6]
> $x0 max $x1 # Except there is more than one way to write it!
[4 5 6]
> $x0 >>max>> $x1 # And that you can make a hyperoperator from any operator!!
[4 9 6]
> $x0 ยปmaxยป $x1 # And you can use Unicode, for more APL-like experience!!!
[4 9 6]

(see https://docs.raku.org/language/operators#Hyper_operators)

 Raku operator composability is really very aesthetically pleasant, if
nothing else.

GC> How would the language be worse if it didn't define [pre-C++20]
GC>   template<typename T, typename A>
GC>   bool operator<(std::vector<T,A> const& lhs, std::vector<T,A> const& rhs);
GC> with the following effects?

 FWIW Rust, which is somewhat of C+++, still implements Ord trait, in
addition to Eq, for its Vec type. And, while I'm not 100% sure about it,
even Haskell, which is the paragon of strong-typed languages, also defines
Ord for its lists. So clearly most people consider it advantageous rather
than problematic. Of course, I know that it doesn't help, but here you
are...

 On a more constructive note, I start wonder if you really shouldn't define
your own lmi::Vec type containing a and forwarding to std::vector. This
would allow defining vector operations exactly as you want them to be and
would also, of course, allow not defining comparison operations for this
type. There should be no overhead in using this type if you can move the
existing vectors to/from it, so maybe it's something to consider?

 Regards,
VZ

Attachment: pgp54_0VZiOVG.pgp
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]