Matlab vs Python (was RE: Discussion: Introducing new operators for matrix computation)
John Lull
lull at acm.org
Thu Jul 20 01:22:06 EDT 2000
Huaiyu Zhu wrote (with possible deletions):
> I really like this kind of ideas. Anyone able to implement it?
It should be near-trivial to implement as part of the core. If I
thought we reach some sort of consensus it was the "right" way to do
it, I'd love to try. So far, I don't see such a consensus developing.
> What it
> takes to change a patch of grammar to an importable module?
This, I suspect, is pretty difficult.
> Maybe the way to do it is to change the python implementation of operator
> into an object oriented approach? Similar to PyObject we'll have a
> PyOperator which defines the symbol, name, scoping and precedence rules.
> This way handling operators within python would be similar to hadling
> ordinary objects, by import NewOperator. To discourage abuses there may be
> restrictions on what is allowed as symbols and what precedence rules are
> allowed and so forth, and perhaps prohibit dynamic changes within an
> importing module.
(Note -- I haven't looked at the Python internals. The following is
based on my experience using the language, & reading about it. If
I've misunderstood something here, please feel free to correct me.)
The problem I see with it is as follows:
The Python compiler can tell just by lexical analysis what is a
function, what is a standard operator, what is a keyword, what is a
constant, etc. It doesn't need an import statement to know that
a.bizarremethodname(b) is supposed to be translated to a call to
bizarremethodname() on object a.
If you require an import statement for the compiler to distinguish
operators from other language elements, you've just made a truly
fundamental change in the way Python works -- because import
statements get compiled into bytecode, but don't get *executed* until
runtime. By that time the compilation is done, but you want the
import statement to change something that already happened. That
clearly doesn't work.
You could, of course, define a completely different import-like
mechanism, which would be handled at compile time, to deal with these
issues -- but your resulting NewOperator wouldn't be terribly like a
standard Python object.
(In the following, '..newOp..' etc. are just a sample of what *might*
be done. I'm not married to the notation, nor am I suggesting it as
in any way optimum.)
To add operators to the language at run time, you would need to define
them in such a way that the compiler could recognize them as operators
without knowing anything it won't know until runtime. The compiler
would also have to be modified to handle them appropriately.
You could, at least in theory, do something like:
a..newOp..(b..otherOp..c)
and have the compiler translate it into:
a.__newOp__(b.__otherOp__(c))
simply because it could recognize [.][.][a-zA-Z][a-zA-Z0-9]*[.][.] as
the standard definition of a user-defined binary operator. It could
compile the statement correctly without knowing whether object 'a'
even implemented the operator.
With a bit of extra work, you could probably even make the run-time
execute the above as
b.__otherOp__(c).__rnewOp__(a)
if it turned out __newOp__() was not defined for object a, but
__rnewOp__() was defined for the result of b.__otherOp__(c).
What you would lose this way is:
1. Any notion of precedence or associativity for these operators.
Changing the definition to give the compiler this information would
likely leave you with something pretty error prone. You're likely
going to have to provide parentheses in your code anywhere simple
left-to-right evaluation is not appropriate.
2. It's not obvious to me how you could make such operators handle
short-cut evaluation as the standard boolean operators do. Whether
this is important or not, I don't know. Probably not terribly.
3. Frankly, expressions written this way just don't look right to me.
Once you know what .* means, 'a .* b' is just easier to read than
'a ..eMul.. b'.
What you would gain is:
1. An unlimited supply of domain-specific binary operators.
2. Operators can make sense to someone who knows little or nothing
about the domain. He doesn't need a reference to find out what '.*'
means.
3. Operator notation anywhere it's clearer than functional notation.
4. Functional notation anywhere it's clearer than operator notation,
*without* having to write separate operator handlers and functions.
Regards,
John
More information about the Python-list
mailing list