[E-Lang] Hydro & E operator expansions
Tyler Close
tclose@oilspace.com
Thu, 22 Mar 2001 10:44:26 -0000
Ping wrote:
> On Wed, 21 Mar 2001, Tyler Close wrote:
> > Ping wrote:
> > > No, don't do this, please. "+" means "add". It's not
> just a couple
> > > of line segments.
> >
> > Who said it doesn't mean "add"?
>
> Maybe i misunderstood. It appeared to me that someone had gotten a
> mistaken impression about Python that the names of the operator
> methods were intentionally free of semantics in order to divorce
> the operators themselves (in the language definition) from the
> semantics of the operators (as implemented in the library).
>
> So i thought Mark was suggesting a change from method names like
> "add", "multiply", "run" to method names like "op_plus", "op_star",
> "op_paren". The former is like Python. The latter is like C++.
>
> The former encourages people to use "+" for something like addition,
> "*" for something like multiplication, and so on. The latter
> encourages people to associate random operators with
> whatever methods
> they feel like. I much prefer the Python way.
Just so that I'm clear here, the difference is "__add__" vs "op__add".
I am having trouble reading as much into this difference as you are. I
would only be inclined to use "op__add", or "op__plus", for something
that was understood as addition.
> > I just had a look at "addition"
> > in a couple of dictionaries and the general sense is that
> "addition"
> > is putting two things together to make something bigger.
>
> That's true. Moreover, in most contexts "+" has a sense of closure
> about it. I believe we have already firmly accepted that the
> behaviour of the operator gets defined by the left operand. That
> left operand implies a set over which "+" operates, and one expects
> that set to be closed under addition. That is, given two operands
> of the same type, the result should be of a similar type.
>
> This is why
>
> [1, 2] + [3, 4] = [1, 2, [3, 4]]
>
> looks so terrible to me. I have added two lists of integers and
> gotten a strange creature that is not a list of integers!
Again, this is because of your insistence that "+" is concatenation.
If "+" is "with", then the return type is the original list with
another element, whatever that element may be.
It might be worthwhile to point out that, unlike EMap, Hydro's
containers support dynamic parameterized type checking. So if your
list was constructed as:
def q := [ 1, 2 ] toFIFO(int)
then your strange creature would have caused an
IllegalArgumentException.
> > > "+" should be symmetric with respect to type. The left side
> > > dominates for the purpose of coercion, but otherwise, the types
> > > of the arguments and the result should be the same.
> >
> > You're claiming that mathematical addition of numbers is
> the only type
> > of addition and that all other types should be coerced into this
> > definition. This is both a narrow definition and a
> dangerous one for a
> > programming language.
>
> No, it's not quite as hard-line as that. What i'm proposing is
> that there should be an understood set of constraints on what the
> operators do. One of these expectations is that, when i add two
> objects of the same kind, the result is something of a similar kind.
>
> Now "same kind" is obviously a fuzzy concept in a dynamically-typed
> language without parameterized types or type inference. But making
> the operators behave predictably is a worthwhile goal. It's the
> same reason why i advocate semantic names for operator methods. We
> have to be careful with operators in *particular* because they
> aren't given meaningful names when they're used.
>
> I am not arguing in favour of automatic coercion, as you'll
> see below.
> I am only arguing against the abuse of "+".
I seem to be alone on this, so I may be wrong, but you haven't
convinced me that I'm abusing the "+" operator. Given your looser
constraint of "similar kind", I'm actually proposing a much stricter
semantics.
> > Consider the company "ABC Attorneys at Law Inc.". The
> partners in this
> > firm are Adams, Babcock and Cunningham. Every time a new lawyer is
> > made a partner, she gets to add her initial to the company's
> > letterhead. This is done by giving the new partner a "once-only"
> > object for adding a single character to the sequence of
> initials in
> > the company letterhead.
> >
> > to addInitial(initial) {
> > ... # Destroy this object.
> > initials += initial
> > ...
> > }
> >
> > Your coercion would let the new partner add as many
> initials to the
> > letterhead as she chose to. Moreover, with your syntax, it is
> > impossible to protect against this threat without using guard
> > statements (:char), or similar fuss. Your message protocol, on its
> > own, has an unplugable security hole.
>
> What on earth do you mean? Of course you want to assert that the
> type of initial is a single character. What's the problem?
The problem is that you have to make this assertion because of the way
the message protocol is defined. If "+" was "append a single
character", and "|" was "concatenate this string", then there would be
no need for external checks. The need for external checks stems
directly from the automatic coercion of a character to a string. The
message protocol does not provide a way to express "append a single
character".
Again, I don't want to try to argue against using "+" for string
concatenation, since I have the distinct feeling of overwhelming odds
against me. The point that I want to make is that extending this
behaviour to collections is a poor decision.
> > To concatenate two queues, you use the concatenation operator.
> >
> > ? [ 1, 2 ] | [ 3, 4 ]
> > # [ 1, 2, 3, 4 ]
>
> > Try using E's "|" operator with an EMap. "|" is concatenation.
>
> Not really. Using "|" on maps overlays the maps (or computes the
> union of two sets). Union is not the same as concatenation.
For a deterministic map, union is the same as concatenation. If it's a
unique map, then duplicates are removed, but the operation is still
the joining of the two collections. It's concatenation in the only way
a map knows how.
Tell me what the difference is between "+" and "|" on a map, if "+" is
concatenation.
> And how do you prepend an element? Or insert one in the middle?
> Why bless *appending* in particular with an operator?
Most collections have very specific behaviour for where an element
will be inserted. You never insert into the middle of a stack.
> > Mostly, I just want people to realize that in generalizing
> > from "a string is a collection of characters" to a
> collection model,
> > addition means:
> >
> > composite := composite + component
> >
> > and
> >
> > component := component + component
> >
> > is just a special case that is true for numbers, where a composite
> > automatically collapses to a component.
>
> Right. So consider:
>
> [1, 2, 3] + [4, 5]
>
> [1, [2, 3]] + [[4, 5]]
>
> What's the composite? What's the component?
The definition of composite and component are decided by the left hand
side operand. For a collection, it is the composite and its direct
elements are components.
> How about this: suppose x is [1, 2, 3] and y is [4, 5, 6].
> Suppose a is "abc" and b is "def".
>
> Now a, b, x, y all have length 3. But the length of a + b is 6
> while the length of x + y is 4 (?!?).
This is again because of your use of "+" for concatenation.
> > Setting the precedent that it
> > is OK to do automatic coercions between very different types is a
> > really bad idea.
> [...]
> > Automatically coercing a component to a composite also
> goes a little
> > outside the semantics of the message passing
> architecture. If "+" is
> > string concatenation, then the string implementation of the "+"
> > operator should expect a single string type parameter.
>
> I totally agree with you.
>
> You may recall that, way back when i was first learning E, i argued
> against such automatic conversion. In my opinion, "" + 5 should
> raise a type mismatch exception.
No, I didn't recall, but it seems likely. You always seem able to
think faster than me.
The other nice thing about having it raise a type mismatch expression
is that it encourages the development of I18N code. "" + 5 is
definitely an english-centric construct.
Maybe the `` quotes are default "en-US" and all the other RFC1766 tags
are reserved for their respective locale specific translators. This
means that:
def balance := 6
fr`Vous avez $balance francs.`
results in:
"Vous avez six francs."
Tyler