Default Value

R

Rotwang

On 21/06/2013 19:26, Rick Johnson wrote:
[...]
I didn't ask what alternative methods of handling default
argument binding exist (I can think of several, but none
of them strikes me as preferable to how Python currently
does it). I asked what would happen in /your/ version of
Python. Which of the alternatives that you present would
have been implemented, if you had designed the language?

The apathetic approach. However, you fail to understand that
whilst Python's current implementation is partly apathetic,
is is also benevolent, and malevolent simultaneously. My
approach is purely apathetic. I'll explain later. Stay
tuned.
OK...

[...]
So how does the interpreter know whether an arbitrary
object passed as a default value is mutable or not? Not
that it really matters.

Well i'm glad it does not matter to you because it does not
matter to me either. *shrugs*
which it does

Am i just to take your word for this? You cannot provide an
example?

Of course I can:
.... def __hash__(self):
.... return hash(tuple(self))
....
x = hashablelist(range(4))
x [0, 1, 2, 3]
# Let's try using x as a dict key:
d = {x: 'Hello'}
d[x] 'Hello'
# Let's try mutating it:
x.append(4)
x
[0, 1, 2, 3, 4]

Here, allow me to "break the ice":

# Literal
py> d = {[1]:2}
Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
d = {[1]:2}
TypeError: unhashable type: 'list'
# Symbol
py> lst = [1]
py> d = {lst:2}
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
d = {lst:2}
TypeError: unhashable type: 'list'

Hmm, maybe only certain mutables work?

Try reading the tracebacks. Notice how they don't say anything about
mutability?

Great, more esoteric
rules! Feel free to enlighten me since i'm not going to
waste one second of my time pursuing the docs just to learn
about ANOTHER unintuitive PyWart i have no use for.

Sure. In order to be used as a dictionary key a Python has to be
hashable. That means its type has to define a __hash__ method, which is
called by the builtin function hash. The __hash__ method should return
an int, and objects that compare equal should have the same hash.

You are correct. Finally, we can agree on something.


(is this lazy readers day? I swear i explained this earlier)

And here is where you are wrong. In the current implementation
python functions carry the state of mutable default arguments
between successive calls. That's a flaw.

But your description of The Apathetic Approach doesn't say anything
about functions carrying the state of mutable default arguments, or
otherwise. How am I supposed to know how your proposed approach treats
mutable defaults if you don't tell me, even after I explicitly ask?

Observe:

py> def foo(arg=[]):
... arg.append(1)
... print(arg)
...
py> foo()
[1]
py> foo()
[1, 1]
py> foo()
[1, 1, 1]

Yes, I am well aware of how Python currently treats mutable default
arguments.

No, no, NO! That's wrong! Subroutines should be stateless.
That means that an empty mutable default argument will
ALWAYS be empty at each call of the subroutine. This is
what should happen:

py> def foo(arg=[]):
... arg.append(1)
... print(arg)
...
py> foo()
[1]
py> foo()
[1]
py> foo()
[1]

Yes, Yes, YES! That is intuitive! That is sane! Now, what if
we pass a reference to a mutable object? What then. Well, let's
see:

py> lst = range(5)
py> lst
[0, 1, 2, 3, 4]
py> def foo(arg=lst):
... arg.append(1)
... print(arg)
...
py> foo()
[0, 1, 2, 3, 4, 1]
py> foo()
[0, 1, 2, 3, 4, 1, 1]

That's fine. Because the object was already created OUTSIDE
the subroutine. So therefore, modifications to the mutable
are not breaking the fundamental of statelessness INSIDE
subroutines. The modification is merely a side effect, and
the subroutine is unconcerned with anything that exists
beyond it's own scope.

IS ALL THIS REGISTERING YET? DO YOU UNDERSTAND?

No, I don't. These two special cases are not sufficient for me to
determine what semantics you are proposing for the general case. For
example, what happens in the second example if lst is rebound? Does the
default stay the same or does it change to the new value of lst? What
about if you pass a call as a default argument, and then subsequently
change the behaviour of the callable? Does the argument get re-evaluated
every time foo() is called, or is the argument guaranteed to be the same
every time? If the latter, what happens if the arguments type is
modified (e.g. by changing one of its class attributes)? What about
defining functions dynamically, with default arguments that are only
known at runtime? Is there any way to avoid the second type of behaviour
in this case? If so, how? If not, isn't that likely to prove at least as
big a gotcha to people who don't know the rules of RickPy as the problem
you're trying to solve?

