[E-Lang] Hydro & E operator expansions
Ka-Ping Yee
ping@lfw.org
Wed, 21 Mar 2001 16:17:37 -0800 (PST)
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.
> 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!
> > "+" 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 "+".
> 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?
> 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.
This is what it does in Python, and people don't complain that it's
too hard to format strings. There are other facilities for formatting
strings that are much more powerful, and moreover, they make the
conversion explicit. Besides, compared to
print "City: " + name + ", Location: " + north + " deg N, " + east + " deg E"
it's just much more *pleasant* to write:
print "City: %s, Location: %.1f deg N, %.1f deg E" % (name, north, east)
The former dissolves into a haze of quotation marks and plus signs
for me, and requires that i count whether there are an even or odd
number of quotation marks on the left to tell whether a given part
of the line is a literal or an expression. In the latter, there is
just one string, the template.
It seems i lost that argument a long time ago. (But since i also
"lost" an argument to get rid of "define" in favour of "def" and
abolish the VB syntax a long time ago, and the winds seem to have
changed on those, i figured it might not hurt to mention it again.)
> Forcing the temporary construction of a single
> element collection just to satisfy your mathematical sense of purity
> is nuts.
That's not what i'm suggesting at all. Inserting a single element
into a collection is simply not addition, however you cut it. You
can *express* it as the addition of a temporary collection containing
one element, but that's pretty unusual.
> ? [ 1, 2 ] + 3
> # [ 1, 2, 3 ]
And how do you prepend an element? Or insert one in the middle?
Why bless *appending* in particular with an operator?
> > [1, 2] + [3, 4]
>
> ? [ 1, 2 ] + [ 3, 4 ]
> # [ 1, 2, [ 3, 4 ] ]
The thing i said about closure up above explains why i find this
horrible.
> 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.
> 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?
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 (?!?).
-- ?!ng
Happiness comes more from loving than being loved; and often when our
affection seems wounded it is is only our vanity bleeding. To love, and
to be hurt often, and to love again--this is the brave and happy life.
-- J. E. Buchrose