Re: nonlocal fails ?
On 2019-11-23 18:18:16 -0500, Richard Damon wrote: > On 11/23/19 4:18 PM, Peter J. Holzer wrote: > > On 2019-11-14 20:29:01 -0500, Dennis Lee Bieber wrote: > >>Instead, at a simple level (a common description invokes "Post-It" > >> notes) > >> > >>x = y > >> > >> means /find/ the object (somewhere in memory) that has a note "y" stuck to > >> it. Without moving the "y" note, attach an "x" note to that same object. > >> The object now has two names bound to it. If the "x" note used to be > >> attached to an object, the old object no longer has that name -- and if the > >> object has NO names attached, it is garbage collected. > > Frankly, I find that model very unsatisfying. [... reasons elided ...] > > It's much simpler to talk about references or pointers or whatever you > > want to call them. You can nicely visualize them with arrows (or pieces > > of string, if you want, but arrows have the advantage of having a > > direction) and it describes directly and without any mental gymnastics > > what is going on (on a conceptual level - actual implementations might > > be somewhat different, as long as they behave the same). > > > > A post-it note analogy is a very good description to allow a > non-technical person to understand how it works. It may allow a non-technical person to understand how it doesn't work. I doubt this is very useful. > Yes, as presented, it doesn't handle the concept of scope of variables, > but that starts to get into more complexity than you might want for a > simple model, Yeah, that's exactly the problem. In an attempt to avoid being "technical", it becomes needlessly complex. There seems to be a wide-spread notion that goes something like this: This is how it really works, therefore it is technical, and non-technical people don't understand technical stuff. Therefore we must make up another explanation. It will be more complicated and it will be wrong, but because it is wrong it is non-technical, therefore non-technical people will understand it. > To a non-techie, a 'Pointer' is either a breed of dog or an arrow > pointing in a general direction. Ok, I apparently wasn't thinking straight yesterday. The real world analogy is of course the address. Everybody knows what an address is (and non-technical people won't have all that cognitive baggage either which can lead programmers down endless rabbit holes). Adresses work slightly differently in different countries (and sometimes even different communities in the same country), but the differences won't matter here. Let's just assume the street/house number system as it is common in many western countries (if you are Japanese, think of blocks and buildings instead). So our objects live in houses on a street. When an object is created it just plops into existence in an empty house (And they never leave their house until they die, so the poor things are a pretty lonely bunch). You don't tack post-it notes to the house-doors. Instead you have a notebook[1] (or rather a bunch of them). So when you write something like 1 x = "spam" 2 y = "eggs" 3 z = x + y 4 Ω = z 5 x = "ham" what happens is this: 1 You create a new object with the value "spam": Let's say this is now in Basil Street 42 You write into your notebook: "x: Basil Street 42" 2 You create a new object with the value "eggs" in Basil Street 3 You write into your notebook: "y: Basil Street 3" 3 You look into your notebook for the notes "x" and "y", find the adresses "Basil Street 42" and "Basil Street 3" there, go to those addresses to ask the objects for their values, create a new combined object from them ("spameggs"), put it into a free house (Basil Street 23) and write that into your notebook: "z: Basil Street 23". (Oof, that was quite a mouthful for such a short line) 4 You look up the address of "z" in your notebook and copy it into the entry for Ω: "Ω: Basil Street 23". 5 You create yet another object ("ham") in Basil Street 52. You cross out your entry for "x" and write a new entry "x: Basil Street 52" (At this point there is no entry for Basil Street 42 in your notebook any more. Eventually the object at that house will notice that nobody loves it any more and die out of desparation) This is quite close to what really happens, it generalizes nicely (e.g, if you call a function, you just hand it a new notebook with just the parameters filled in; An object (e.g. a tuple or a dict) may itself possess a notebook; etc.) and it doesn't use any terms (except object) that the "non-technical person" won't be familiar with. > The key is that you are showing something fundamentally different than a > box to hold a value. If you show names as boxes with arrows in them, > someone is going to ask how to get one name point to another name (re > the discussion about is it call by value or call by reference) Which is a legitimate question. The answer is that Python's inventors though
Re: nonlocal fails ?
On Sun, Nov 24, 2019 at 10:19 AM Richard Damon wrote: > Yes, as presented, it doesn't handle the concept of scope of variables, > but that starts to get into more complexity than you might want for a > simple model, and it is simple to extend to handle it, either every > scope gets a different color post-it note, or when you write the name of > the variable, you include the scope. Or you can try to describe a scope as like a notebook where you say "x is Blue K12" where the thing is identified by a matching note (think raffle tickets). Not sure how useful it'd be, but the concept does at least scale. Recursion means setting down one notebook and picking up another (with most/all of the same names). ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/23/19 4:18 PM, Peter J. Holzer wrote: > On 2019-11-14 20:29:01 -0500, Dennis Lee Bieber wrote: >> Instead, at a simple level (a common description invokes "Post-It" >> notes) >> >> x = y >> >> means /find/ the object (somewhere in memory) that has a note "y" stuck to >> it. Without moving the "y" note, attach an "x" note to that same object. >> The object now has two names bound to it. If the "x" note used to be >> attached to an object, the old object no longer has that name -- and if the >> object has NO names attached, it is garbage collected. > Frankly, I find that model very unsatisfying. > > It's not just that it doesn't describe any existing or even plausibly > possible implementation or that it implies a complexity that isn't there > (search for an object with a note attached to it?). It starts to break > down even for simple cases: There may be several variables called "x" in > a program. How does the system distinguish between multiple objects with > an "x" note? What about objects which have no name, like members of a > tuple or the return value of a function? Sure, you can come up with > arcane rules to on how to label a post-it to reference an object > referenced by the x parameter of the lamba on line 7 of the third > recursive invocation of function foo within the method bar of the Gazonk > class in the fred packagerbut called from Bobble ... (ok, I'll stop > now). But why would you? > > It's much simpler to talk about references or pointers or whatever you > want to call them. You can nicely visualize them with arrows (or pieces > of string, if you want, but arrows have the advantage of having a > direction) and it describes directly and without any mental gymnastics > what is going on (on a conceptual level - actual implementations might > be somewhat different, as long as they behave the same). > > hp A post-it note analogy is a very good description to allow a non-technical person to understand how it works. Yes, as presented, it doesn't handle the concept of scope of variables, but that starts to get into more complexity than you might want for a simple model, and it is simple to extend to handle it, either every scope gets a different color post-it note, or when you write the name of the variable, you include the scope. To a non-techie, a 'Pointer' is either a breed of dog or an arrow pointing in a general direction. The key is that you are showing something fundamentally different than a box to hold a value. If you show names as boxes with arrows in them, someone is going to ask how to get one name point to another name (re the discussion about is it call by value or call by reference) -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 2019-11-14 20:29:01 -0500, Dennis Lee Bieber wrote: > Instead, at a simple level (a common description invokes "Post-It" > notes) > > x = y > > means /find/ the object (somewhere in memory) that has a note "y" stuck to > it. Without moving the "y" note, attach an "x" note to that same object. > The object now has two names bound to it. If the "x" note used to be > attached to an object, the old object no longer has that name -- and if the > object has NO names attached, it is garbage collected. Frankly, I find that model very unsatisfying. It's not just that it doesn't describe any existing or even plausibly possible implementation or that it implies a complexity that isn't there (search for an object with a note attached to it?). It starts to break down even for simple cases: There may be several variables called "x" in a program. How does the system distinguish between multiple objects with an "x" note? What about objects which have no name, like members of a tuple or the return value of a function? Sure, you can come up with arcane rules to on how to label a post-it to reference an object referenced by the x parameter of the lamba on line 7 of the third recursive invocation of function foo within the method bar of the Gazonk class in the fred packagerbut called from Bobble ... (ok, I'll stop now). But why would you? It's much simpler to talk about references or pointers or whatever you want to call them. You can nicely visualize them with arrows (or pieces of string, if you want, but arrows have the advantage of having a direction) and it describes directly and without any mental gymnastics what is going on (on a conceptual level - actual implementations might be somewhat different, as long as they behave the same). hp -- _ | Peter J. Holzer| Story must make more sense than reality. |_|_) || | | | h...@hjp.at |-- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!" signature.asc Description: PGP signature -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Sun, Nov 17, 2019, at 07:26, Richard Damon wrote: > I am not sure about C#, but in C++, a base language for C#, you can not > take the address of a variable of reference type, if you do, you get the > objected referred to, not the reference. References are essentially > constant pointers, and can not be re-seated to reference another object. C# is not very closely related to C++, calling it "a base language" would be inaccurate IMO. It's much more similar to Java in many ways. In particular, its "reference types" have absolutely nothing to do with C++'s references. They're much more similar to Java or Python object types. The "ref" references used for call-by-reference arguments are much more similar to C++ references [and there's no analogous feature in Java], but somewhat more restricted (they can't be used as a member of a class, for example) The ability to make a "ref" reference to a variable of reference type is analogous to being able to make a reference to a pointer in C++, even though C#/Java/Python object references are not really the same things as pointers due to e.g. not having pointer arithmetic, etc. (the C++ .NET compatibility layer calls these 'handles', and uses the ^ character for them. The "ref" variables themselves use a % character, since they have to be distinct from &-references due to their role in the .NET garbage collection system) > I suppose one way at looking at Python's name binding system (maybe not > entirely accurate) would be to say that all Python names act like > references, but that assignment, rather than being applied to the > referred to object, re-seat the reference to point to the new object. As > such, you can't get a reference to the name, to let one name re-seat > where another name refers to. I guess if anything this discussion has proven to me that C#'s decision to use "reference" for two unrelated concepts in fact causes more confusion than I thought it would from the perspective of the amount of .NET experience I have. However, my point was that the basic idea of pass by reference, even if it should be called something else (if implemented in Python it would probably use cell objects as "references", with some other kind of wrapper object being needed to handle the case of the target not being a local variable) is not fundamentally inapplicable to Python just because of the object reference model. Call by cell? Call by getter/setter? There's an old saying that one of the hardest problems in computer science is naming things. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/17/19 1:33 AM, Random832 wrote: > On Fri, Nov 15, 2019, at 13:41, Dennis Lee Bieber wrote: >> C# documents those as something visible to the user at the language >> level... >> https://www.infoworld.com/article/3043992/a-deep-dive-value-and-reference-types-in-net.html >> """ >> Types in Microsoft .Net can be either value type or reference type. >> """ > I was strictly talking about how reference types work (which are just like > python or Java objects), and how that is completely distinct from the "ref" > of call-by-reference arguments which are also supported, and that both > features coexist just fine in the same language. The existence of value types > wasn't really relevant to my point. > > I'm not sure if you were left with the impression that you can't have a "ref" > argument that points to a variable of reference type (and which does *not* > point directly to the object), but that is false. I am not sure about C#, but in C++, a base language for C#, you can not take the address of a variable of reference type, if you do, you get the objected referred to, not the reference. References are essentially constant pointers, and can not be re-seated to reference another object. I suppose one way at looking at Python's name binding system (maybe not entirely accurate) would be to say that all Python names act like references, but that assignment, rather than being applied to the referred to object, re-seat the reference to point to the new object. As such, you can't get a reference to the name, to let one name re-seat where another name refers to. -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019, at 13:41, Dennis Lee Bieber wrote: > C# documents those as something visible to the user at the language > level... > https://www.infoworld.com/article/3043992/a-deep-dive-value-and-reference-types-in-net.html > """ > Types in Microsoft .Net can be either value type or reference type. > """ I was strictly talking about how reference types work (which are just like python or Java objects), and how that is completely distinct from the "ref" of call-by-reference arguments which are also supported, and that both features coexist just fine in the same language. The existence of value types wasn't really relevant to my point. I'm not sure if you were left with the impression that you can't have a "ref" argument that points to a variable of reference type (and which does *not* point directly to the object), but that is false. > Similar to Java. Well, Java doesn't have user-defined value types, but again, value types are beside the point. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Sat, Nov 16, 2019 at 5:41 PM Gregory Ewing wrote: > > On 16/11/19 8:22 am, Chris Angelico wrote: > > That's the typical sort of description you get from someone who mostly > > understands Python's semantics, but is hung up on the idea that > > everything is either call-by-value or call-by-reference, and is trying > > to figure out which box Python fits into. > > Or they may have read the definition of "call by value" in the > Algol60 report, which says that "The actual parameter expression > is evaluated and the result is assigned to the formal parameter." > Which is exactly what Python does... > This is 100% true, but actually just punts on the question of "call-by-X". All the subtleties are bound up in this little bit: > the result is **assigned** to the formal parameter Which is actually a really REALLY good way to start peeling things back. In Python - and in many many other languages - the semantics of function calls can be summarized as assignment. You evaluate an expression in the caller's context, and assign the result to a local name in the callee's context. So far, C and Python both have the exact same semantics. So the real question is: What is assignment? And that's where everything about name binding comes in. In C, that assignment operates on a bit-copying level, cloning some value (which might be a pointer). In Python, that same assignment operates as a name binding, giving the target a reference to some particular object. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 16/11/19 8:22 am, Chris Angelico wrote: That's the typical sort of description you get from someone who mostly understands Python's semantics, but is hung up on the idea that everything is either call-by-value or call-by-reference, and is trying to figure out which box Python fits into. Or they may have read the definition of "call by value" in the Algol60 report, which says that "The actual parameter expression is evaluated and the result is assigned to the formal parameter." Which is exactly what Python does... (Notably, that definition doesn't contain the word "value" at all. So people who argue about the meaning of "call by value" based on the meaning of "value" are barking in the wrong direction.) -- Greg -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/2019 5:48 AM, R.Wieser wrote: Closures are standard in functional languages and are less limited than you seem to think. I was talking about the "nonlocal" method of variable inheritance, not closures. You cannot really separate the two. A 'nonlocal' declaration can only be used in a nested function, and when you do, the function becomes a closure (a function with a '__closure__' attribute that is not None). -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Sat, Nov 16, 2019 at 6:20 AM Luciano Ramalho wrote: > > Re: the whole pass by reference discussion. > > I've seen Python's argument passing described as "call by value, > except that all values are references". This makes sense, but is > confusing. That's the typical sort of description you get from someone who mostly understands Python's semantics, but is hung up on the idea that everything is either call-by-value or call-by-reference, and is trying to figure out which box Python fits into. > Michael Scott, in his textbook Programming Language Pragmatics (4e) > terms the Python way "call by sharing". That is the same mode used in > most OO languages that don't have pointers, including Ruby, SmallTalk, > and Java (this applies to Java reference types; primitive types use > call by value). Call by sharing means that each formal parameter of > the function gets a copy of each reference in the arguments. > I don't think anyone's yet linked to this: https://nedbatchelder.com/text/names1.html ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Re: the whole pass by reference discussion. I've seen Python's argument passing described as "call by value, except that all values are references". This makes sense, but is confusing. Michael Scott, in his textbook Programming Language Pragmatics (4e) terms the Python way "call by sharing". That is the same mode used in most OO languages that don't have pointers, including Ruby, SmallTalk, and Java (this applies to Java reference types; primitive types use call by value). Call by sharing means that each formal parameter of the function gets a copy of each reference in the arguments. Cheers, Luciano On Fri, Nov 15, 2019 at 3:58 PM Dennis Lee Bieber wrote: > > On Fri, 15 Nov 2019 11:54:50 -0500, Richard Damon > declaimed the following: > > > > >I remember in early FORTRAN being able to do something like this (its > >been years since I have done this so syntax is probably a bit off) > > > > > > > >foo(1) > > > >and after that if you did > > > >j = 1 > > > >then now j might have the value 2 as the constant 1 was changed to the > >value 2 (this can cause great confusion) > > > > It was a very early FORTRAN that did that, since literals were stored > in general R/W memory and the address was passed. Later FORTRAN compilers > would flag a section of memory for R/O and stored literals in that section > -- so attempts at modification would result in an error. > > >later I believe they added the ability to specify by value and by > >reference, and you weren't allowed to pass constants by reference, > > Many compilers added extensions for interfacing to other languages > (DEC > is famous for %val(), %ref(), %descr() for controlling parameters, and > %loc() external to parameters. %ref wasn't really useful in FORTRAN since > that is the native method. %loc returned the address of the target item. > %descr was a weird one -- things like character strings were passed by > descriptor: first word was the address [standard reference model], second > word encapsulated information like the length allocated to the string [not > the length used, but the size of the memory allocation]. > > Literals were still passed by reference -- just to read-only memory > block. Otherwise the called function wouldn't know how to behave! > > subroutine xyz(parm) > integer parm > > ... > > call xyz(1) > call xyz(abc) > > if the first was passed by value and the second by reference, what was > "parm" in the called function to do > > > -- > Wulfraed Dennis Lee Bieber AF6VN > wlfr...@ix.netcom.comhttp://wlfraed.microdiversity.freeddns.org/ > > -- > https://mail.python.org/mailman/listinfo/python-list -- Luciano Ramalho | Author of Fluent Python (O'Reilly, 2015) | http://shop.oreilly.com/product/0636920032519.do | Technical Principal at ThoughtWorks | Twitter: @ramalhoorg -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
> On Nov 15, 2019, at 11:11 AM, Python wrote: > > Richard Damon wrote: > ... >> then elsewhere you could do >> foo(j) >> and after that j is 2 >> you also could do >> foo(1) >> and after that if you did >> j = 1 >> then now j might have the value 2 as the constant 1 was changed to the >> value 2 (this can cause great confusion) > > Wow! So fubar that such a feature should definitely makes its > way into PHP! I remember fixing a bug caused by this. Bev in TX -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 12:21 PM, Random832 wrote: > On Fri, Nov 15, 2019, at 11:47, Richard Damon wrote: >> The issue with calling it a Reference, is that part of the meaning of a >> Reference is that it refers to a Object, and in Python, Names are >> conceptually something very much different than an Object. Yes, in the >> implementation details, a name is basically a dictionary entry, so it >> could be done, the question is should it. > C# has basically the same issue and does fine calling its thing 'ref'. But > that's not really the point - my point was that the concept of being able to > have a function change the value of a variable specified by its caller > doesn't magically cease being applicable just because the value is a > "reference" and the variable is a "name binding". > > [Similarly, the fact that values are "references" to mutable objects doesn't > mean that python, or Java or C#, isn't call-by-value. The value is the > "reference" itself, the fact that it can be used to change data that exists > elsewhere is beside the point.] My understanding is the C# is like the rest of the C* family that defining a variable x in the code, binds the name x to a specific object in memory at compile time. That name will ALWAYS refer to that object and that object can be thought to have that name, and no others in the same way. The object may be/have a reference to another variable. (C++ references are a bit different at the language level, a reference itself isn't an object, and taking the address of the reference 'object' give the address of the object that the reference refers to, C++ references are still compile time bound to a single object, but that object still has a concept of the name it was created through) (I will admit that I don't really know C#, but going from what I understand it as) This is NOT true in Python. A 'Variable Name' in Python is not statically bound to given object, but every assignment rebind the name to object mapping. Python does NOT use call by value, because a key feature of call by value is that the value being passed is copied, and the new copy is used in the subroutine. Name bindings are NOT values, objects have values, and the value of the object passed is NOT copied to somewhere else. It is only by misunderstanding the language, and trying to define a name as being some sort of pointer object that points to the 'real' value of object that you can create such an idea. This is NOT the model Python is defined with, and while it might help a bit when starting to understand how things work, you do need to move from that 'wrong' understanding to starting to think of it the way Python is defined, or many things in Python won't make sense. -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019, at 11:47, Richard Damon wrote: > The issue with calling it a Reference, is that part of the meaning of a > Reference is that it refers to a Object, and in Python, Names are > conceptually something very much different than an Object. Yes, in the > implementation details, a name is basically a dictionary entry, so it > could be done, the question is should it. C# has basically the same issue and does fine calling its thing 'ref'. But that's not really the point - my point was that the concept of being able to have a function change the value of a variable specified by its caller doesn't magically cease being applicable just because the value is a "reference" and the variable is a "name binding". [Similarly, the fact that values are "references" to mutable objects doesn't mean that python, or Java or C#, isn't call-by-value. The value is the "reference" itself, the fact that it can be used to change data that exists elsewhere is beside the point.] -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Richard Damon wrote: ... then elsewhere you could do foo(j) and after that j is 2 you also could do foo(1) and after that if you did j = 1 then now j might have the value 2 as the constant 1 was changed to the value 2 (this can cause great confusion) Wow! So fubar that such a feature should definitely makes its way into PHP! -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 11:26 AM, Dennis Lee Bieber wrote: > On Fri, 15 Nov 2019 12:56:02 +0100, "R.Wieser" > declaimed the following: > >> There are quite a number of languages where /every/ type of argument >> (including values) can be transfered "by reference". Though some default to >> "by value", where others default to "by reference". >> > Yes -- and in those languages the concept of value vs reference is > visible at the source code level. In C, everything is passed by value -- > and the programmer uses & to pass (by value) the address of the argument, > and uses * in the called function to dereference that address back to the > data item itself. C++ added reference arguments (where the & is used in the > function declaration) in which the compiler automatically applies the > "address" and "dereference" operations. There are languages where pass by reference is the default and not explicit. I remember in early FORTRAN being able to do something like this (its been years since I have done this so syntax is probably a bit off) PROCEDURE foo(i) i = 2 return then elsewhere you could do foo(j) and after that j is 2 you also could do foo(1) and after that if you did j = 1 then now j might have the value 2 as the constant 1 was changed to the value 2 (this can cause great confusion) later I believe they added the ability to specify by value and by reference, and you weren't allowed to pass constants by reference, -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 11:04 AM, Random832 wrote: > On Fri, Nov 15, 2019, at 10:48, Richard Damon wrote: >> On 11/15/19 6:56 AM, R.Wieser wrote: >>> There are quite a number of languages where /every/ type of argument >>> (including values) can be transfered "by reference". Though some default >>> to >>> "by value", where others default to "by reference". >> It seems you are stuck in a programming model different than what Python >> provides, In a very real sense, the terms call "By Reference" and "By >> Value" don't apply to Python. Those concepts presume that a variable >> name represents a bucket of bytes that holds some value, and call by >> value copies those bytes into a new variable for the subroutine, and >> call by Reference creates a pointer value back to original value, and >> all uses of that parameter work indirect that pointer. >> >> That is NOT how Python works. In Python, in effect, every name in your >> code is just a reference which points to some object (This is called >> binding). Multiple names can point to the same object (or no names, at >> which point the object is subject to being garbage collected). Names >> themselves aren't objects, so you can't really make one name refer to >> another, only to the same object that the other one does. (In actuality, >> these collections of names are implemented basically in a Dictionary, so >> using this sort of implementation details you can sort of get that >> result, but I don't think that is defined to work in the language). > Being abstractly typed objects rather than a bucket of bytes, and having the > values themselves be a kind of reference or pointer (though to immutable data > in some important cases), does not in fact change the meaning of the "call by > reference" concept or its applicability. > > It would be entirely reasonable, I think, in the python model, to provide a > way for making a variable a cell variable, passing the cell object around > explicitly, and having the called function automatically set/get the value > when the argument is accessed. I don't think it would solve the OP's problem, > since his talk about automatically "inheriting" the caller's variable of the > same name sounds a lot more like dynamic scope than call by reference. It isn't hard to explicitly do this in Python. The caller just puts it value into a 1 element list, and then the called function mutates that list (setting parm[0] instead of parm). This appears to align with standard Python idioms. The issue with calling it a Reference, is that part of the meaning of a Reference is that it refers to a Object, and in Python, Names are conceptually something very much different than an Object. Yes, in the implementation details, a name is basically a dictionary entry, so it could be done, the question is should it. I have learned many computer languages over the years, and can say that while figuring out how to map constructs from one language to another has some value to start, you really do want to learn how the language really working in itself. There is an old saying that you can write FORTRAN in any language, and in a real sense it is true, and applies to many languages. In a general sense you can generally take a programming style from language X, and use it in language Y, and often be able to get a 'working' and 'valid' program, but your really should be using language X structures and use them in language X, write language Y using the normal style for language Y. In general, if you want to write a 'x' program, use language x, not language y. The major exception is if language x isn't available on the platform, but Python is usually the fallback language to go to, that will more likely be C or C++ as those are what are most often the first languages that are brought to a platform. (So maybe learning how to write Python is C is useful, but writing C in Python has less need), -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 5:28 AM, R.Wieser wrote: > :-) Although that is how we humans remember the effect of what we do, there > is no reason for a programming language to do it exactly like that. And > sometimes they don't. So, in effect he's saying not all languages use the classic variable model, which you then agree with but then go on to insist that there must be a way in Python to implement the classic, traditional language variable model? I don't understand your point. > Which you can find back in any language which allows a "by reference" > passing of arguments to a procedure (and do remember how strings are often > /only/ passed as such).The caller often uses one name for the "value" > passed as an argument but in the procedure uses a different one - both > accessing the same contents. Again, which isn't Python. And come to that such mechanisms should be used sparingly in languages which offer/require them. > With some variation of "simple" I guess. :-) > > Personally I think I would sooner go for a single-element tuple. To each his own. I rather suspect Python is not a good a fit for you. Quite a few folks here have showed a lot of patience with your questions, and posted very insightful and educational comments, which is a part of the list that I enjoy very much and learn a great deal from. But you seem to unwilling to internalize any of it. However, I appreciate that you have kept the tone civil and polite. Thank you. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019, at 10:48, Richard Damon wrote: > On 11/15/19 6:56 AM, R.Wieser wrote: > > There are quite a number of languages where /every/ type of argument > > (including values) can be transfered "by reference". Though some default > > to > > "by value", where others default to "by reference". > > It seems you are stuck in a programming model different than what Python > provides, In a very real sense, the terms call "By Reference" and "By > Value" don't apply to Python. Those concepts presume that a variable > name represents a bucket of bytes that holds some value, and call by > value copies those bytes into a new variable for the subroutine, and > call by Reference creates a pointer value back to original value, and > all uses of that parameter work indirect that pointer. > > That is NOT how Python works. In Python, in effect, every name in your > code is just a reference which points to some object (This is called > binding). Multiple names can point to the same object (or no names, at > which point the object is subject to being garbage collected). Names > themselves aren't objects, so you can't really make one name refer to > another, only to the same object that the other one does. (In actuality, > these collections of names are implemented basically in a Dictionary, so > using this sort of implementation details you can sort of get that > result, but I don't think that is defined to work in the language). Being abstractly typed objects rather than a bucket of bytes, and having the values themselves be a kind of reference or pointer (though to immutable data in some important cases), does not in fact change the meaning of the "call by reference" concept or its applicability. It would be entirely reasonable, I think, in the python model, to provide a way for making a variable a cell variable, passing the cell object around explicitly, and having the called function automatically set/get the value when the argument is accessed. I don't think it would solve the OP's problem, since his talk about automatically "inheriting" the caller's variable of the same name sounds a lot more like dynamic scope than call by reference. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 4:56 AM, R.Wieser wrote: >> Well I've only seen this done in languages where other mechanisms >> for returning complex types are not present. > > :-) Than you have not seen to many languages I'm afraid. Careful there. > If I would have wanted that, why would I post here with open questions ? > But yes, I often refer to how other languages work, in an attempt to get the > other to tell me whats so special/different about the current languages > solution for it. Yes you can learn a certain amount about a language by doing such 1:1 transliteration exercises. But you can only go so far. For example you'll never master such powerful concepts as generators, closures, list comprehensions, and so forth by doing this. I've found a far better way is to do a project in a language, either something you've done already in another language, or something new. Instead of doing a low-level transliteration, look at the problem at the high level, and find out how the language at hand best works to solve the problem. That's why I and others asked what problem you're trying to solve. Also you seem to be comparing traditional, compiled with statically- but often weakly-typed languages such as C, C++, Pascal, etc, with Python, which is an interpreted, dynamically-typed language. They are very different beasts with different strengths and weaknesses and very different performance characteristics. The reason you're getting such push back is that over the years on this list we've seen dozens of new users arrive at Python but never really learn how to program in Python. These users insisted on coding in Java, C#, or C++ (or whatever) in Python. Some resist strongly when we suggest this is a recipe for failure. It was an exercise in frustration and most of them left thinking what a horrible, limited language Python is, and unable to understand what makes Python so productive, expressive, and powerful. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/15/19 6:56 AM, R.Wieser wrote: > There are quite a number of languages where /every/ type of argument > (including values) can be transfered "by reference". Though some default to > "by value", where others default to "by reference". It seems you are stuck in a programming model different than what Python provides, In a very real sense, the terms call "By Reference" and "By Value" don't apply to Python. Those concepts presume that a variable name represents a bucket of bytes that holds some value, and call by value copies those bytes into a new variable for the subroutine, and call by Reference creates a pointer value back to original value, and all uses of that parameter work indirect that pointer. That is NOT how Python works. In Python, in effect, every name in your code is just a reference which points to some object (This is called binding). Multiple names can point to the same object (or no names, at which point the object is subject to being garbage collected). Names themselves aren't objects, so you can't really make one name refer to another, only to the same object that the other one does. (In actuality, these collections of names are implemented basically in a Dictionary, so using this sort of implementation details you can sort of get that result, but I don't think that is defined to work in the language). In the more classical languages, to draw a model of the variables you have in memory, you take a big sheet of paper, put down each variable name, and next to it a box where you put what value is stored in the variable, and that value is intimately associated with that variable name. You might have some objects being or containing pointers/references and in that case you can represent it by an arrow from the box representing the pointer to the object it is pointing to. There may be some object that are created without a name (like on the heap), but many of the objects are directly tied to a name. In Python you do this differently. On one side of your paper, you put your variable names, and on the other (perhaps a larger side) all the values/objects you are working with. Each name gets an arrow to an object to show what object it is currently bound to. Objects store the values they hold, and some, like collections) also have arrows to other objects they reference. An arrow always points to an object, never to a name on the left side. An assignment just changes what object a reference points to. If it is a 'top level' name being assigned to (as opposed to referring to a member of an object or element of a collection), that is changing one of the names on the left side of the page. This difference in value model means you have to think about things differently, and in a very real sense makes the terms 'by value' and 'by reference' not applicable. You don't get values 'By Value', because you didn't get a copy of the object reference, so if you mutate it, the caller sees the change, but also it isn't by reference, as you can't rebind the callers reference to point to a different object. This isn't 'Wrong' just 'Different'. It takes some getting used to a different model, and I think it helps to accept that it is different rather than trying to keep trying to translate how Python does things into how some other language does it, as the latter make you focus on the things it can't do, not the things it can. -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Pieter, > Do you mean, if Proc1() is called from Func1, it uses MyVar defined >in Func1, and if it is called from Func2, it uses MyVar from Func2? Yep. > If that is what you mean, that would be dynamic scope. Thanks for pointing that out (I've learned a new definition today! :-) ). Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Dennis, > The first thing one needs to learn is that Python does NOT follow the > common post-office mailbox concept where > > x = y > > means the /value/ stored at location identified by "y" is /copied/ to the > location identified by "x". :-) Although that is how we humans remember the effect of what we do, there is no reason for a programming language to do it exactly like that. And sometimes they don't. > means /find/ the object (somewhere in memory) that has a note "y" > stuck to it. Without moving the "y" note, attach an "x" note to that > same object. Which you can find back in any language which allows a "by reference" passing of arguments to a procedure (and do remember how strings are often /only/ passed as such).The caller often uses one name for the "value" passed as an argument but in the procedure uses a different one - both accessing the same contents. > In software engineering as I learned it, it is preferable to decouple ... not because its so good for us humans, but that way you can mathematically prove that the finished program should work as designed. ... which some languages (mostly the ones which allow only single results returned from a function) are starting to turn back from (allowing "by reference" access back in - its just too damn usefull). > All depends upon the scope of those procedures. I have no idea which circumstances you're hinting at. But just take it that the scope is local - apart from that externally referenced value ofcourse. > The simplest is to use a mutable object as a container at the > module level. With some variation of "simple" I guess. :-) Personally I think I would sooner go for a single-element tuple. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019 at 11:01 PM R.Wieser wrote: > > As for "complex types" ? I don't think a(n ASCII) string can be considered > any kind of a complex type, but most all languages I know of transfer them > "by reference" only (though some fake "by value" by using a copy-on-write > mechanism). "Pass by value" and "pass by reference" become largely irrelevant when your strings are immutable objects; so I would say that a large number of languages have broadly "pass-by-value" semantics for strings, treating them as first-class objects that are defined by value, not identity. > > In C you can either return a pointer to the string (and remember who's > > responsibility it is to free the memory!), or you can allocate memory > > yourself and pass the pointer to a function, like strcpy. > > Or pass a reference to an empty pointer, have the procedure allocate the > memory and return the address of it in that pointer. I don't know why you'd do that rather than simply return the new pointer, but whatever. It's still a lot clunkier than simply returning a string, which is what happens in all sane high-level languages. > > In Python there is no similar equivalent, > > It looks like it > > > other than hacks involving passing in mutable objects > > The only "hack" I see here is to transfer /mutable/ object, instead of a > non-mutable one. Yes, Python has no concept of pass-by-reference. Python *always* passes objects around, not variables. But everything that you could do with "pass by reference" can be done by passing a mutable object, and everything that you could do by passing mutable objects around can be done by passing pointers to data structures, or (equivalently) passing data structures by reference. There's no real difference. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019 at 9:16 PM R.Wieser wrote: > > Chris, > > > That doesn't really answer the question. > > The problem is that you want to solve /this/ problem, while I'm looking for > replies that are applicable to similar ones too. > > To be blunt about it: I consider solutions that only solve a single problem > most always as a waste of my time (exceptions to the rule, yadayadayada). > Solutions that I can expand and build upon are the ones I'm looking for > (read: learn from). > > But as lot of people will respond like you and than pick something from the > /supporting information/ and go off on a tangent with it that doesn't aim to > answer /my/ question I have become rather carefull about what I post in > regard to specifics. > > > The point of your new car isn't to push the pedal - it's to get you some > > place. > > And thats your problem in a nutshell: You think in forms of "get you some > place". > > What about just /learning how to drive/ ? > The purpose of a car is not to learn how to ride a bicycle. Yes, I am thinking in terms of an ultimate goal, because the point of coding is to achieve something. Maybe your goal *right now* is to learn rather than to create, but surely the purpose of the learning is to be able to achieve things later? Rather than try to implement pass-by-reference semantics in Python, figure out what abstract concept you're actually trying to implement. Otherwise, all you'll do is come up with convoluted methods of implementing some other language's semantics in Python, and then write your code using that other language's idioms, and run it in a Python interpreter. Far better to actually learn Python's semantics, and how they can be used to represent your actual goals. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Michael, > Well I've only seen this done in languages where other mechanisms >for returning complex types are not present. :-) Than you have not seen to many languages I'm afraid. There are quite a number of languages where /every/ type of argument (including values) can be transfered "by reference". Though some default to "by value", where others default to "by reference". As for "complex types" ? I don't think a(n ASCII) string can be considered any kind of a complex type, but most all languages I know of transfer them "by reference" only (though some fake "by value" by using a copy-on-write mechanism). > In C you can either return a pointer to the string (and remember who's > responsibility it is to free the memory!), or you can allocate memory > yourself and pass the pointer to a function, like strcpy. Or pass a reference to an empty pointer, have the procedure allocate the memory and return the address of it in that pointer. And only the second one comes near to what I indicated I asked about: a mutable value stored outside the current procedure. > In Python there is no similar equivalent, It looks like it > other than hacks involving passing in mutable objects The only "hack" I see here is to transfer /mutable/ object, instead of a non-mutable one. > Fair enough, but trying to do 1:1 transliterations isn't going to > help you learn idiomatic Python. If I would have wanted that, why would I post here with open questions ? But yes, I often refer to how other languages work, in an attempt to get the other to tell me whats so special/different about the current languages solution for it. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Terry, > This is discouraged for anything very complex. Complex things do not exist. If you think you have something like it you've just not yet broken it down in its components yet. :-) > This is the standard way in Python and other OO languages. By 'excluded', > do you mean 'rejected', or 'tried that, what else is there?' The latter. Although I've pretty-much rejected the "global" method. > Closures are standard in functional languages and are less limited than > you seem to think. I was talking about the "nonlocal" method of variable inheritance, not closures. I'm not going to comment (much) on the latter until I've had a chance to play with them. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Chris, > That doesn't really answer the question. The problem is that you want to solve /this/ problem, while I'm looking for replies that are applicable to similar ones too. To be blunt about it: I consider solutions that only solve a single problem most always as a waste of my time (exceptions to the rule, yadayadayada). Solutions that I can expand and build upon are the ones I'm looking for (read: learn from). But as lot of people will respond like you and than pick something from the /supporting information/ and go off on a tangent with it that doesn't aim to answer /my/ question I have become rather carefull about what I post in regard to specifics. > The point of your new car isn't to push the pedal - it's to get you some > place. And thats your problem in a nutshell: You think in forms of "get you some place". What about just /learning how to drive/ ? Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 14/11/19 18:46, R.Wieser wrote: > Jan, > >> So what you want to do is dynamic scope? > No, not really.I was looking for method to let one procedure share a > variable with its caller - or callers, selectable by me. And as a "by > reference" argument does not seem to exist in Python ... If you start thinking about what kind of argument passing mechanisme Python has, you should first think about what kind of assignment semantics Python has. In some sense all parameter passing in Python is by reference, but it is the assignment semantics that cause it to not have the effect people expect. The preffered terminology is call by sharing, but if you mutate the parameter it has the same effect as call by reference. -- Antoon. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
"R.Wieser" writes: > Jan, > >> So what you want to do is dynamic scope? > > No, not really.I was looking for method to let one procedure share a > variable with its caller - or callers, selectable by me. And as a "by > reference" argument does not seem to exist in Python ... > > And yes, I am a ware that procedures can return multiple results. I just > didn'want to go that way (using the same variable twice in a single > calling). Do you mean, if Proc1() is called from Func1, it uses MyVar defined in Func1, and if it is called from Func2, it uses MyVar from Func2? If that is what you mean, that would be dynamic scope. -- Pieter van Oostrum WWW: http://pieter.vanoostrum.org/ PGP key: [8DAE142BE17999C4] -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 12:57 PM, R.Wieser wrote: > Michael, > >> nonlocal does not share or use its *caller's* variables. Rather it >> reaches into the scope of the outer function where it was defined. >> That's a very different concept than what you're proposing. > Oh blimy! You're right.Its an at compile-time thing, not a runtime > one. > > Thanks for the heads-up. > >> I know of no sane way that a function could work with the scope of >> any arbitrary caller. > The trick seems to be to emulate a "by reference" call, by using a mutable > object as the argument and stuff the value inside of it (IIRC a tuple with a > single element). tuples are immutable, use a list or a dictionary. >> What would happen if the caller's scope didn't have any >> names that the function was looking for? > Handle it the same as any other mistake, and throw an error ? > > Regards, > Rudy Wieser > > -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 1:43 PM, R.Wieser wrote: > Richard, > >> Assuming that one language works like another is a danger > Abitrarily redefining words and using misnomers is another ... ("global" > and "nonlocal" respecivily if you wonder) > >> First, Python doesn't really have 'Variables' like a lot of other >> languages >> (they don't hold a bag of bytes), as Python names don't hold values, but >> are just references to objects which actually hold the value > That's a principle as old as programming languages itself I believe. There are at least two very different concepts that act like variables in different languages. In a language like C, a variable is a 'bucket of byte' that holds some value. If you assign the value of one variable to another, that byte pattern is copied from one to another. That representation might include a pointer to some other block (a pointer or reference), but generally this is something explicit. In this sort of language your names represent variables that actually hold values. In Python, the name for your 'variable' doesn't actually hold the value that is assigned to it, but instead the bucket of bytes associated with the name is ALWAYS a pointer to a bucket of bytes that represents the value. Multiple names are allowed to point to the same value object, so assigning one name to another just copies that pointer, and they share the same value object. You shouldn't really think of names as holding 'values' but the names are 'bound' to the value objects (which aren't tied to a given name). > >> If the name is never bound to something, then the name will be also looked >> for in the global namespace. > Can you give an example of that ?I currently cannot wrap my head around > what you could be meaning there - anything I can imagine simply doesn't make > any sense ... > > Regards, > Rudy Wieser > #This Function creates a local name and updates it. str will be created locally and looked up locally def useslocal(): str = "String" str = str + " Added" gstr = "Global" # This function never binds a value to gstr, so it will look in the 'global' space to find the name def useglobal(): str = gstr + " Seen" # This function include a binding to gstr, so it is only looked for locally, #so this use will create an error that it can't find gstr, # even though it was defined in the global name space def getserror(): str = gstr + " Error" gstr = str # This works because of the global statement, and updates the global def workingglobal(): global gstr str = gstr + " Error" gstr = str -- Richard Damon -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 2:16 PM, R.Wieser wrote: > I think I did - though implicitily. What do normal people use "by > reference" arguments for ? Yep, that is what I wanted too. Well I've only seen this done in languages where other mechanisms for returning complex types are not present. For example in C. Chris talked about dealing with languages where strings are not first-class citizens, for example. In C you can either return a pointer to the string (and remember who's responsibility it is to free the memory!), or you can allocate memory yourself and pass the pointer to a function, like strcpy. In Python there is no similar equivalent, other than hacks involving passing in mutable objects and using those objects to save the state. State is maintained either by returning everything from the function you need to maintain state (in a tuple, for example), or by using OOP. Another mechanism Python has for doing certain types of state keeping between calls is the generator idea. > I'm trying to learn how Python works, and for that I (ofcourse) compare it > to other languages. What-and-how it does something different (or equal!) > in regard to them. Fair enough, but trying to do 1:1 transliterations isn't going to help you learn idiomatic Python. > 1) Have value > 2) use value in procedure 1 > 3) use updated value in procedure 2 > 4) use again updated value in procedure 1, 2 or maybe 3 A clear case for using an object and placing your procedures as methods to the object. Everything in Python is OO under the hood, even if you are not forced to use a particular paradigm. Even a module is an object. It's a sort of singleton really. functions are like a static method in other languages. The beauty of Python's organization, though, is you don't have to use a forced class structure as your namespace. Modules and packages provide a nicer namespace than Java or C#'s method. But I digress. > For the sake of learning I'm now going over all of the possibilities to see > if and how they work. For that I've already excluded globals and the > practice of feeding the value as an argument to the procedure and than store > its result as the new one. I've also excluded using a class object and put > the code in there, as well as faking a "by reference" passing by using a > tuple. "nonlocal" looked to be another option, but it appears to be rather> > limited in its application. Well be sure to add Python's classes and objects to your list of possibilities. And also explore generators (coroutines). > In short, the /ways to the goal/ are (currently) important to me, not the > goal itself (I'm sure that apart from the "nonlocal" one all of the above > are viable, and I thus can get /something/ to work) > > Yeah, I'm weird like that. Sorry. Okay I just was wondering if there is a particular task at hand. Often that's the best way to learn a language. You have a specific task you want to accomplish, or program you need to write, and then find out the best way to do it within the abilities and strengths of the language. Years ago I was taught Prolog and man I fought that language because I never really grasped the concepts and wanted to program in C or Pascal instead of Prolog. If I knew then what I know now I would have probably had an easier time of it. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/2019 4:16 PM, R.Wieser wrote: If you mentioned what problem you are trying to solve 1) Have value 2) use value in procedure 1 3) use updated value in procedure 2 4) use again updated value in procedure 1, 2 or maybe 3 For the sake of learning I'm now going over all of the possibilities to see if and how they work. > For that I've already excluded globals and the practice of feeding the value as an argument to the procedure and than store its result as the new one. This is discouraged for anything very complex. I've also excluded using a class object and put the code in there, This is the standard way in Python and other OO languages. By 'excluded', do you mean 'rejected', or 'tried that, what else is there?' as well as faking a "by reference" passing by using a tuple. One has to pass a mutable, such as list, set, dict, or user class instance. "nonlocal" looked to be another option, but it appears to be rather limited in its application. Closures are standard in functional languages and are less limited than you seem to think. But you have to enclose (nest) many or all of the functions that directly rebind 'val' (else one might as well use a global value). def valclass(val): def set(newval): # For functions not defined within valclass. nonlocal val val = newval def get() return val def proc1(args) nonlocal val ... dev proc2(args) nonlocal val ... return setval, getval, proc1, proc2 # return {'set':set, 'get':get, 'proc1':proc1, 'proc2':proc2} setval, getval, proc1, proc2 = valclass(3) # val = valclass(3) In short, the /ways to the goal/ are (currently) important to me, not the goal itself (I'm sure that apart from the "nonlocal" one all of the above are viable, and I thus can get /something/ to work) -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019 at 8:21 AM R.Wieser wrote: > > Michael, > > > I note that you didn't answer the question, what are you trying > > to accomplish? > > I think I did - though implicitily. What do normal people use "by > reference" arguments for ? Yep, that is what I wanted too. > That doesn't really answer the question. It's like you just bought a self-driving car and then ask people how you push the accelerator pedal. What are you trying to do? Well, what normal people use the accelerator pedal for! Only, that's irrelevant. The point of your new car isn't to push the pedal - it's to get you some place. Where are you trying to get to? ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Michael, > I note that you didn't answer the question, what are you trying > to accomplish? I think I did - though implicitily. What do normal people use "by reference" arguments for ? Yep, that is what I wanted too. > It looks to me like you're trying to write a program in a different > language here, not Python. I'm trying to learn how Python works, and for that I (ofcourse) compare it to other languages. What-and-how it does something different (or equal!) in regard to them. >Although come to that I can't think of very many reasons to do > what you propose in any language. I made propositions to its functioning ?And I was thinking that I just pointed out oddities in it ... > If you mentioned what problem you are trying to solve 1) Have value 2) use value in procedure 1 3) use updated value in procedure 2 4) use again updated value in procedure 1, 2 or maybe 3 For the sake of learning I'm now going over all of the possibilities to see if and how they work. For that I've already excluded globals and the practice of feeding the value as an argument to the procedure and than store its result as the new one. I've also excluded using a class object and put the code in there, as well as faking a "by reference" passing by using a tuple. "nonlocal" looked to be another option, but it appears to be rather limited in its application. In short, the /ways to the goal/ are (currently) important to me, not the goal itself (I'm sure that apart from the "nonlocal" one all of the above are viable, and I thus can get /something/ to work) Yeah, I'm weird like that. Sorry. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019 at 7:19 AM Michael Torrie wrote: > > On 11/14/19 10:57 AM, R.Wieser wrote: > >> I know of no sane way that a function could work with the scope of > >> any arbitrary caller. > > > > The trick seems to be to emulate a "by reference" call, by using a mutable > > object as the argument and stuff the value inside of it (IIRC a tuple with a > > single element). > > Right. You could pass in a dict as an argument. You could even pass in > the caller's locals() dictionary. I'm not sure I recommend the latter > approach, however. The locals() dict isn't guaranteed to be mutable. At the moment, there are very very few actual language guarantees regarding changes to locals(), but there's currently a WIP to define things a little more tightly: https://www.python.org/dev/peps/pep-0558/ Neither in the current wording nor in the proposed wording is any sort of promise that you could pass locals() to another function and have it usefully modify that. > I'm coming more and more around to some of the ideas of functional > programming. Doing as you suggest, reaching back to the caller's > variables, sounds extremely messy to me. And very fragile, hard to > test, and doesn't lend itself to easily extended functionality by > chaining(think unix-style piping). > > I find Python's ability to return tuples virtually eliminates any need I > have to "pass by reference." Agreed. Or Python's ability to return strings. Most of the pass-by-reference that I do in languages like SourcePawn is just to get around the problem that strings aren't first-class values. > I'm coming around to the idea that wherever possible, functions should > have no side effects. Those things that need side effects should be > isolated so they are easy to maintain. I believe they call this "push > side effects to the edges." Something like that. Ideally, a function should be pure - having no side effects, being unaffected by external state, and having a return value determined entirely by its arguments. Not every function can be pure, of course (for instance, print() is most certainly NOT a pure function), but the more of your functions that are pure, and the purer your other functions are, the easier it is to reason about your code and refactor things. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 10:57 AM, R.Wieser wrote: > The trick seems to be to emulate a "by reference" call, by using a mutable > object as the argument and stuff the value inside of it (IIRC a tuple with a > single element). I note that you didn't answer the question, what are you trying to accomplish? In other words, what problem are you trying to solve. It looks to me like you're trying to write a program in a different language here, not Python. Although come to that I can't think of very many reasons to do what you propose in any language. If you mentioned what problem you are trying to solve, I'm sure folks can suggest cleaner, more idiomatic ways of doing it in Python. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 10:57 AM, R.Wieser wrote: >> I know of no sane way that a function could work with the scope of >> any arbitrary caller. > > The trick seems to be to emulate a "by reference" call, by using a mutable > object as the argument and stuff the value inside of it (IIRC a tuple with a > single element). Right. You could pass in a dict as an argument. You could even pass in the caller's locals() dictionary. I'm not sure I recommend the latter approach, however. > Handle it the same as any other mistake, and throw an error ? Sure. I'm coming more and more around to some of the ideas of functional programming. Doing as you suggest, reaching back to the caller's variables, sounds extremely messy to me. And very fragile, hard to test, and doesn't lend itself to easily extended functionality by chaining(think unix-style piping). I find Python's ability to return tuples virtually eliminates any need I have to "pass by reference." I'm coming around to the idea that wherever possible, functions should have no side effects. Those things that need side effects should be isolated so they are easy to maintain. I believe they call this "push side effects to the edges." -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/2019 12:53 PM, Richard Damon wrote: On Nov 14, 2019, at 12:20 PM, R.Wieser wrote: MRAB, 'nonlocal' is used where the function is nested in another function The problem is that that was not clear to me from the description - nor is it logical to me why it exludes the main context from its use. Regards, Rudy Wieser Module ‘main’ content is already available via ‘global’, nonlocal was likely added later to get to enclosing function scope, which isn’t global, nor is it local. Correct, and the addition was in two stages. At first, automatically *accessing* non-locals was added. Note that no declaration is needed, just as no declaration is needed to access globals. >>> >>> f(3) 3 The 'nonlocal' keyward to *rebind* nonlocals, analogous to the 'global' keyword to rebind module globals, was added later, for 3.0, after considerable bikeshedding on the new keyword. The access mechanism is quite different. Function f accesses globals through f.__globals__, which points to the global dict. In CPython, at least, it accesses nonlocals through f.__closure__, a tuple of 'cells'. >>> def f(a): b = 'b outer' def g(): nonlocal b print(a, b) b = 'b inner' print(a, b) print(g.__closure__) g() >>> f(0) (, at 0x0277AAAF7880: str object at 0x0277AAB0DAB0>) 0 b outer 0 b inner >>> print(f.__closure__) None Closures are used in functional programs, instead of classes, to create 'groups' of functions than share 'group' variables. -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Fri, Nov 15, 2019 at 5:46 AM R.Wieser wrote: > > Richard, > > > Assuming that one language works like another is a danger > > Abitrarily redefining words and using misnomers is another ... ("global" > and "nonlocal" respecivily if you wonder) Every language that has a concept of "global" still has some sort of limitation on it. If you look up that word in a dictionary, it won't say "within the currently-running program" or anything. Yet, we programmers are quite happy for global variables in one program to be isolated from another - in fact, I think you'd be seriously disconcerted if that were NOT the case. Is that "arbitrarily redefining" the word global? > > First, Python doesn't really have 'Variables' like a lot of other > > languages > > (they don't hold a bag of bytes), as Python names don't hold values, but > > are just references to objects which actually hold the value > > That's a principle as old as programming languages itself I believe. True, and it's also largely irrelevant here, so let's move on. > > If the name is never bound to something, then the name will be also looked > > for in the global namespace. > > Can you give an example of that ?I currently cannot wrap my head around > what you could be meaning there - anything I can imagine simply doesn't make > any sense ... > def foo(): x = 1 print("x is", x) Inside this function, you have one local name (x), and one name reference that isn't local (print). When the function looks for print, it looks in the globals, and then in the built-ins. ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Richard, > Assuming that one language works like another is a danger Abitrarily redefining words and using misnomers is another ... ("global" and "nonlocal" respecivily if you wonder) > First, Python doesn't really have 'Variables' like a lot of other > languages > (they don't hold a bag of bytes), as Python names don't hold values, but > are just references to objects which actually hold the value That's a principle as old as programming languages itself I believe. > If the name is never bound to something, then the name will be also looked > for in the global namespace. Can you give an example of that ?I currently cannot wrap my head around what you could be meaning there - anything I can imagine simply doesn't make any sense ... Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
> On Nov 14, 2019, at 12:56 PM, R.Wieser wrote: > > Jan, > >> So what you want to do is dynamic scope? > > No, not really.I was looking for method to let one procedure share a > variable with its caller - or callers, selectable by me. And as a "by > reference" argument does not seem to exist in Python ... > > And yes, I am a ware that procedures can return multiple results. I just > didn'want to go that way (using the same variable twice in a single > calling). > > Regards, > Rudy Wieser Watch out about thinking about ‘Variables’ because Python doesn’t really have them. In one sense EVERYTHING in Python is by reference, as names are just references bound to objects. If you are pass a mutable object to a function, and the function uses the parameter that was bound to the object to mutate the object, that same object referenced in the caller has changed. (Note that strings, number, and tupples are not mutable, but lists, dictionaries and most class objects are). The key is that the function should use assignment to the parameter name to try and change the object, but use mutating methods on the object to change it. Thus if the caller creates a list and binds it to a name, and passes that to the function, then the function can manipulate the list (things like parm[0] = 5) and that change will be see by the caller. The function just needs to be careful not to do a parm = statement that would rebind the name and thus lose the reference to the callers object. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 14/11/2019 17:11, R.Wieser wrote: Rhodri, MyVar is a global here, so nonlocal explicitly doesn't pick it up. I do not agree with you there (the variable being global). If it where than I would have been able to alter the variable inside the procedure without having to resort to a "global" override (an override which is only valid for the context its used in by the way, not anywhere else) Than again, that is how it works in a few other languages, so I might have been poisonned by them.:-) You have been. # This is at the top level of a module # I.e. it's a global variable my_global_variable = 5 # You can read globals from within a function without declaring them def show_my_global(): print(my_global_variable) # If you try setting it, you get a local instead def fudge_my_global(n): my_global_variable = n show_my_global() # prints '5' fudge_my_global(2) show_my_global() # prints '5' # If you read the variable before setting it, you get an exception def mess_up_my_global(n): print(my_global_variable) my_global_variable = n mess_up_my_global(2) # UnboundLocalError! # ...because it must be a local because of the assignment, but it # doesn't have a value at the time print() is called. # To do it right, declare you want the global from the get go def love_my_global(n): global my_global_variable print("It was ", my_global_variable) my_global_variable = n love_my_global(3) # prints 'It was 5' show_my_global() # prints '3' -- Rhodri James *-* Kynesim Ltd -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Michael, > nonlocal does not share or use its *caller's* variables. Rather it > reaches into the scope of the outer function where it was defined. > That's a very different concept than what you're proposing. Oh blimy! You're right.Its an at compile-time thing, not a runtime one. Thanks for the heads-up. > I know of no sane way that a function could work with the scope of > any arbitrary caller. The trick seems to be to emulate a "by reference" call, by using a mutable object as the argument and stuff the value inside of it (IIRC a tuple with a single element). > What would happen if the caller's scope didn't have any > names that the function was looking for? Handle it the same as any other mistake, and throw an error ? Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
> > On Nov 14, 2019, at 12:20 PM, R.Wieser wrote: > > MRAB, > >> 'nonlocal' is used where the function is nested in another function > > The problem is that that was not clear to me from the description - nor is > it logical to me why it exludes the main context from its use. > > Regards, > Rudy Wieser Module ‘main’ content is already available via ‘global’, nonlocal was likely added later to get to enclosing function scope, which isn’t global, nor is it local. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Jan, > So what you want to do is dynamic scope? No, not really.I was looking for method to let one procedure share a variable with its caller - or callers, selectable by me. And as a "by reference" argument does not seem to exist in Python ... And yes, I am a ware that procedures can return multiple results. I just didn'want to go that way (using the same variable twice in a single calling). Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On Nov 14, 2019, at 12:18 PM, R.Wieser wrote: > > Rhodri, > >> MyVar is a global here, so nonlocal explicitly doesn't pick it up. > > I do not agree with you there (the variable being global). If it where than > I would have been able to alter the variable inside the procedure without > having to resort to a "global" override (an override which is only valid for > the context its used in by the way, not anywhere else) > > Than again, that is how it works in a few other languages, so I might have > been poisonned by them. :-) > > Regards, > Rudy Wieser Assuming that one language works like another is a danger. It really pays to learn the base concepts of a language if you are going to be using it. First, Python doesn’t really have ‘Variables’ like a lot of other languages (they don’t hold a bag of bytes), as Python names don’t hold values, but are just references to objects which actually hold the value (this can be important when several names all reference the same object, that means that if you mutate the object through one name they all see the change) Also, for name lookup, the Python Compiler looks to see if the name is bound to an object (via assignment, etc) in the function, if so the name is by default local, (changeable by using a global or non local statement). If the name is never bound to something, then the name will be also looked for in the global namespace. Yes, this is different than many other languages. -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
MRAB, > 'nonlocal' is used where the function is nested in another function The problem is that that was not clear to me from the description - nor is it logical to me why it exludes the main context from its use. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Rhodri, > MyVar is a global here, so nonlocal explicitly doesn't pick it up. I do not agree with you there (the variable being global). If it where than I would have been able to alter the variable inside the procedure without having to resort to a "global" override (an override which is only valid for the context its used in by the way, not anywhere else) Than again, that is how it works in a few other languages, so I might have been poisonned by them. :-) Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 11/14/19 7:15 AM, R.Wieser wrote: > Too bad though, it means that procedures that want to share/use its callers > variables using nonlocal can never be called from main. And that a caller > of a procedure using nonlocal cannot have the variable declared as global > (just tested it). nonlocal does not share or use its *caller's* variables. Rather it reaches into the scope of the outer function where it was defined. That's a very different concept than what you're proposing. I know of no sane way that a function could work with the scope of any arbitrary caller. Remember that even inner functions can be returned and called from anywhere, even other functions or modules. What would happen if the caller's scope didn't have any names that the function was looking for? What are you trying to accomplish? -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 14 Nov 2019, at 15:15, R.Wieser wrote: Too bad though, it means that procedures that want to share/use its callers variables using nonlocal can never be called from main. And that a caller of a procedure using nonlocal cannot have the variable declared as global (just tested it). So what you want to do is dynamic scope? https://www.geeksforgeeks.org/static-and-dynamic-scoping/ = jem -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
Jan, > The nonlocal statement causes the listed identifiers to refer to > previously bound variables in the nearest **enclosing scope excluding > globals**. I read that too, but didn't get from it that the main scope is excluded (I assumed the"excluding globals" was ment at as such declared variables) . Thanks the clarification. Too bad though, it means that procedures that want to share/use its callers variables using nonlocal can never be called from main. And that a caller of a procedure using nonlocal cannot have the variable declared as global (just tested it). Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 14/11/2019 13:06, R.Wieser wrote: Hello all, I've just tried to use a "nonlocal MyVar" statement in a procedure defenition, but it throws an error saying "Syntax error: no binding for nonlocal 'MyVar' found. According to platform.python_version() I'm running version 3.8.3 Why am I getting that error ? (already googeled ofcourse) Testcode: - - - - - - - - - - - - Def Proc1() nonlocal MyVar MyVar = 5 MyVar = 7 Proc1() print(MyVar) - - - - - - - - - - - - I've also tried moving "MyVar = 7" to the first line, but that doesn't change anything. Using "global MyVar" works.. The Language Reference says (https://docs.python.org/3/reference/simple_stmts.html#the-nonlocal-statement): "The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope *excluding globals.*" (my emphasis.) MyVar is a global here, so nonlocal explicitly doesn't pick it up. -- Rhodri James *-* Kynesim Ltd -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 2019-11-14 13:06, R.Wieser wrote: Hello all, I've just tried to use a "nonlocal MyVar" statement in a procedure defenition, but it throws an error saying "Syntax error: no binding for nonlocal 'MyVar' found. According to platform.python_version() I'm running version 3.8.3 Why am I getting that error ? (already googeled ofcourse) Testcode: - - - - - - - - - - - - Def Proc1() nonlocal MyVar MyVar = 5 MyVar = 7 Proc1() print(MyVar) - - - - - - - - - - - - I've also tried moving "MyVar = 7" to the first line, but that doesn't change anything. Using "global MyVar" works.. In section 7.13 of the Help it says: """The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest enclosing scope excluding globals.""" 'nonlocal' is used where the function is nested in another function and you want to be able to bind to the variables in the enclosing function. In your code, there's no enclosing function. Instead, you want to be able to bind to the module's global variables. For that, you should use 'global' instead. def Proc1(): global MyVar MyVar = 5 MyVar = 7 Proc1() print(MyVar) -- https://mail.python.org/mailman/listinfo/python-list
Re: nonlocal fails ?
On 14 Nov 2019, at 14:06, R.Wieser wrote: I've also tried moving "MyVar = 7" to the first line, but that doesn't change anything. Using "global MyVar" works.. Try def outer(): MyVar = 10 def Proc1(): nonlocal MyVar MyVar = 5 Proc1() MyVar = 7 outer() print(MyVar) From the documentation The nonlocal statement causes the listed identifiers to refer to previously bound variables in the nearest **enclosing scope excluding globals**. This is important because the default behavior for binding is to search the local namespace first. The statement allows encapsulated code to rebind variables outside of the local scope besides the global (module) scope. Names listed in a nonlocal statement, unlike those listed in a global statement, must refer to pre-existing bindings in an enclosing scope (the scope in which a new binding should be created cannot be determined unambiguously). Names listed in a nonlocal statement must not collide with pre-existing bindings in the local scope. -- https://mail.python.org/mailman/listinfo/python-list
nonlocal fails ?
Hello all, I've just tried to use a "nonlocal MyVar" statement in a procedure defenition, but it throws an error saying "Syntax error: no binding for nonlocal 'MyVar' found. According to platform.python_version() I'm running version 3.8.3 Why am I getting that error ? (already googeled ofcourse) Testcode: - - - - - - - - - - - - Def Proc1() nonlocal MyVar MyVar = 5 MyVar = 7 Proc1() print(MyVar) - - - - - - - - - - - - I've also tried moving "MyVar = 7" to the first line, but that doesn't change anything. Using "global MyVar" works.. Regards, Rudy Wieser -- https://mail.python.org/mailman/listinfo/python-list