My buddies? This design flaw is NOT my brain child. Your
barking up the wrong tree pal.

But I didn't ask about Python's current approach, which I already
understand quite well. I was asking about what your approach would be.
If this is not your brainchild then why were you telling me about it?

I explained this to MRAB already.

But you haven't said how you test an object for mutability.

Nice attempt at sleight of hand but your logic is clumsy.

Your trying to argue that my use of a "custom callable state
object" (to avoid the esoteric and unintuitive nature of the
current implementation of Python "mutable function
arguments") is somehow only a mere reproduction of the
function behavior and has no positive benefits, when in
fact, it has a HUGE direct benefit:

* AVOIDING A FLAW IN THE LANGUAGE

But it doesn't avoid a flaw in the language, unless you get rid of
function defaults altogether. As long as functions can have default
arguments, people are going to try passing mutable ones. Avoiding the
alleged "flaw" in the language means proposing a different semantics for
when they do, not just explaining how the current behaviour can be
reproduced in other ways (which nobody AFAICR has denied).

It also has quite a few positive side effects:

* CODE ENCAPSULATION
* INTERFACE
* USING THE CORRECT TOOL FOR THE JOB++
* READABILITY
* NO HIDDEN SURPRISES
* LESS BUGGY

How much more justification do you need?

I don't need more justification, I just need you to tell me
unambiguously what alternative behaviour you're proposing. I can't
really compare the pros and cons of the two approaches if I only know
one of them.

Yes, iterating a sequence can be achieved using a "while
loop", but "for loops" should not be thrown out because they
offer a specific type of iteration that nicely complements a
while loop. Plus, for loops do not have any strange side
effects (unlike Python functions).

They exhaust iterators. Whether that is considered "strange" depends on
who is doing the considering (Python's default binding behaviour doesn't
seem strange to most people who are familiar with its data model).

They do one thing and
they do damn well! So stop picking on for loops :)

I want Python functions to also "do one thing and do it
well", and what is that "one thing" you ask, execute
subprograms.


The fix is simple. No more "magical Python functions", only
stateless routines.

So no generators, then?
 
M

MRAB

I think you're onto something here, but you really haven't gone far
enough. Mutable objects *anywhere* are a problem. The solution?
Abolish mutable objects. Strings (bytes and Unicode), integers,
decimals (floats are a problem to many people), tuples of the above,
and dictionaries mapping any of the above to any other of the above,
should be enough to do everything.
Pure functional languages don't have mutables, or even variables, but
then we're not talking about a pure functional language, we're talking
about Python.
 
C

Chris Angelico

... def __hash__(self):
... return hash(tuple(self))

There's a vulnerability in that definition:
a=hashablelist((1,[],3))
a [1, [], 3]
{a:1}
Traceback (most recent call last):
File "<pyshell#255>", line 1, in <module>
{a:1}
File "<pyshell#249>", line 3, in __hash__
return hash(tuple(self))
TypeError: unhashable type: 'list'

Of course, if you monkey-patch list itself to have this functionality,
or always use hashablelist instead of list, then it will work. But
it's still vulnerable.

ChrisA
 
R

Rotwang

... def __hash__(self):
... return hash(tuple(self))

There's a vulnerability in that definition:
a=hashablelist((1,[],3))
a [1, [], 3]
{a:1}
Traceback (most recent call last):
File "<pyshell#255>", line 1, in <module>
{a:1}
File "<pyshell#249>", line 3, in __hash__
return hash(tuple(self))
TypeError: unhashable type: 'list'

Of course, if you monkey-patch list itself to have this functionality,
or always use hashablelist instead of list, then it will work. But
it's still vulnerable.

Quite right, sorry. I should have called my class
"sometimeshashablelist", or something.
 
R

Rick Johnson

