October 14, 2022

On Thursday, 13 October 2022 at 20:28:52 UTC, solidstate1991 wrote:

>

require unicode, which would upset a lot of people

Require unicode and break another convention in one go is even more effective:

October 14, 2022

On Friday, 14 October 2022 at 18:29:10 UTC, Walter Bright wrote:

>

[snip]
True that documentation often (always?) lies about what the code actually does. But the causes of this are usually because of programmer laziness and/or error in documenting it correctly.

But operating overloading for non-arithmetic purposes is deliberately doing the unexpected.

What is your opinion about R's custom infix binary operators? (ignoring that R is dynamically typed)

So for instance, you can make a function

`%foo%` <- function(x, y) { #does something }

and use it like x %foo% y

The surrounding % lets the user know that anything could be happening in there. However, it doesn't have to just be some string, it could be anything. For instance, R comes with %*% built-in for matrix multiplication and a few others.

From D's perspective, it doesn't really make sense to use a string since we have UFCS and it is just as easy to use x.foo(y) [in R you would have to do foo(x, y) if this feature didn't exist]. However, it is useful when it is some symbol that would otherwise have a longer name. Code that is full of X.matmul(Y) is harder to read than X %*% Y.

October 14, 2022
On Friday, 14 October 2022 at 06:59:43 UTC, Walter Bright wrote:
> On 10/13/2022 7:44 PM, H. S. Teoh wrote:
>>> and also a project he saw in the past that overloaded C++ operators to
>>> make a regex DSL.
>> [...]
>> 
>> That would be Boost.Xpressive, I think.
>
> Here it is:
>
> #include <boost/spirit.hpp>
> using namespace boost;
> int main() {
>     spirit::rule<> group, fact, term, expr;
>     group   = '(' >> expr >> ')';
>     fact    = spirit::int_p   | group;
>     term    = fact >> *(('*' >> fact) | ('/' >> fact));
>     expr    = term >> *(('+' >> term) | ('-' >> term));
>     assert( spirit::parse("2*(3+4)", expr).full );
>     assert( ! spirit::parse("2*(3+4", expr).full );
> }
>
> https://studylib.net/doc/10029968/text-processing-with-boost---northwest-c---users--group
>
> slide 40
>
> It's a technical marvel, but the embedded DSL looks like C++ expressions yet does something completely different. One cannot distinguish the C++ code from the DSL code. It's in the same category as macros, and I can't recommend it.

Potentially controversial response: Who cares? The alternative in D is basically just the same code with some quotes around it (a DSL like pegged).

You can do real sin with operating overloading, or just badly chosen operators, but this particular one really isn't that bad. The alternative is preprocessor macros, which are considerably worse.
October 14, 2022
On Friday, 14 October 2022 at 18:29:10 UTC, Walter Bright wrote:
> On 10/14/2022 12:54 AM, Atila Neves wrote:
>> As Bjarne said once in response to complaints that operator overloading lets people write code that doesn't do what you expect:
>> 
>> ```
>> // notice how the code and the docs lie
>> /**
>>   * Adds two numbers
>>   */
>> int sum(int i, int j) {
>>      return i - j;  // oops
>> }
>> ```
>
> True that documentation often (always?) lies about what the code actually does. But the causes of this are usually because of programmer laziness and/or error in documenting it correctly.
>
> But operating overloading for non-arithmetic purposes is *deliberately* doing the unexpected.

A slightly more useful way of thinking about this I think is to think about it algebraically, i.e. If the nu-operation is confusing algebraically then it is *definitely* wrong versus merely not to taste. You can do useful algebra on things that wouldn't typically be considered arithmetic, that algebra often has an analogue in familiar arithmetic on numbers (we'll gloss over floating point arithmetic...)

In the case of `sum`, we'd expect it to be associative - it's not, something has gone wrong. This is a more precise way of expressing that "Go home, you're drunk" feeling from this kind of code.

D not using + for strings was something that helped sell me on it early on. Intuitively we all know concatenation isn't commutative anyway, but it doesn't hurt to express it lexically.


October 14, 2022
On Fri, Oct 14, 2022 at 08:24:47PM +0000, jmh530 via Digitalmars-d wrote: [...]
> So for instance, you can make a function
> ```
> `%foo%` <- function(x, y) { #does something }
> ```
> and use it like `x %foo% y`
> 
> The surrounding `%` lets the user know that anything could be happening in there. However, it doesn't have to just be some string, it could be anything. For instance, R comes with %*% built-in for matrix multiplication and a few others.

IMO, %*% is extremely ugly to read.


> From D's perspective, it doesn't really make sense to use a string since we have UFCS and it is just as easy to use `x.foo(y)` [in R you would have to do foo(x, y) if this feature didn't exist]. However, it is useful when it is some symbol that would otherwise have a longer name. Code that is full of `X.matmul(Y)` is harder to read than `X %*% Y`.

It's just a matter of formatting; just write it like this:

	X .mul (Y)

and it will read just fine.  The mandatory parentheses are actually a good thing to prevent confusion with operator precedence. (Making operator precedence user-configurable may not be a good idea -- it forces you to do semantic analysis before the syntax can be parsed, and will add far more complexity to the parser than is justifiable by the marginal benefits.)

For this specific example, though, I'd say just overload *. Matrix multiplication is called "multiplication" because it generally *does* behave like a multiplicative arithmetic operator. As opposed to like array manipulation or I/O.  So I'd call it an appropriate use of operator overloading in this case.


T

-- 
One Word to write them all, One Access to find them, One Excel to count them all, And thus to Windows bind them. -- Mike Champion
October 14, 2022

On Friday, 14 October 2022 at 20:24:47 UTC, jmh530 wrote:

>

So for instance, you can make a function

`%foo%` <- function(x, y) { #does something }

and use it like x %foo% y

You can actually do that in D with some hacks:

struct Operator(alias fn, string operator = "/")
{
    static auto opBinaryRight(string op : operator, T...)(T value1)
    {
        struct Result
        {
            auto opBinary(string op : operator, U...)(U value2)
                if (__traits(compiles, fn(value1, value2)))
            {
                return fn(value1, value2);
            }
        }

        Result result;
        return result;
    }
}

void main()
{
    import std.algorithm.comparison;
    alias min = Operator!(std.algorithm.comparison.min, "%");
    assert(1 %min% 3 == 1);
}

Credit to Simen Kjærås:
https://forum.dlang.org/post/ldiwiffdyzeswggytudh@forum.dlang.org

October 14, 2022
On 10/14/2022 1:49 PM, Max H wrote:
> Potentially controversial response: Who cares? The alternative in D is basically just the same code with some quotes around it (a DSL like pegged).

With color syntax highlighting, nobody will think the quoted string is ordinary D code. It's also why the `mixin` keyword is a keyword - to make it stand out.

> You can do real sin with operating overloading, or just badly chosen operators, but this particular one really isn't that bad. The alternative is preprocessor macros, which are considerably worse.

The best alternative to a proper DSL is to simply use functions instead of operators.

October 14, 2022
On 10/14/2022 1:24 PM, jmh530 wrote:
> What is your opinion about R's custom infix binary operators? (ignoring that R is dynamically typed)
> 
> So for instance, you can make a function
> ```
> `%foo%` <- function(x, y) { #does something }
> ```
> and use it like `x %foo% y`

I've thought about it many times. It keeps coming back to "it's just too ugly."

Operator precedence is also a problem.

October 14, 2022
On 10/14/2022 2:07 PM, Max H wrote:
> D not using + for strings was something that helped sell me on it early on. 

When I was working on that, I could not believe that other languages persisted in conflating add with concatenate, which continues to cause confusion.
October 15, 2022
On Friday, 14 October 2022 at 22:48:51 UTC, Walter Bright wrote:
> On 10/14/2022 2:07 PM, Max H wrote:
>> D not using + for strings was something that helped sell me on it early on.
>
> When I was working on that, I could not believe that other languages persisted in conflating add with concatenate, which continues to cause confusion.

Perhaps ironically, one of the languages that got this right was Perl: it used + for numeric addition and . (period) for string concatenation.