Pass-by-reference : Could a C#-like approach work in Python?

Stephen Horne $$$$$$$$$$$$$$$$$ at $$$$$$$$$$$$$$$$$$$$.co.uk
Thu Sep 11 17:43:11 CEST 2003


On Thu, 11 Sep 2003 13:10:42 GMT, "Steve Holden"
<sholden at holdenweb.com> wrote:

>First of all, if you insist on using an invalid address, might I suggest
>that "x at y.invalid" would be less visually annoying, with the additional
>merit of actually meaning something.

I used to have something like that, only my newreader won't allow a
completely invalid addresss (it insists on seeing '.co.uk' and some
other formatting stuff). It turned out that my obviously invalid
domain was actually valid and owned by someone else. Actually, it was
pointed out to me by someone who disagreed with a point I was making.

Basically, even if a spamtrap domain is actually a real domain by pure
fluke, it will still recieve my spam - as said the lecture.

If dollar signs are valid in a domain name (which I assume they are as
my newsreader allows them) then I can imagine a valid domain
consisting of one, two, three or whatever of them - but not a huge run
of them. That is the reason for my choice. By preference I would miss
that line out of the header completely, but it's not an option.

This first comment of yours raises the suspicion that, in disagreeing
with my idea, you feel you have to attack everything you can about me
and about the idea. Let's see how that suspicion pans out...

>So, if I can summarise. You see a feature in C# that represents perhaps one
>of the less-well-thought-out aspects of the language. You then ask how to
>graft it into Python because "Python should be more like C#"?

Oh dear.

In C#, 'ref' parameters are not IMO a "less-well-thought-out" aspect
of the language. They are, IMO, a very well thought out feature in the
context of that language. Making the 'ref' explicit in the call is
also a novel approach which I don't think I've seen in any other
language, which is why I decided to raise the subject.

On thinking it through, it simply isn't necessary in Python - but that
doesn't mean you have to make it out to be a universally bad idea or
go through the old 'stop trying to turn Python into X' garbage.

Actually I'm sick to death of the old 'your just trying to turn Python
into X' argument whenever I suggest that *maybe* Python might learn a
trick from another language. I have been accused of trying to turn
Python into C, C++, Java, Pascal, Ada and several others in the past.
None of these accusations is true. They are tired and pathetic. They
say more about the accuser than the accused.

Believe it or not, languages other than Python have good features.
Believe it or not, Python has become a better language by adopting
features from other languages AS WELL AS by adopting ideas of its own.

Sometimes a feature that works well in one language can work well in
another.

Python does not need a 'not invented here' mentality.

>> : The rationale for this in C#, I assume, is mostly about clarity and
>> : maintainability - the caller can't be surprised when value type
>> : parameters are changed in a function as he had to explicitly allow it.
>>
>I agree the requirement for the "ref" keyword in the call lends some
>clarity. Not sure I'd agree about maintainability, though.

Maintainability is mostly helped by explicitness. The maintainer can
see that the parameter might be rebound simply by looking at the call.
I can't imagine any scenario where improved clarity doesn't lead to
improved maintainability.

> And it can only
>be a matter of time before people start suggesting that the ref mechanism be
>used because there's a two-hundred nanosecond time saving ...

Garbage. Neither Python nor C# are meant to be execution speed record
holders. I did address a performance issue, but only because (1) that
performance issue was raised by the 'against' side in a previous
discussion of pass-by-reference parameters and (2) there is already
some sensitivity to the idea of Python becoming slower than it already
is (IIRC some people still use Python 1.5 in part because it is a
little faster than Python 2.x).

It would be hard to predict the relative speeds of a this idea against
the tuple-returning method. Each has its own overheads - in one case
creating and unpacking the tuple, in the other case checking that the
right parameters are marked as 'ref' or not. All I can say for sure is
that the performance of conventional function calls would not change.

But then my argument was never about performance. It appears to me
that you invented that issue purely so you could counter it - but
countering an argument that the other side never made is a very weak
victory.

>But given Python's ability to have a function return a tuple to an unpacking
>assignment (which has the real advantage that the intention to modify the
>value of the left-hand tuple elements is explicit) I really can't see why
>you want to complicate things further.

