ANN: Free-form-operators patch

Charles Hixson said:

This is one place that I don't think Eiffel got things quite right.
Precedence should be defineable, not necessarily higher than all
built-in operators. If one is defining a cross-product, e.g., one
doesn't necessarily want it to be of higher precedence than whatever one
is using to define the literal representation of the matrix. And
ordinary arithmetic might be of even higher precedence. E.G.:

> .< 1 + 3, 5 * 2, 6 / 3 >. .<n21, n22, n23>. .<n31, n32, n33>. | .*. M

Hmmmm ... I'm not sure that the .<, >. and | are technically operators
(certainly not binary operators). They seem to be merely syntactical
markers.

The problem with definable precedence is that precedence is a compile time
operation and the selection of the operator implementation is a run time
thing. Consider ...

   x @a y @b z

(note: Syntax is Eiffel style syntax, so @a and @b are operators. Ignore
for the moment that this conflicts with Ruby syntax for instance variables
and go with me here).

Should this be parsed ((x @a y) @b z) or (x @a (y @b z))? Operators are
generally transformed into method calls, e.g. (x @a y) => (x.@a(y)). So
we look at the runtime class of x to find the operator and determine the
precedence. Unfortunately, at the time the expression is compiled the
runtime class of x isn't available! Indeed, x may have a different class
every time the expression is executed.

So, that leaves us two choices: (1) Reparse the expression everytime it is
executed, or (2) globally define the precedence of an operator across all
classes.

(1) seems a bit too dynamic for my taste, and (2) is troublesome when you
have more than one class defining the operator.

Given that, I wouldn't mind user defined operators in Ruby under the
following conditions...

(A) The operators are visually distinctive. In Eiffel, all user defined
operators must begin with a limited set of symbols (@, #, &, and | IIRC).
After the initial symbol, any printable, non-space character is allowed.
So @in, @cross, &and, #..# are all recognized as operators according to
the Eiffel rules.

(B) Fixed precedence. User defined unary operators should have the same
precedence as other unary operators. User defined Binary operators should
be the same as the highest precedence binary operator under the unary
operators.

Point A means that I don't have to parse a random string of symbols in my
head and decide whether it is legal Ruby syntax or user defined operators
(or Beetle Baily swearing). Ruby's problem is that all the punctuation
characters are already used for other purposes, it would be difficult to
set aside yet another character for this purpose. Perhaps something like
@op@ can be used.

Regarding the matrix example, I find it less than compiling, especially
when existing Ruby can be used to get something quite readable ...

   Matrix [
     [ 1 + 3, 5 * 2, 6 / 3 ],
     [ n21, n22, n23 ],
     [ n31, n32, n33 ]
   ].cross M

···

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

From: "Markus" <markus@reality.com>
>
> * It makes the parser about 150 lines shorter

Wow, amazing! Sounds like you found a way to generalize
what used to be code handling the existing operators
separately?

     Yes, though I haven't gone as far in that direction as I'd like;
since I'm not a C programmer (and this is my first attempt to mess with
the parser) I was being conservative.

Nice work !

     Thanks!

   -- Markus

···

On Fri, 2004-10-08 at 15:33, Bill Kelly wrote:

Charles Hixson ha scritto:

This is one place that I don't think Eiffel got things quite right. Precedence should be defineable, not necessarily higher than all built-in operators. If one is defining a cross-product, e.g., one doesn't necessarily want it to be of higher precedence than whatever one is using to define the literal representation of the matrix. And ordinary arithmetic might be of even higher precedence. E.G.:

yes, but this would be library interaction nightmare.

* Markus <markus@reality.com> [Oct 09, 2004 14:02]:

    Yes, that was part of my inspiration for this. In theory it is