On Friday, June 21, 2013 5:49:51 PM UTC-5, MRAB wrote:
My argument has always been that mutables should not be
passed into subroutines as default arguments because bad
things can happen. [...] I also believe that a programmer
should not be prevented from passing mutable default
arguments [...]
So, having mutables as default arguments is a bad idea,
but a programmer should not be prevented from doing that,
and a warning message should be printed on such occasions.

Well i'll admit that does sound like a contradiction.
Basically i meant, programmers should be *discouraged* from
passing mutables as default arguments but not *prevented*.
Of course, utilizing a stateless subroutine like i suggest,
argument mutability would not matter.

Sometimes when you're passionate about something your
explanations become so verbose as to render your idea lost
in the noise. Obviously i made that mistake here :)

In my last reply to Rotwang i explained the functionality i
seek to achieve in a set of three interactive examples.
Take a look at those and let me know what you think.
They've developed this language, and provided it for free.
They've even released the source code. You perceive flaws
that you say must be fixed, but you're not going to help
to fix them.

Agreed. And i am thankful for everyone's contributions. I
can be a bit harsh sometimes but my intention has always
been to improve Python.
I _do_ want you to help to improve the language, and I
don't care if you don't get it right first time. I didn't
get it right first time when I worked on the regex module
(I think that what I have on PyPI is my _third_ attempt!).

Well thanks for admitting you are not perfect. I know i am
not. We all had to start somewhere and anyone who believes
he knows everything is most assuredly a fool. Learning is
a perpetual process, same for software evolution.
Python isn't perfect, but then no language is perfect.
There will always be compromises, and the need to maintain
backwards compatibility means that we're stuck with some
"mis-features", but I think it's still worth using; I
still much prefer it to other languages.

I understand. We can't break backwards compatibility for
everything, even breaking it for some large flaws could
cause a fatal abandonment of the language by long time
users.

I just don't understand why i get so much hostility when i
present the flaws for discussion. Part of my intention is to
air the flaw, both for new users and old users, but a larger
intention is to discover the validity of my, or others,
possible solutions.

And even if that solution involves a fork, that is not a bad
thing. Creating a new fork and then garnering an acceptance
of the new spinoff would lead to at worse, a waste of time
and a huge learning experience, or at best, an evolution of
the language.

Sorry. I failed to explain that this statement was meant not
directly for you but as a general statement to all members.
Sometimes i feel like my back is against the wall and i'm
fighting several foes at once. That can lead to me getting
defensive.
 
R

rusi

While we're at it, I would like to petition for a function
terminates(f, args) that I can use to determine whether a function
will terminate before I actually call it.

I was going to say something about this -- viz that in prog. languages sometimes things that look laughably easy can turn out HARD.

As a personal example of a time I found myself in Rick's shoes:

I was lecturing to some audience on the glories of FP. Someone asked me how efficient such a language would be. I replied (rather ****-surely) that efficiency is not a property of languages but of implementations.

So someone got up and asked me: Ok lets say I add a new value-space to your language -- propositions, and a new operator -- sat -- that checks whether a proposition is satisfiable...

So Rick... I agree with you... all these theoreticians should be burnt at the stake!

On a more serious note: many people make similar mistakes eg Haskellers who think Haskell is safe.
Safer (than something or other) -- Ok
Safe -- NO
 
R

Rick Johnson

The answer to this conundrum is staring you in the face.

Thanks for posting a solution for this. Not sure if i'll
ever need it, but nice to know.
Note that the TypeError complains that you passed it an
"unhashable" type, and not that you passed it a "mutable"
type. If you want to take a mutable type and make it
hashable, just add a __hash__ method.

class HashableList(list):
def __hash__(self):
return 42
d = dict()
hl = HashableList(range(5))
hl2 = HashableList(range(6, 10))
d[hl] = 10
d[hl2] = 20
d
{[0, 1, 2, 3, 4]: 10, [6, 7, 8, 9]: 20}

Additionally, instances of user-defined classes are, by
default, both mutable and hashable. This is safe because
equality and hashing for such objects are by default based
on identity. If you override the __eq__ method though,
then you lose hashability unless you explicitly override
__hash__ as well.

