def fn(arg1,x=arg2,y=10,*args,**kwargs): GO PYTHON!

def fn(arg1,x=arg2,y=10,*args,**kwargs):

That's kind of ugly, but the design is elegant. With that declaration, the function supports positional arguments, required named arguments, optional arguments, an arbitrary number of additional unnamed arguments, and additional arbitrary named arguments.

It allows function calls to be simpler and more readable than they would be without this flexibility.

In languages without named arguments, people fake it by passing hashes (see Perl, PHP). Likewise, some languages, like C, support arbitrary positional arguments, but most do not or do so inelegantly (Javascript). Many support optional arguments. Some prefer named arguments (VB), but most do not. Strongly typed languages tend to use type signatures to dispatch code (C++, Java, Haskell, etc. etc.) I think Forth-like languages only support fixed numbers of positional args... but the trade off is that these languages are highly deterministic. Likewise Lisp-like languages, except that it appears that they've added parameter flexibility features into the language.

The R language is pretty similar to Python with regard to mixing positional and named parameters.

Named parameters' only "downside" is that you can't do C-style assignments within parameter lists, like this: fn( x=1, y=2 ); z = x + y; and after that executes, z is 3.

IMNSHO, that's a misfeature. It's led to lame conventions like PHP's using assignments to document parameters:fn( $name = 'john' ). That's not a named parameter - it's assigning 'john' to $name, but it won't be used later.

More info here about Python parameter expansion.

And if you really want to think about it, parameter lists in Lisp and Clojure.