It is possible for a person to propose an idea for discussion without
having though it through fully - that may even be the point of
proposing it for discussion. If discussion could never lead to new
ideas and changed opinions there'd really be no point.

In the context of Python the idea turns out to serve no compelling
purpose. I already admitted that in message ID
cg5vlvgorsi88elsn9ur5ueavpg27d7ui3 at 4ax.com. I was even showing signs
of heading that way when I said...

: C# 'needs' ref parameters because it has no convenient way to return
: multiple values from a function. Python does not. The question is
: really whether this argument about expressing intentions and evading
: errors is compelling or not.

all the way back in message ID
jnkulv8t6e1qc3mb4pmf0k706e98pgmss2 at 4ax.com

You don't have to claim that the feature is "one of the
less-well-thought-out aspects of" C# to do that - C# is not Python.
You also don't need to accuse me of trying to "graft it into Python
because "Python should be more like C#"".

Basically, you don't have to turn this into a crusade just because I
thought an idea from another language might be worth some thought and
discussion. Python is not the one true faith - it is a programming
language. Like all good programming languages it has sometimes adopted
good ideas from other programming languages. This idea is not destined
to be one of them, and that's fine - it was a bad idea, but that
doesn't make it a heresy. Discovering whether an idea is bad is one of
the advantages of discussion.


>"Explicit is better than implicit".

This has nothing to do with it - the 'ref' notation *is* explicit.


>> >  Currently, if you see a call to f(x) you know
>> >that x cannot be rebound.
>>
>> And if in some future version of Python the suggestion I made was
>> implemented, when you see f(x) you will still know that x cannot be
>> rebound - but when you see f(ref x) you will know that x may well be
>> rebound.
>>
>OK, remind me why this is better than
>
>x = Inc(x)
>
>or
>
>x, y = DoubleInc(x, y)

The idea I had in mind is that sometimes it is a good thing to
restrict what the caller can do in order to prevent errors. The
return-value method may hypothetically, in some cases, allow excessive
flexibility. If the intention of the function is to replace a value
then literally doing that in the function itself - rather than leaving
it the the caller to decide whether to replace it or whether to keep
both - may be a good idea.

At present Python allows this if the value is a component of a mutable
object passed in as a paramater, but not if the value was passed in
directly as the parameter itself.

As it turns out, I can't think of a compelling example where this idea
would be beneficial and that logic above almost certainly doesn't
connect to the practicalities of real world programming - I've already
said that - but it wasn't immediately obvious that it would work out
like that when I started the thread.

>> I wouldn't want this. To implement it, either a single compiled
>> version of a function would need to figure out at run time whether the
>> parameters where by reference or not, or several versions of each
>> function would have to be compiled into the .pyc file.
>>
>> Also, I don't really see the benefit. If a function has by-reference
>> parameters then rebinding those parameters is likely a big part of the
>> purpose of the function. Supplying a parameter which cannot be rebound
>> is likely an error caused by someone forgetting to type the 'ref', in
>> which case they'd equally likely appreciate an error message as
>> opposed to wierd, hard-to-trace logic errors.
>>
>So you introduce a "ref" keyword so that a dangerous and unneccessary
>mechanism can be "safely" introduced?

Not at all.

The dangerous thing in JCMs example is the overloading, not the
call-by-reference.

Pass-by-reference parameters are not dangerous. Making the
pass-by-reference explicit in the call is also not dangerous.

I am a little suspicious of the C# system of using 'ref' and 'out' to
resolve overloading, but Python doesn't do overloading at all. That
doesn't mean overloading has to be a bad idea and neither does it mean
that Python is a bad language. Like any language feature overloading
has a good and a bad side to it, and like any good language Pythons
features are selected to work well in the context of the language as a
whole. Different languages simply have different strengths and
weaknesses.

But overloading is a separate issue to pass-by-reference - take a look
at standard Pascal for instance, which has pass-by-reference but no
overloading.

Pass-by-reference is unnecessary in Python, yes. The theoretical
argument does not connect to practical reality. But as I already said,
it was not immediately obvious that it would work out that way.





More information about the Python-list mailing list