Hey, you went above and beyond to provide that last bit of info.
Thanks again!
 
R

rusi

Pure functional languages don't have mutables, or even variables, but
then we're not talking about a pure functional language, we're talking
about Python.

In which case neither do mathematicians. Do we rewrite the last 1000 years of math history?

The incantation:
x = x+1
is something algorithmists (ie programmers) write without batting an eyelid.

Algebraically (ie for a mathematician) this is the specification of an impossibility.

Every programmer needs to have both these modes of thinking -- algebraic and algorithmic -- up his sleeve.

Ironically it was al Khwarizmi -- whose name became 'algorithm' -- who wrote al Gebr -- from which we get algebra ie its taken us a millenium to come full circle!!
 
M

Michael Torrie

Nice idea from a theoretical point of view, but practicality beats
purity, and most people know their functions will terminate (that's
what Ctrl-C is for). No, I want a function isbuggy(f) to find out
whether a function is, well, buggy. We could abolish all unit-testing
if we had that.

That's awesome. I laughed out loud when I read Ian's comment, though it
took me longer than I should have needed to notice your tongue firmly in
your cheek as well.
 
R

Rick Johnson

So Rick... I agree with you... all these theoreticians
should be burnt at the stake! On a more serious note: many
people make similar mistakes eg Haskellers who think
Haskell is safe. Safer (than something or other) -- Ok
Safe -- NO

So now you're going to attempt to defeat my idea by
suggesting that it chalks up to nothing more than a safety
measure? How many times must i explain the simple concept
of stateless subroutines and hazards of the current
incarnation Python FUNCtions (You smell the func!)

Yes you gain safety by utilizing such an implementation
over the current implementation, however you also trim
a negative attribute of the language. Not to mention the
intuitive and readability gains.
 
R

rusi

So now you're going to attempt to defeat my idea by
suggesting that it chalks up to nothing more than a safety
measure? How many times must i explain the simple concept
of stateless subroutines and hazards of the current
incarnation Python FUNCtions (You smell the func!)

I appreciate Rick that you are committed to a better programming language.
And you too need to appreciate that many intelligent and capable people forthe last 50 years have had similar goals. When those goals are soft eg strictures on cohesion and coupling -- which is what your wish for stateless procedures amounts to -- then those remain suggestions and cannot be imposed.
When those goals are made hard as in functional programming then other problems result such as performance hits, what-to-do-about-IO etc etc.

See my blog
http://blog.languager.org/2012/11/imperative-programming-lessons-not.html
for a history of wishes akin to yours and lessons not learnt.

In short the problems accruing from unconstrained imperative programming are severe and the solutions are hard.

In the meanwhile, goals such as your 'keep-procedures-stateless' can and should certainly be practised in the human sphere even if not implemented in the programming language sphere. The aggregation of such 'best-practices' is what I call FP as an ideology rather than as technology.
I have a collection here
http://blog.languager.org/2012/10/functional-programming-lost-booty.html
And I would welcome suggestions/discussions on the same.
 
M

Mark Lawrence

Oh! I know. Function argument defaults will now be restricted to
int/float/tuple. That would do it, right? Nobody would be bothered by
little restrictions like that, would they.

Alas, tuples won't do it. Fortunately, you can include str and bytes
(unicode and str) and frozenset in the "Good List". Tuples have to go
into the "Bad List" because, although they themselves are immutable,
their contents may not be. Imagine the confusion and horror that poor
developers will experience when they do something like this:

def func(arg, extra=(23, 'foo', [])):
[code goes here...]
extra[2].append("something")
[more code...]


and they've now mutated the immutable default!

Thinking about this, I think that the only safe thing to do in Rickython
4000 is to prohibit putting mutable objects inside tuples. Putting a list
or a dict inside a tuple is just a bug waiting to happen!

How about naming the fork RickedPython 4000, where ricked is defined
here http://www.urbandictionary.com/define.php?term=ricked ?

--
"Steve is going for the pink ball - and for those of you who are
watching in black and white, the pink is next to the green." Snooker
commentator 'Whispering' Ted Lowe.

