Verbose and flexible args and kwargs syntax

Steven D'Aprano steve+comp.lang.python at pearwood.info
Tue Dec 13 06:13:16 EST 2011


On Tue, 13 Dec 2011 01:15:46 -0800, Eelco wrote:

> On Dec 13, 3:43 am, Steven D'Aprano <steve
> +comp.lang.pyt... at pearwood.info> wrote:
>> On Mon, 12 Dec 2011 04:21:15 -0800, Eelco wrote:
>> >> No more, or less, explicit than the difference between "==" and
>> >> "is".
>>
>> > == may be taken to mean identity comparison; 'equals' can only mean
>> > one thing.
[...]
> We are not talking mathemathics, we are talking programming languages.

What *I* am talking about is your assertion that there is only one 
possible meaning for "equals" in the context of a programing language. 
This is *simply not correct*.

You don't have to believe me, just look at the facts. It's hard to find 
languages that use the word "equals" (or very close to it) rather than 
equals signs, but here are four languages which do:

(1) OpenXION:

Equals in OpenXION is weakly typed, like Perl:

>1 + 1.0 equals "2"
true


(2) C# uses method notation: a.Equals(b) can be overridden, but for many 
types it defaults to value equality, that is, the equivalent to Python's 
a == b.

(3) Ruby uses a.equal?(b) for "reference equality", that is, the 
equivalent of Python's "is" operator:

irb(main):001:0> a = "abc"
=> "abc"
irb(main):002:0> b = "abc"
=> "abc"
irb(main):003:0> a.equal?(b)
=> false
irb(main):004:0> a == b
=> true


(4) Mathematica's Equal[x, y] can test values and expressions for 
equality. It may return true, false, or unevaluated (i.e. itself).


Four languages that use Equals (or close to it) with four different 
behaviours.



> Identity versus value equality is a well established concept within its
> jargon. Within this context, 'equals' and 'is' have clearly defined
> meanings. 

Incorrect. Most programming languages do not even have a concept of 
identity: identity is only(?) relevant to reference languages, like 
Python, where variables are references to objects.

Even for languages that have a concept of identity, most don't don't call 
it "is". Objective-C calls it "==", PHP calls it "===", C# calls it 
object.ReferenceEquals. (Python, Algol 68, and VB .NET are three which do 
call it "is".)

For stack-based languages like Forth, it doesn't even make sense to talk 
about identity, since values aren't variables: they're just values on a 
stack, not values in a fixed location, or bound to a known name.

Again, all this goes to demonstrate that the language designer is free to 
choose any behaviour they like, and give it any name they like.


[...]
> So 'frequency of use' is no valid interpretation of 'obscurity'? Im not
> a native speaker, but im pretty sure it is.

No. Things which are obscure are used in language infrequently, because 
if they were common they would not be obscure. But things which are used 
infrequently are not necessarily obscure.

An example in common language: "Napoleon Bonaparte" does not come up in 
conversation very frequently, but he is not an obscure historical figure.

An example from programming: very few people need to use the 
trigonometric functions sin, cos, tan in their code. But they are not 
obscure functions: most people remember them from school. People who have 
forgotten almost everything about mathematics except basic arithmetic 
probably remember sin, cos and tan. But they never use them.



>> >> And you can blame C for the use of % instead of mod or modulo.
>>
>> > I didnt know one of Python's design goals was backwards compatibility
>> > with C.
>>
>> Don't be silly. You know full well Python is not backwards compatible
>> with C, even if they do share some syntactical features.
> 
> Of course I was being silly; I know this use is following a historical
> precedent; but id rather see it rectified in the previous version of
> python rather than the next. My sillyness was prompted by the percieved
> pointlessness of your remark. Of course python is not trying to be
> backwards compatible with C; so why bring it up then?

Because you asked why Python uses the % operator for remainder.


[...]
> They are bad ideas because they truely do not lead to the execution of
> different code, but are merely a reordering, mixing statements in with a
> function declaration. I am proposing no such thing; again, the type(arg)
> notation I have dropped, and never was meant to have anything to do with
> function calling; it is a way of supplying an optional type constraint,
> so in analogy with function annotations, I changed that to arg::type.
> Again, this has nothing to do with calling functions on arguments.

You have not thought about this carefully enough. Consider what happens 
when this code gets called:

def f(*args): pass

f(a, b, c)


The Python virtual machine (interpreter, if you prefer) must take three 
arguments a, b, c and create a tuple from them. This must happen at 
runtime, because the value of the objects is not known at compile time. 
So at some point between f(a, b, c) being called and the body of f being 
entered, a tuple must be created, and the values of a, b, c must be 
collated into a single tuple.

Now extend this reasoning to your proposal:

def f(args:FOO): pass

At runtime, the supplied arguments must be collated into a FOO, whatever 
FOO happens to be. Hence, the function that creates FOO objects must be 
called before the body of f can be entered. This doesn't happen for free. 
Whether you do it manually, or have the Python interpreter do it, it 
still needs to be done.

 
> First off, type constraints must have some use; all those languages cant
> be wrong.

But you're not talking about type constraints. You're not instructing the 
function to reject arguments which have the wrong type, you are 
instructing it to collate multiple arguments into a list (instead of a 
tuple like Python currently does). def f(*args) *constructs* a tuple, it 
doesn't perform a type-check.




-- 
Steven



More information about the Python-list mailing list