simple; in practice (especially since I don't know C) the devil has been
in the details. Specifically, Eiffel doesn't execute
definitions/declarations, while ruby does. This makes life more
interesting.

Take a look at Haskell. It has user-defined operators with adjustable
precedence,
  nikolai

···

--
::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::
::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::
::: page: www.pcppopper.org :: fun atm: gf,lps,ruby,lisp,war3 :::
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Markus wrote:

    Ah, but that would be great! (And many people are converging on
this very ability.) Not perhaps to write Pascal in ruby (though who
knows?), but I have seen SQL, Postscript, and Forth (for a control
system) integrated with ruby. Plus little "built to suit languages"
that were invented on the spot. In every case, it was The Right Thing
To Do (tm) and made what would otherwise have been a difficult problem
much easier to write, to understand, and to maintain.

It depends on the context and the usage. I recall a shop (not mine, a friend
worked there) where management mandated that C would be used henceforth. But
these were diehard BASIC programmers. What they did was fulfill the minimum
requirement of using C by creating a "CBAS" layer ("looks like BASIC, tastes
like C") and mandating that junior programmers write to that layer. Sheer
madness.

But if you're talking about integrating SQL and such in useful, productive
ways, that is different.

> You aren't seriously

arguing that people using ruby in some way that you don't like is going
to "undermine ruby" are you?

What I like is ultimately irrelevant. I admit that "good code" and "bad code"
are subjective terms; but we all use those terms, do we not? I'm saying it is
theoretically possible that someday the amount of bad code in Ruby could exceed
the amount of good code. That, in my opinion, would undermine Ruby.

     And, as an aside, if you aren't wanting to start a political
discussion it's probably best not to compare the person you are writing
to to a terrorist. Just a thought.

I really truly never intended any such comparison. Please accept my apologies
for my poor phrasing.

I stand by the abstraction: A sufficiently open system can be turned against
itself to undermine that openness.

There are millions of ways to concretize that abstraction, but most of those
are otherwise unrelated to each other, and they range from the momentous to
the inconsequential. I have no reason and no desire to compare you to a terrorist
or any other form of criminal.

If you don't believe there is such a thing as "too much flexibility," then we
will have to agree to disagree.

Cheers,
Hal

Randy W. Sims wrote:

Charles Hixson wrote:

> .< 1 + 3, 5 * 2, 6 / 3 >. .<n21, n22, n23>. .<n31, n32, n33>. | .*. M

A perfect example of why free-form-operators are a bad idea. :wink:

No offense intended. It's just that custom notations are not obvious to readers/maintainers of the code. Also, adding such flexibility to the parser means it is probably less capable of recognizing and diagnosing errors. Then there is the problem of clashes when multiple extensions try to define the same ops for entirely different operations.

Regards,
Randy.

And your proposed method of representing a matrix is??
I don't find:

M.backCross([[1 + 3, 5 * 2, 6 / 3 ], [n21, n22, n23], [n31, n32, n33] ] )

to be very intelligible, even if I wrote it. Do remember that matrix multiplication isn't commutative, so the order is very significant. The list ISN'T a matrix. It's a double list. Quite a different beast. One can't make the same assumptions about it's organization, contents, etc. And one doesn't want to define a matrix mulitplication on a list, without being certain that it's a matrix.

I suppose one could do
Matrix([[1 + 3, 5 * 2, 6 / 3 ], [n21, n22, n23], [n31, n32, n33] ] ).cross(M)
which is a bit better, but not very good. (It couldn't really be the Matrix class. That name is already taken, and doesn't act the way I want. I use it because it's intelligible with minimal explanation.)

Specialized areas create specialized representations for very good reasons. That you don't want to use them doesn't make them bad representation, it means that you don't work in that area. Logicians worked a long time developing good representation for symbolic logic. They still don't have good translations into programming languages, even though programming is an outgrowth of the same field. Not being able to create representations for specialized forms cripples the development of a field. That some bad representations will be created along the way is, unfortunately, inevitable. It doesn't mean that allowing the expression is bad, merely that developing good expressions is difficult.

Consider the number of flawed programs that are written. Extending your argument only slightly would argue against allowing any programming languages to exist.

In article <4166FD1B.2020604@thepierianspring.org>,

···

Randy W. Sims <ml-ruby@thepierianspring.org> wrote:

Charles Hixson wrote:

> .< 1 + 3, 5 * 2, 6 / 3 >. .<n21, n22, n23>. .<n31, n32, n33>. | .*. M

A perfect example of why free-form-operators are a bad idea. :wink:

No offense intended. It's just that custom notations are not obvious to
readers/maintainers of the code. Also, adding such flexibility to the
parser means it is probably less capable of recognizing and diagnosing
errors. Then there is the problem of clashes when multiple extensions
try to define the same ops for entirely different operations.

I think this patch is quite cool and I even have immediate applications
for it (the much discussed ':=' operator)... However, I have the same
concern mentioned above. It seems that it could make it more difficult
to detect some syntax errors. Couldn't it also lead to some parsing
ambiguities?

Phil

Charles Hixson said:
> This is one place that I don't think Eiffel got things quite right.
> Precedence should be defineable, not necessarily higher than all
> built-in operators. If one is defining a cross-product, e.g., one
> doesn't necessarily want it to be of higher precedence than whatever one
> is using to define the literal representation of the matrix. And
> ordinary arithmetic might be of even higher precedence. E.G.:
>
> > .< 1 + 3, 5 * 2, 6 / 3 >. .<n21, n22, n23>. .<n31, n32, n33>. | .*. M

Hmmmm ... I'm not sure that the .<, >. and | are technically operators
(certainly not binary operators). They seem to be merely syntactical
markers.

     You could do it, but it would be kludgey unless you generalized it
properly (i.e. take the people who designed smalltalk and the people
behind postscript out for a beer and take notes). The basic trick:
define a class that is a "partial structure" and is the result (and
consumer) of the individual expressions.
     But without doing gymnastics, you're right.

The problem with definable precedence is that precedence is a compile time
operation and the selection of the operator implementation is a run time
thing. Consider ...

   x @a y @b z

(note: Syntax is Eiffel style syntax, so @a and @b are operators. Ignore
for the moment that this conflicts with Ruby syntax for instance variables
and go with me here).

Should this be parsed ((x @a y) @b z) or (x @a (y @b z))? Operators are
generally transformed into method calls, e.g. (x @a y) => (x.@a(y)). So
we look at the runtime class of x to find the operator and determine the
precedence. Unfortunately, at the time the expression is compiled the
runtime class of x isn't available! Indeed, x may have a different class
every time the expression is executed.

So, that leaves us two choices: (1) Reparse the expression everytime it is
executed, or (2) globally define the precedence of an operator across all
classes.

(1) seems a bit too dynamic for my taste, and (2) is troublesome when you
have more than one class defining the operator.

     This is a very good description of why I'm unsure about letting the
user set the precedence/associativity/arity. Do you mind if I use it?

     The best answer I have come up with so far, is to require that if
they're compile-time properties are changed they must be declared before
their first use, and that any additional declaration must match.
Declarations of this sort are not commonly done in ruby (but they are
not unheard of either).

Given that, I wouldn't mind user defined operators in Ruby under the
following conditions...

(A) The operators are visually distinctive. In Eiffel, all user defined
operators must begin with a limited set of symbols (@, #, &, and | IIRC).
After the initial symbol, any printable, non-space character is allowed.
So @in, @cross, &and, #..# are all recognized as operators according to
the Eiffel rules.

     I'm being a bit more conservative at this point: only characters
that are already found in ruby operators (and only on combinations that
are not already used) may be user defined.

(B) Fixed precedence. User defined unary operators should have the same
precedence as other unary operators. User defined Binary operators should
be the same as the highest precedence binary operator under the unary
operators.

     Why the highest? I know that's how eiffel does it, but I don't
recall the rational. I've also considered some function of the length
or contents (such that the built in operators would "fit" the scheme),
but I haven't found anything I like.

Point A means that I don't have to parse a random string of symbols in my
head and decide whether it is legal Ruby syntax or user defined operators
(or Beetle Baily swearing). Ruby's problem is that all the punctuation
characters are already used for other purposes, it would be difficult to
set aside yet another character for this purpose. Perhaps something like
@op@ can be used.

     I think "duck typing" on character classes does the job nicely. If
it looks like an operator (e.g., like => <-+ +/- !~~, etc. it is
composed of (and only of) the characters used in ruby to construct
operators and noting else) it is an operator.

Regarding the matrix example, I find it less than compiling, especially
when existing Ruby can be used to get something quite readable ...

   Matrix [
     [ 1 + 3, 5 * 2, 6 / 3 ],
     [ n21, n22, n23 ],
     [ n31, n32, n33 ]
   ].cross M

     I agree, though I think the initial point was about the value of
being able to experiment to find a comfortable notation, and not so much
that the example provided was the best one.

-- Markus

···

On Fri, 2004-10-08 at 15:39, Jim Weirich wrote:

Markus ha scritto:

This is just my opinion, so don't take it the wrong way. And don't stop your
experimentation. :wink:

     Oh, no worries. There's no risk of that.

I believe that a language should provide "all the power you need" but "not
too much more than you need." This is admittedly highly subjective.

     The problem is, what if I want more power than you do? And what if
Angilena Mathmatica or Bob Business wants something that neither of us
do? I'd say that the language should provide enough flexibility for
everyone, so long as it's not required that anyone use it who doesn't
want it.

the problem I can see is: +,*,- have a ,more or less obvious semantic. You can expect them to be implemented to be similar things in diffenret domains.
The problem is: given that -> is not a standard operator, what could happen if Angelina and Joe Automator implement themselve it for different things?

I mean, one could intend it as a function definition operator, while the other could use it to indicate movements of an hunter in the usual wumpus labyrinth. then their two library would be completely incompatible.

Maybe we could be happy if standard operators such as
+= or != could be overriden, and everything could become prefix.
  I guess this could be enough power.

···

On Fri, 2004-10-08 at 12:43, Hal Fulton wrote:

* Markus <markus@reality.com> [Oct 09, 2004 14:02]:

    Ah, but that would be great! (And many people are converging on
this very ability.) Not perhaps to write Pascal in ruby (though who
knows?), but I have seen SQL, Postscript, and Forth (for a control
system) integrated with ruby. Plus little "built to suit languages"
that were invented on the spot. In every case, it was The Right Thing
To Do (tm) and made what would otherwise have been a difficult problem
much easier to write, to understand, and to maintain.

Precisely. This is great for domain specific languages,
  nikolai

···

--
::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::
::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::
::: page: www.pcppopper.org :: fun atm: gf,lps,ruby,lisp,war3 :::
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Hal Fulton wrote:

...I stand by the abstraction: A sufficiently open system can be turned against
itself to undermine that openness.

There are millions of ways to concretize that abstraction, but most of those
are otherwise unrelated to each other, and they range from the momentous to
the inconsequential. I have no reason and no desire to compare you to a terrorist
or any other form of criminal.

If you don't believe there is such a thing as "too much flexibility," then we
will have to agree to disagree.

Cheers,
Hal

OK. I will counter with the assertion that any system which centralizes power will find the power turned to the benefit of those occupying the positions of power, irrespective of the reasons for which the power was centralized.

Ruby should be and remain open.

I don't think so. My policy is: if it could be ambiguous, warn and
interpret it as the old parser would have (break no code). In general,
it is no more confusing to the parser than the existence of reserved
words and identifiers, both made out of lower-case letters.

     -- Markus

···

On Fri, 2004-10-08 at 17:24, Phil Tomson wrote:

I think this patch is quite cool and I even have immediate applications
for it (the much discussed ':=' operator)... However, I have the same
concern mentioned above. It seems that it could make it more difficult
to detect some syntax errors. Couldn't it also lead to some parsing
ambiguities?

Just a thought. Since you are already using only character already used in
Ruby operators (which I think is good idea) then you may also fix the
precedence according to those. You would just need to come up with good set
of rules. For example, where R means one or more other op-chars:

  Ruby (high to low) User defined examples with same precedence
  ** R** **R R**R (contains ** goes right to top)
  ! ~ + - all unary operators (can we do those 'def @++' ?)
  * / % *R /R %R
  + - +R -R
  & &R
  ^ | ^R |R
  < > <R R>
  = =R R=R (equals on end illegal)

It may have to be a bit more complex then that but you get the idea. Like I
said, just a thought.

T.

···

On Friday 08 October 2004 11:12 pm, Markus wrote:

This is a very good description of why I'm unsure about letting the
user set the precedence/associativity/arity. Do you mind if I use it?

 The best answer I have come up with so far, is to require that if

they're compile-time properties are changed they must be declared before
their first use, and that any additional declaration must match.
Declarations of this sort are not commonly done in ruby (but they are
not unheard of either).

Markus wrote:

     This is a very good description of why I'm unsure about letting the
user set the precedence/associativity/arity. Do you mind if I use it?

Please do!

I'm being a bit more conservative at this point: only characters
that are already found in ruby operators (and only on combinations that
are not already used) may be user defined.

Hmmm ... I felt my position was the conservative one :slight_smile: I think yours will be quite hard on the programmer.

Quick, without looking ahead ... which of the following operators can appear in valid ruby code today ...

     (A) <-+
     (B) +/-
     (C) !~~
     (D) ++

I'll comment on something else (to provide spoiler prevention :slight_smile:

[...] User defined Binary operators should
be the same as the highest precedence binary operator under the unary
operators.

Why the highest? I know that's how eiffel does it, but I don't
recall the rational. I've also considered some function of the length
or contents (such that the built in operators would "fit" the scheme),
but I haven't found anything I like.

I'm not strongly tied to it being the highest. Whatever it is, it should be easy to remember. I don't want to have to remember 35 levels of operator precedence (I can go back to C++ if I want that).

So highest seems like an easy to remember option. If you have another easy to remember scheme, I would be open to it.

Now back to the legal operators ...

(A) is legal, e.g. 2<-+1 => false
(B) is illegal, e.g. 2+/-1 => illegal, however, 2/-1 is legal
(C) is illegal (but I'm not sure why)
      ! ~~1 is legal, but !~~1 gives strange results
      try: ruby -e '!~~1' and see for yourself.
(D) is legal, e.g. ++1 => 1

Anyways, I'm not sure it will be immediately obvious to the casual observer that +/- is a user defined operator and ++ and <+- are concatenations of existing legal Ruby built in operators. (Or that !~~ looks like a concatentation of built in operators, but for some reason is not).

···

--
-- Jim Weirich jim@weirichhouse.org http://onestepback.org
-----------------------------------------------------------------
"Beware of bugs in the above code; I have only proved it correct,
not tried it." -- Donald Knuth (in a memo to Peter van Emde Boas)

Phil Tomson wrote:

...
I think this patch is quite cool and I even have immediate applications for it (the much discussed ':=' operator)... However, I have the same concern mentioned above. It seems that it could make it more difficult to detect some syntax errors. Couldn't it also lead to some parsing ambiguities?

Phil

Perhaps one could require that the user defined operators be delimited by whitespace? In that way no ambiguities could be introduced.

* gabriele renzi <rff_rff@remove-yahoo.it> [Oct 09, 2004 14:05]:

the problem I can see is: +,*,- have a ,more or less obvious semantic.

Yet "a" + "b" != "b" + "a".

The problem is: given that -> is not a standard operator, what could
happen if Angelina and Joe Automator implement themselve it for
different things?

That's basically saying that since the method implies? isn't a standard
method, what could happen if Angelina and Joe Automator implement it for
different things.

Maybe we could be happy if standard operators such as
+= or != could be overriden, and everything could become prefix.

+= is given by +, so that's no problem.
  nikolai

···

--
::: name: Nikolai Weibull :: aliases: pcp / lone-star / aka :::
::: born: Chicago, IL USA :: loc atm: Gothenburg, Sweden :::
::: page: www.pcppopper.org :: fun atm: gf,lps,ruby,lisp,war3 :::
main(){printf(&linux["\021%six\012\0"],(linux)["have"]+"fun"-97);}

Hi --

I stand by the abstraction: A sufficiently open system can be turned against
itself to undermine that openness.

There are millions of ways to concretize that abstraction, but most of those
are otherwise unrelated to each other, and they range from the momentous to
the inconsequential. I have no reason and no desire to compare you to a terrorist
or any other form of criminal.

If you don't believe there is such a thing as "too much flexibility," then we
will have to agree to disagree.

Just so Hal doesn't feel all alone, I'll put in a note of skepticism
:slight_smile: I'm not eager for Ruby to have, in essence, no fixed syntax. I
think Ruby's strength lies largely in its specificity as a language --
a language that is good at domain-specific things, but still a
particular language -- and if it were turned into a kind of
proto-language, I would feel a sense of loss. Also, I don't want to
have to learn new syntactic rules every time I want to read a program
or use a library.

I know the argument gets made a lot that it can't hurt to have this
feature, that feature, etc., because no one has to use them. I think
that misses the point, though. It's like saying: a flute should have
strings like a violin, in case someone wants it to be a violin. What
you end up with, eventually, is not a musical instrument but a kind of
buffet of characteristics, adding up to nothing. I consider Ruby not
only an instrument, but a work of art, like a flute or violin.

The idea of something being treated as either a flute or a violin
sounds like duck typing :slight_smile: What I'm saying, in those terms, is that
I don't consider Ruby itself to be a Ruby object. It's
interesting.... I've thought for a long time that the flexibility and
dynamism of Ruby objects sometimes rubs off on people's views of the
language itself, so that the perception, expectation, or desire is for
Ruby itself to be untyped, open, malleable, and so forth. (Or is that
'mallardeable'? :slight_smile: I tend to think of Ruby, instead, as a quite
stable and distinctive thing whose stability supports the dynamism of
the objects.

But at that level it's fine to agree to disagree; there is of course
nothing whatsoever wrong with experimentation. I guess my more
concrete fear -- and I tend to feel this way about all interpreter
patches -- is that people will start releasing programs that depend on
the patch. At that point, it would be better to do an outright fork
of Ruby. But hopefully that won't be an issue. Mainly I just tend to
agree with Hal that this particular change affects the whole profile
and identity of the language.

David

···

On Sat, 9 Oct 2004, Hal Fulton wrote:

--
David A. Black
dblack@wobblini.net

By exactly the same argument, we could claim that users should not
be able to define their own identifiers. What if I think 'web' has
something to do with fishing, while you think it has something to do
with printing. And who knows, maybe somebody else has a third
definition. Think of the chaos.

    Remember, operators aren't defined in a vacuum, nor are they
global. They are defined as messages send to objects, just like
methods.

     -- Markus

···

> On Fri, 2004-10-08 at 12:43, Hal Fulton wrote:
>>I believe that a language should provide "all the power you need" but "not
>>too much more than you need." This is admittedly highly subjective.
>
>
Markus ha scritto:
> The problem is, what if I want more power than you do? And what if
> Angilena Mathmatica or Bob Business wants something that neither of us
> do? I'd say that the language should provide enough flexibility for
> everyone, so long as it's not required that anyone use it who doesn't
> want it.

On Sat, 2004-10-09 at 01:04, gabriele renzi wrote:

the problem I can see is: +,*,- have a ,more or less obvious semantic.
You can expect them to be implemented to be similar things in diffenret
domains.

The problem is: given that -> is not a standard operator, what could
happen if Angelina and Joe Automator implement themselve it for
different things?

I mean, one could intend it as a function definition operator, while
the other could use it to indicate movements of an hunter in the usual
wumpus labyrinth. then their two library would be completely incompatible.

gabriele renzi wrote:

Markus ha scritto:

This is just my opinion, so don't take it the wrong way. And don't stop your
experimentation. :wink:

...

the problem I can see is: +,*,- have a ,more or less obvious semantic. You can expect them to be implemented to be similar things in diffenret domains.
The problem is: given that -> is not a standard operator, what could happen if Angelina and Joe Automator implement themselve it for different things?

I mean, one could intend it as a function definition operator, while the other could use it to indicate movements of an hunter in the usual wumpus labyrinth. then their two library would be completely incompatible.

Maybe we could be happy if standard operators such as
+= or != could be overriden, and everything could become prefix.
I guess this could be enough power.

This is a real problem. Mutual dialects can diverge sufficiently to be mutually unintelligible. BUT that won't happen to any significant degree unless each one is sufficiently useful in some problem domain area. It's already possible to write unintelligible code in Ruby. (Certainly to write code that *I* can't understand.) This doesn't mean that I feel that certain features which some people find very powerful and valuable should be removed from the language. It means that I haven't yet bothered to learn how to use that part of the language.

Similarly, if user defineable operators become a part of the language, nobody will be required to use them. And presumably people usually WON'T use them. They'll only be (commonly) used where their use improves the code. There will, of course, be experiments by J. Random Hacker, but so what? If it doesn't do anything important, it will be forgotten. If it does, then those who find it important will learn how to use that feature. And if someone wants to use two mutually incompatible dialects, then they will need to come up with a way to harmonize them. Exactly as is done with libraries of functions.

Every objection that I've heard to user defined operators would apply with equal vigor to user defined functions, if the language didn't already include them.

OTOH, if the argument is made that these techniques should be implemented as libraries that one needs to require... that has a lot of validity. They should only be included in the core language if that would significantly improve the core itself. The only other argument for including them in the core is if they can't be done any other way, and in that case it would probably be better for there to be an experimental fork of the code that included them. (Undesireable, but better that including experimental features in the core.)

It shouldn't, and doesn't have to be, an all or nothing kind of thing. It should be a"Use however much you want, and don't complain bitterly if you cut your finger on the bleeding edge. You were warned." kind of thing. Naturally exotic features will have less support. If they were in common use, they wouldn't be exotic. And there should be a path into learning Ruby that's no steeper than the current path. Currently one can learn enough to start being productive in a couple of hours. And one can study for years, and still encounter new things. This is an important characteristic!

···

On Fri, 2004-10-08 at 12:43, Hal Fulton wrote:

That was my "doodle in meeting" project for a few days last week.
I didn't come up with anything I liked. For example, what do you do
with something that comprises two or more extant operators? How do you
decide which part is the R and which is not-R? How do you find the
buddha-nature of a missmatched pair of socks? And what if there is a
chance congruence hidden in an operator that the users don't see?

     I'll add you suggestions to my notes, but I'm not optimistic about
that path.

   -- Markus

···

On Fri, 2004-10-08 at 20:32, trans. (T. Onoma) wrote:

On Friday 08 October 2004 11:12 pm, Markus wrote:
> This is a very good description of why I'm unsure about letting the
> user set the precedence/associativity/arity. Do you mind if I use it?
>
> The best answer I have come up with so far, is to require that if
> they're compile-time properties are changed they must be declared before
> their first use, and that any additional declaration must match.
> Declarations of this sort are not commonly done in ruby (but they are
> not unheard of either).

Just a thought. Since you are already using only character already used in
Ruby operators (which I think is good idea) then you may also fix the
precedence according to those. You would just need to come up with good set
of rules. For example, where R means one or more other op-chars:

  Ruby (high to low) User defined examples with same precedence
  ** R** **R R**R (contains ** goes right to top)
  ! ~ + - all unary operators (can we do those 'def @++' ?)
  * / % *R /R %R
  + - +R -R
  & &R
  ^ | ^R |R
  < > <R R>
  = =R R=R (equals on end illegal)

It may have to be a bit more complex then that but you get the idea. Like I
said, just a thought.