Mark Lawrence
 
A

Antoon Pardon

Op 22-06-13 03:27, Ian Kelly schreef:
On 21/06/2013 21:44, Rick Johnson wrote: [...]
Which in Python would be the "MutableArgumentWarning".

*school-bell*

I notice that you've omitted any mention of how you'd know that the
argument was mutable.

That's easy. Just call ismutable(arg). The implementation of ismutable is
just an implementation detail, somebody else can work that out. A
language designer of the sheer genius of Rick can hardly be expected to
worry himself about such trivial details.

While we're at it, I would like to petition for a function
terminates(f, args) that I can use to determine whether a function
will terminate before I actually call it.

Are you two guys now egging on Rick Johnson?
 
R

Rick Johnson

See my blog [...]
for a history of wishes akin to yours and lessons not
learnt. In short the problems accruing from unconstrained
imperative programming are severe and the solutions are
hard. In the meanwhile, goals such as your 'keep-
procedures-stateless' can and should certainly be
practised in the human sphere even if not implemented in
the programming language sphere. The aggregation of such
'best-practices' is what I call FP as an ideology rather
than as technology.

I have a collection here [...]
And I would welcome suggestions/discussions on the same.

Here are some statements from your blog, i have made a few
tweaks to the text (mainly structure) so as to render it
more readable.
Unfortunately these are the exceptions. In the vast
majority of cases, the quest for generalities only
produces rubbish. So lets see how the... The Philosophy of
OO fares in this regard.

OO starts off its philosophical sojourn with the dogma:
Everything is an object I will start with a variation that
is slightly less nonsensical but easier to debunk;
Everything can be modeled as a class

Now if we start looking at the justifications of this
statement we would find certain methodological directives
such as Identify the nouns in the use-case and make them
classes In itself this is - as a methodology - not
objectionable.

So for example if we are presented with the standard
example of a customer coming to an ATM and making a
transaction, this methodology tells us that it may be a
good idea to make customer and ATM into classes - so far
so good.

And what about transaction? Yes we could make it into a
class also, but as we shall see, blanket- adding the set
of abstract nouns into the set of common nouns as class-
ifiable objects gets us into trouble.

No, the transaction itself need NOT be a custom object.
So for example, if the use-case contained a statement
like: In order to safeguard customer-satisfaction, the
ATM's performance shall not degrade beyond 3 seconds
response time.
So now - according to our methodology - we need to
make performance, response-time and even customer-
satisfaction(!!) into classes.

LOL!

Only a fool, or a religious OOP extremist, would create
custom objects for such things. Although, if he were forced
to use Java, he wouldn't have any choice would he? Poor
basterd! >:D

But my point is, OOP is not a cure-all for every problem, in
fact, it can overly complicate many problems. For instance,
being forced to write an object definition for a simple hello
world program in Java is nothing less than pure sadism --
but that's why i don't use Java unless i'm forced!

OTOH, from skimming a few other threads in your blog, you
seem to long for some salvation of FP to save all our souls
from the eternal damnation of IP, like a Christian
longing for the second coming of Christ!

"Take us away to streets paved in gold!"

I sorry, but FP is not going to wash our sins clean. In
fact, if taken too seriously, FP leads to preaching
professors, intellectually unstimulated students, and
semesters of wasted time that could have been better spent
honing practical *real world* skill sets.

########################################################
# Tip of the Day #
########################################################
# Remember, whilst the professor's tenure will #
# guarantee he gets a paycheck even for producing #
# rubbish, you won't be afforded such luxuries in the #
# real world. #
########################################################

"If it IS to be, then it's up to ME"

The point is, no one paradigm is going to save us from the
devil. We must take from each style it's positive
attributes, and reject it's negative attributes. The art of
intelligently applying multiple paradigms to solve complex
problems should be held up as the pinnacle of greatness. If
your going to worship something, worship achievement.
 
R

rusi

LOL!

Only a fool, or a religious OOP extremist, would create
custom objects for such things. Although, if he were forced
to use Java, he wouldn't have any choice would he? Poor
basterd! >:D

Shall I quote something of yours to Steven about "the ability to recognize sarcasm?"

On a more serious note, Ian's terminate function, or Chris' bug-free function which is the same by Rice theorem are different variants of the same thing: some of the most key things of concern to the programmer cannot be modeled/reified into his program.

The point is, no one paradigm is going to save us from the
devil. We must take from each style it's positive
attributes, and reject it's negative attributes. The art of
intelligently applying multiple paradigms to solve complex
problems should be held up as the pinnacle of greatness. If
your going to worship something, worship achievement.

Ok -- I agree.
 
R

rusi

I sorry, but FP is not going to wash our sins clean. In
fact, if taken too seriously, FP leads to preaching
professors, intellectually unstimulated students, and
semesters of wasted time that could have been better spent
honing practical *real world* skill sets.


########################################################
# Tip of the Day #
########################################################
# Remember, whilst the professor's tenure will #
# guarantee he gets a paycheck even for producing #
# rubbish, you won't be afforded such luxuries in the #
# real world. #
########################################################

Here are some examples for your kind consideration.
[Something I wrote a few days back with a few additions]

Comprehensions and lambdas have come into python. From where? Haskell
[Lambdas have even got into C++ !!]
LINQ in C# inspired by comprehensions
Generics were not there in C# and Java early editions. Now they've
been retrofitted -- Origin SML.
Almost every modern language supports garbage collection. Origin Lisp
Numpy is just APL with python syntax
Hottest DBMSes today are the nosql ones -- couchdb written in erlang.
Knuth - Vol 1 is a gigantic exercise on how to do lisp without lisp.
Also called Greenspun's 10th law: http://c2.com/cgi/wiki?GreenspunsTenthRuleOfProgramming

And heard of google? Uses something called map-reduce. Route: APL -> FPLs -> google

Yes FP is very academic -- for those living in the last century.

I just assumed we are all in 2013 :)
 
D

Dennis Lee Bieber

On 21/06/2013 21:44, Rick Johnson wrote: [...]
Which in Python would be the "MutableArgumentWarning".

*school-bell*

I notice that you've omitted any mention of how you'd know that the
argument was mutable.

That's easy. Just call ismutable(arg). The implementation of ismutable is
just an implementation detail, somebody else can work that out. A
language designer of the sheer genius of Rick can hardly be expected to
worry himself about such trivial details.

While we're at it, I would like to petition for a function
terminates(f, args) that I can use to determine whether a function
will terminate before I actually call it.

Maybe in a universe with different physical constants...

Otherwise I think you have encountered
http://en.wikipedia.org/wiki/Halting_problem (consider: could your function
conclude that it terminates when fed it's own code)
 
R

Rotwang

[...]

This is what should happen:

py> def foo(arg=[]):
... arg.append(1)
... print(arg)
...
py> foo()
[1]
py> foo()
[1]
py> foo()
[1]

Yes, Yes, YES! That is intuitive! That is sane! Now, what if
we pass a reference to a mutable object? What then. Well, let's
see:

py> lst = range(5)
py> lst
[0, 1, 2, 3, 4]
py> def foo(arg=lst):
... arg.append(1)
... print(arg)
...
py> foo()
[0, 1, 2, 3, 4, 1]
py> foo()
[0, 1, 2, 3, 4, 1, 1]

That's fine. Because the object was already created OUTSIDE
the subroutine. So therefore, modifications to the mutable
are not breaking the fundamental of statelessness INSIDE
subroutines. The modification is merely a side effect, and
the subroutine is unconcerned with anything that exists
beyond it's own scope.

IS ALL THIS REGISTERING YET? DO YOU UNDERSTAND?

No, I don't. These two special cases are not sufficient for me to
determine what semantics you are proposing for the general case. For
example, what happens in the second example if lst is rebound? Does the
default stay the same or does it change to the new value of lst? What
about if you pass a call as a default argument, and then subsequently
change the behaviour of the callable? Does the argument get re-evaluated
every time foo() is called, or is the argument guaranteed to be the same
every time? If the latter, what happens if the arguments type is
modified (e.g. by changing one of its class attributes)? What about
defining functions dynamically, with default arguments that are only
known at runtime? Is there any way to avoid the second type of behaviour
in this case? If so, how? If not, isn't that likely to prove at least as
big a gotcha to people who don't know the rules of RickPy as the problem
you're trying to solve?

Since you haven't answered this, allow me to suggest something. One
thing that a language could do is treat default arguments as mini
function definitions with their own scope, which would be the same as
the scope of the function itself but without the function's arguments.
In other words, in this alternative version of Python, the following
.... <stuff>

would be equivalent, in actual Python, to this:
.... if x is sentinel:
.... x = default()
.... <stuff>

That would be something that could be implemented, and as far as I can
tell it's consistent with the examples you've given of how you would
like Python to work. Is this indeed the kind of thing you have in mind?
 
R

Rick Johnson

No, I don't. These two special cases are not sufficient
for me to determine what semantics you are proposing for
the general case.

============================================================
QUESTION 1:
============================================================
For example, what happens in the second
example if lst is rebound?

Well nothing could happen, or something significant could
happen. How do you expect me to determine an answer for
such a general question when i have no context, or any
algorithms to work from.

Maybe you are trying to set a situation that results in
chaos, okay, then chaos will happen. But who's fault is the
chaos when a programmer is rebinding names? The programmer
is ultimately responsible for his action.

Remember my "Apathetic Approach"?

============================================================
QUESTION 2:
============================================================
Does the default stay the same or does it change to the
new value of lst?

Here you go again, you cannot seem to comprehend very simple
concepts. My second example clearly explains what will happen
py> lst = range(5)
py> lst
[0, 1, 2, 3, 4]
py> def foo(arg=lst):
... arg.append(1)
... print(arg)
...
py> foo()
[0, 1, 2, 3, 4, 1]
py> foo()
[0, 1, 2, 3, 4, 1, 1]

Do you see how the name 'lst' is bound to a list object
living in global module scope? Do you see how the default
argument (named `arg`) is a reference to a global list named
`lst`?

ARE YOU FOLLOWING ALONG SO FAR?

Since the mutable arg exists OUTSIDE the subroutine, the
subroutine merely need to provide access to the global
*name* `lst` from within the body of the subroutine, and the
subroutine merely do this ONCE at compile time!

ARE YOU FAMILIAR WITH THE CONCEPT OF POINTERS?

============================================================
QUESTION 3-A:
============================================================
What about if you pass a call as a default argument, and
then subsequently change the behaviour of the callable?

Hmm, let's have a thought experiment. What if i give you a
digital birthday card. And when you open the card you see a
friendly note from me:

"Rotwang is my best friend in the whole wide world".

But unbeknownst to you, i have actually hacked the card and
installed a secret wifi device. I've made the message
mutable -- hmm, surely nothing "bad" could arise from
mutability correct?

*evil-grin*

A few hours later when you open the card to show to some
friends, you are alarmed to see a new message:

"Rotwang is a degenerative penis condition"

Now, besides being embarrassed, and probably angry as hell,
do you understand the dangers of mutable objects?

I'm not suggesting you don't ever want to use the power of
mutability, no, but you do need to have a healthy respect for
mutability -- because it can really ruin your day!

============================================================
QUESTION 3-B:
============================================================
Does the argument get re-evaluated every time foo() is
called, or is the argument guaranteed to be the same every
time?

If the argument is an expression, like a literal, it will be
reset to the literal each time the subroutine is called. If
the argument is a non-local object, the argument will NOT be
reset each time. See "ANSWER 2" for more context.

============================================================
QUESTION 3-C:
============================================================
If the latter, what happens if the arguments type is
modified (e.g. by changing one of its class attributes)?
What about defining functions dynamically, with default
arguments that are only known at runtime? Is there any way
to avoid the second type of behaviour in this case? If so,
how? If not, isn't that likely to prove at least as big a
gotcha to people who don't know the rules of RickPy as the
problem you're trying to solve?

What if X?
What if Y?
What i pass in a pony but i sell it to a glue factory before
the subroutine gets called???

I'm sorry but have no more patience for these ridiculous
questions. If you want me to answer *specific* questions, then
be sure to ask them one at a time and provide relevant code
examples.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top