Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #70985 > unrolled thread
| Started by | Ned Batchelder <ned@nedbatchelder.com> |
|---|---|
| First post | 2014-05-06 16:31 -0400 |
| Last post | 2014-05-07 01:14 +0000 |
| Articles | 20 on this page of 67 — 16 participants |
Back to article view | Back to comp.lang.python
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: Pass variable by reference Ned Batchelder <ned@nedbatchelder.com> - 2014-05-06 16:31 -0400
Re: Pass variable by reference Mark H Harris <harrismh777@gmail.com> - 2014-05-06 16:00 -0500
Re: Pass variable by reference Ned Batchelder <ned@nedbatchelder.com> - 2014-05-06 17:27 -0400
Re: Pass variable by reference Chris Angelico <rosuav@gmail.com> - 2014-05-07 09:46 +1000
Re: Pass variable by reference Rustom Mody <rustompmody@gmail.com> - 2014-05-06 19:18 -0700
Re: Pass variable by reference Chris Angelico <rosuav@gmail.com> - 2014-05-07 12:39 +1000
Re: Pass variable by reference Rustom Mody <rustompmody@gmail.com> - 2014-05-06 19:54 -0700
Re: Pass variable by reference Steven D'Aprano <steve@pearwood.info> - 2014-05-07 04:59 +0000
Re: Pass variable by reference Mark H Harris <harrismh777@gmail.com> - 2014-05-07 13:11 -0500
Re: Pass variable by reference Marko Rauhamaa <marko@pacujo.net> - 2014-05-08 00:22 +0300
Values and objects [was Re: Pass variable by reference] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-08 01:08 +0000
Re: Values and objects [was Re: Pass variable by reference] Mark H Harris <harrismh777@gmail.com> - 2014-05-09 16:56 -0500
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-10 01:34 +0300
Re: Values and objects Ben Finney <ben@benfinney.id.au> - 2014-05-10 10:24 +1000
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-10 01:01 +0000
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-09 19:19 -0700
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-10 12:33 +1000
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-09 20:05 -0700
Re: Values and objects Mark H Harris <harrismh777@gmail.com> - 2014-05-09 23:15 -0500
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-10 06:15 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-10 17:21 +1000
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-10 09:09 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-10 19:32 +1000
Re: Values and objects Ethan Furman <ethan@stoneleaf.us> - 2014-05-10 12:10 -0700
Re: Values and objects MRAB <python@mrabarnett.plus.com> - 2014-05-10 20:22 +0100
Re: Values and objects Ethan Furman <ethan@stoneleaf.us> - 2014-05-10 12:28 -0700
Re: Values and objects Terry Reedy <tjreedy@udel.edu> - 2014-05-10 16:16 -0400
Re: Values and objects Terry Reedy <tjreedy@udel.edu> - 2014-05-10 16:24 -0400
Re: Values and objects Devin Jeanpierre <jeanpierreda@gmail.com> - 2014-05-10 14:03 -0700
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 03:17 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-11 13:30 +1000
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 05:11 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-11 15:22 +1000
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-10 22:31 -0700
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-11 09:21 +0300
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-10 23:48 -0700
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-11 18:10 +0300
Re: Values and objects Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2014-05-11 11:26 +0300
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-11 01:48 -0700
Re: Values and objects Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2014-05-11 15:22 +0300
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-11 18:46 +0300
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-11 22:56 +0300
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 12:51 +0000
Re: Values and objects Rustom Mody <rustompmody@gmail.com> - 2014-05-11 07:12 -0700
Re: Values and objects Ethan Furman <ethan@stoneleaf.us> - 2014-05-10 22:42 -0700
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 06:40 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-11 09:18 +1000
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 03:11 +0000
Re: Values and objects Rotwang <sg552@hotmail.co.uk> - 2014-05-11 14:46 +0100
Re: Values and objects Ned Batchelder <ned@nedbatchelder.com> - 2014-05-11 14:40 -0400
Re: Values and objects Rotwang <sg552@hotmail.co.uk> - 2014-05-12 00:06 +0100
Re: Values and objects Ethan Furman <ethan@stoneleaf.us> - 2014-05-10 18:28 -0700
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 07:24 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-11 11:59 +1000
Re: Values and objects Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-11 07:29 +0000
Re: Values and objects Ethan Furman <ethan@stoneleaf.us> - 2014-05-10 21:46 -0700
Re: [Python-Dev] Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-11 16:08 +1000
Re: Values and objects albert@spenarnc.xs4all.nl (Albert van der Horst) - 2014-05-17 14:26 +0000
Re: Values and objects Chris Angelico <rosuav@gmail.com> - 2014-05-10 11:58 +1000
Re: Values and objects Marko Rauhamaa <marko@pacujo.net> - 2014-05-10 10:57 +0300
Re: Values and objects Jussi Piitulainen <jpiitula@ling.helsinki.fi> - 2014-05-10 11:06 +0300
Re: Values and objects Dennis Lee Bieber <wlfraed@ix.netcom.com> - 2014-05-10 12:07 -0400
Re: Pass variable by reference Chris Angelico <rosuav@gmail.com> - 2014-05-08 11:31 +1000
Re: Pass variable by reference Mark H Harris <harrismh777@gmail.com> - 2014-05-09 17:30 -0500
Abstractions [was Re: Pass variable by reference] Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-10 00:58 +0000
Re: Abstractions [was Re: Pass variable by reference] Mark H Harris <harrismh777@gmail.com> - 2014-05-09 21:17 -0500
Re: Pass variable by reference Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-05-07 01:14 +0000
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-05-10 17:21 +1000 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9843.1399706518.18130.python-list@python.org> |
| In reply to | #71224 |
On Sat, May 10, 2014 at 4:15 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Sat, 10 May 2014 12:33:28 +1000, Chris Angelico wrote:
>> 1) Passing them as parameters. You can pass a pointer to a variable,
>> which is effectively the same as passing a variable to a function.
>
> No it is not. It is nothing like passing a variable to a function. You
> are passing a pointer, which is itself a value. True, it is a value which
> you, the author, gives meaning as a pointer to a variable, but that need
> not be the case. It might be a pointer to a part of an array, or a
> record, or to some random address in memory, or a dangling pointer. C
> allows you to perform arithmetic on pointers, which means you can
> construct pointers to nothing in particular.
I think at this point it's arguable, in that you can get so close to
"passing a variable to a function" that it doesn't really matter about
the distinction. But as I explained further down, it really just shows
that "patch of memory" can be passed around, and that a variable can
be backed by such a patch of memory.
> Rather than *creating* patches of memory, malloc merely allocates it from
> pre-existing memory.
I disagree. On a modern system with memory management, malloc can grab
memory from the system, thus making it available to your process.
Sure, physical memory will normally have to have been installed in the
system, but conceptually you could have a malloc function that
actually freezes the program, asks the user to build a new computer
and turn it on, connects to a new service on that computer, and
allocates memory from there. As far as your program's concerned,
malloc actually does (attempt to) give you more room than you had.
> Python variables aren't first-class either, but in fact we can get a bit
> closer to first-class than either C or Pascal.
>
> Creating new variables is trivial. Since they don't need to be declared,
> you create a new variable just by assigning to it:
>
> try:
> spam
> except NameError:
> spam = 23
No no no, this is really creating them at compile time. If you do this
inside a function, the name has to be created as a local name before
the function begins execution.
> There are at least two other ways:
>
> globals()['spam'] = 23
> exec('spam = 23')
With exec, you can do anything "at run time". Does that mean that, in
languages with an exec action, absolutely everything is first-class?
I'm not sure that that counts. Maybe I'm wrong.
Subscript-assigning to globals() is actually creating new
(module-level) variables, though. And if Python allowed you to assign
to locals() inside a function, then I would accept that local function
variables can be created and destroyed at run time, but you can't, so
local variables aren't first-class.
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-05-10 09:09 +0000 |
| Subject | Re: Values and objects |
| Message-ID | <536decca$0$29980$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #71228 |
On Sat, 10 May 2014 17:21:56 +1000, Chris Angelico wrote:
> On Sat, May 10, 2014 at 4:15 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> On Sat, 10 May 2014 12:33:28 +1000, Chris Angelico wrote:
>>> 1) Passing them as parameters. You can pass a pointer to a variable,
>>> which is effectively the same as passing a variable to a function.
>>
>> No it is not. It is nothing like passing a variable to a function. You
>> are passing a pointer, which is itself a value. True, it is a value
>> which you, the author, gives meaning as a pointer to a variable, but
>> that need not be the case. It might be a pointer to a part of an array,
>> or a record, or to some random address in memory, or a dangling
>> pointer. C allows you to perform arithmetic on pointers, which means
>> you can construct pointers to nothing in particular.
>
> I think at this point it's arguable, in that you can get so close to
> "passing a variable to a function" that it doesn't really matter about
> the distinction. But as I explained further down, it really just shows
> that "patch of memory" can be passed around, and that a variable can be
> backed by such a patch of memory.
No offence Chris, but I think this demonstrates that learning C causes
brain damage and prevents clear logical thinking :-P
You're not passing a variable to a function. You're passing a pointer,
which is itself a first-class value. It could be a pointer to ANYTHING,
or NOTHING at all -- C doesn't even promise to ensure that it is a valid
pointer, although more modern languages may. There's certainly no
guarantee that it's a pointer to a variable. And you cannot create new
variables -- C only allows variables to be created at compile time.
The question is not, "Can I implement some aspects of first-class
behaviour for variables by hand?" The question is, "Are variables treated
as first class values in C?"
If you asked, "Does Pascal have an exponentiation or power operator?",
and I answered "Sure it does! If you want to calculate x squared, you
just write x*x, if you want x cubed, write x*x*x, and if you want x to
the power of twelve, x*x*x*x*x*x*x*x*x*x*x*x" you would rightfully slap
me with a halibut. Being able to manually perform repeated multiplication
is not the same as having the language support exponentiation. To say
nothing of fractional exponents. "How about x to the power of one third?"
Being able to manually pass pointers to variables about is not the same
as having first class variables. It fails on the very first hurdle, "Are
variables treated the same as other values?"
How do I pass an int to a function? func(some_int)
How do I pass a double to a function? func(some_double)
How do I pass a bool to a function? func(some_bool)
How do I pass a variable to a function? ptr = &some_variable; func(ptr)
Does that look the same to you? The fact that you can do it at all is not
sufficient to make it first class. It just makes it a work-around for the
lack of first class variables in the language.
Personally, I don't imagine that there ever could be a language where
variables were first class values *exactly* the same as ints, strings,
floats etc. Otherwise, how could you tell the difference between a
function which operated on the variable itself, and one which operated on
the value contained by the value? The best you can do is for variables to
be "second class" -- you can do these things to them, but you need
special syntax or declarations to tell the compiler you're operating on
the variable rather than the variable's value. E.g. Pascal and Algol have
syntax for instructing the compiler when to pass a variable as a value,
and when to pass the value. C gives you nothing.
I would say that C variables are *third class*. There's no compiler
support for variables-as-values at all, but you can manually fake it a
bit by using pointers. There is no way to tell whether the pointer
actually points to a variable, and since arrays aren't first class
neither are pointer-to-arrays.
Algol and Pascal are *second class*, since the compiler does allow you to
pass variables as arguments (var parameters in Pascal, I forget what they
are called in Algol). Likewise, Python let's you create new variables at
runtime, or delete them, but you can't pass them around. But still,
you're quite limited in what the language does for you, compared to what
you have to do yourself:
x = 23
function("x", globals()) # See, I can pass a variable! Not.
>> Rather than *creating* patches of memory, malloc merely allocates it
>> from pre-existing memory.
>
> I disagree. On a modern system with memory management, malloc can grab
> memory from the system, thus making it available to your process. Sure,
> physical memory will normally have to have been installed in the system,
> but conceptually you could have a malloc function that actually freezes
> the program, asks the user to build a new computer and turn it on,
> connects to a new service on that computer, and allocates memory from
> there. As far as your program's concerned, malloc actually does (attempt
> to) give you more room than you had.
Ha, well I guess you got me there. Perhaps a less over the top example is
that you're running in a VM, and malloc can request more information from
the host (which presumably has unlimited memory). Still impractical, but
theoretically possible.
Nevertheless, blocks of memory are not *first class* because you don't
handle blocks of memory like other values. To make a new int variable,
you declare it: "int foo". To make a new block of memory, there is no
declaration "block foo". Rather, you call malloc() at runtime. And it
might fail. "int foo" can never fail.
>> Python variables aren't first-class either, but in fact we can get a
>> bit closer to first-class than either C or Pascal.
>>
>> Creating new variables is trivial. Since they don't need to be
>> declared, you create a new variable just by assigning to it:
>>
>> try:
>> spam
>> except NameError:
>> spam = 23
>
> No no no, this is really creating them at compile time.
It certainly isn't. Here's a slightly different demonstration of the same
principle, this time inside a function to prove that there's nothing
special about the global namespace:
py> def demo():
... print('spam' in locals())
... spam = 23
... print('spam' in locals())
...
py> demo()
False
True
> If you do this
> inside a function, the name has to be created as a local name before the
> function begins execution.
An implementation detail. CPython -- but not necessarily other Pythons --
use pre-allocated slots for local variables, but tries to hide this fact
from you (it *almost* succeeds too). But those pre-allocated slots can
represent unbound variables, i.e. variables which from the perspective of
Python code don't exist:
py> def demo2():
... spam = 23
... print('spam' in locals())
... del spam
... print('spam' in locals())
...
py> demo2()
True
False
If you peer under the hood of the CPython implementation, the slot still
exists, but that's invisible from Python, and just an implementation
detail. Other implementations may not even have slots at all.
>> There are at least two other ways:
>>
>> globals()['spam'] = 23
>> exec('spam = 23')
>
> With exec, you can do anything "at run time". Does that mean that, in
> languages with an exec action, absolutely everything is first-class? I'm
> not sure that that counts. Maybe I'm wrong.
No, you're right. That's why I said "Python variables aren't first-class
either". But they're less second class than C or Pascal.
> Subscript-assigning to globals() is actually creating new (module-level)
> variables, though. And if Python allowed you to assign to locals()
> inside a function, then I would accept that local function variables can
> be created and destroyed at run time, but you can't, so local variables
> aren't first-class.
See above.
--
Steven D'Aprano
http://import-that.dreamwidth.org/
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-05-10 19:32 +1000 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9847.1399714333.18130.python-list@python.org> |
| In reply to | #71240 |
On Sat, May 10, 2014 at 7:09 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> On Sat, 10 May 2014 17:21:56 +1000, Chris Angelico wrote:
>
> No offence Chris, but I think this demonstrates that learning C causes
> brain damage and prevents clear logical thinking :-P
>
> You're not passing a variable to a function. You're passing a pointer,
> which is itself a first-class value. It could be a pointer to ANYTHING,
> or NOTHING at all -- C doesn't even promise to ensure that it is a valid
> pointer, although more modern languages may. There's certainly no
> guarantee that it's a pointer to a variable. And you cannot create new
> variables -- C only allows variables to be created at compile time.
>
> The question is not, "Can I implement some aspects of first-class
> behaviour for variables by hand?" The question is, "Are variables treated
> as first class values in C?"
Ehh... good point. I admit my brain damage - which, I have to say, has
earned me a good portion of my life's salaries, so it's not useless :)
Okay. So variables are not first-class in C. I still think memory
blocks are pretty much first class, though; you can declare them at
compile time (usually as an array of char or pointers) or at run time
(with malloc or equivalent), and they can be passed to functions,
returned from functions, etc. The only limitation is that a generic
memory block doesn't maintain its size, so you can't distinguish
between a char[10] and a char[1024].
> Being able to manually pass pointers to variables about is not the same
> as having first class variables. It fails on the very first hurdle, "Are
> variables treated the same as other values?"
>
> How do I pass an int to a function? func(some_int)
>
> How do I pass a double to a function? func(some_double)
>
> How do I pass a bool to a function? func(some_bool)
>
> How do I pass a variable to a function? ptr = &some_variable; func(ptr)
>
> Does that look the same to you? The fact that you can do it at all is not
> sufficient to make it first class. It just makes it a work-around for the
> lack of first class variables in the language.
You can simply say func(&some_variable), but yes, there is that
difference. (This is how "out" parameters usually look in C. You stick
ampersands in front of things.) And that's still passing memory blocks
around, not variables.
>>> Rather than *creating* patches of memory, malloc merely allocates it
>>> from pre-existing memory.
>>
>> I disagree. On a modern system with memory management, malloc can grab
>> memory from the system, thus making it available to your process. Sure,
>> physical memory will normally have to have been installed in the system,
>> but conceptually you could have a malloc function that actually freezes
>> the program, asks the user to build a new computer and turn it on,
>> connects to a new service on that computer, and allocates memory from
>> there. As far as your program's concerned, malloc actually does (attempt
>> to) give you more room than you had.
>
> Ha, well I guess you got me there. Perhaps a less over the top example is
> that you're running in a VM, and malloc can request more information from
> the host (which presumably has unlimited memory). Still impractical, but
> theoretically possible.
Yeah. Completely impractical, but so is "Post-It Note Python" where
everything's done with physical strings and sheets of paper. Thought
experiments don't have to be performant :)
> Nevertheless, blocks of memory are not *first class* because you don't
> handle blocks of memory like other values. To make a new int variable,
> you declare it: "int foo". To make a new block of memory, there is no
> declaration "block foo". Rather, you call malloc() at runtime. And it
> might fail. "int foo" can never fail.
As I mentioned above, you can make a new block of memory with "char
foo[1234]". And that's where a lot of buffer overruns come from,
because someone thinks "1234 is *heaps* of space"... but sometimes you
really can know in advance how long something can be. (Maybe you're
about to ask a file to give you the next 1233 bytes of content.) In
this form, it's as safe as "int foo" - that is to say, safe unless
your stack overflows, in which case all bets are off anyway.
>>> Python variables aren't first-class either, but in fact we can get a
>>> bit closer to first-class than either C or Pascal.
>>>
>>> Creating new variables is trivial. Since they don't need to be
>>> declared, you create a new variable just by assigning to it:
>>>
>>> try:
>>> spam
>>> except NameError:
>>> spam = 23
>>
>> No no no, this is really creating them at compile time.
>
> It certainly isn't. Here's a slightly different demonstration of the same
> principle, this time inside a function to prove that there's nothing
> special about the global namespace:
>
>
> py> def demo():
> ... print('spam' in locals())
> ... spam = 23
> ... print('spam' in locals())
> ...
> py> demo()
> False
> True
Tell me, what may this function do in a compliant Python?
def demo():
ret = spam
spam = 23
return ret
In CPython, that'll raise UnboundLocalError, because the local
variable 'spam' does already exist, and currently has no value (no
object bound to it). If a compliant Python implementation is allowed
to have this return the value of a global or builtin spam, then I
would agree that you can create variables at run time. Is
demo.__code__.co_varnames a CPython implementation detail or part of
the language spec?
Ultimately, a variable name must be looked up somehow. If you can
create and destroy them inside an inner scope that shadows an outer
scope, then you should be able to shadow and unshadow them. Is there a
way to do this with exec? I tried this and it failed:
def demo():
print("spam =",spam)
exec("spam = 23")
print("spam =",spam)
exec("del spam")
print("spam =",spam)
CPython 3.4, each lookup of spam becomes a LOAD_GLOBAL, so each print
outputs the global value of spam. Is there a way to fiddle with this?
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2014-05-10 12:10 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9860.1399749029.18130.python-list@python.org> |
| In reply to | #71240 |
On 05/10/2014 02:32 AM, Chris Angelico wrote: > > Tell me, what may this function do in a compliant Python? > > def demo(): > ret = spam > spam = 23 > return ret > > In CPython, that'll raise UnboundLocalError, because the local > variable 'spam' does already exist, and currently has no value (no > object bound to it). No, it does not exist -- or, more accurately, it does not exist *yet* but will. The fact that there is a slot waiting for what will be spam is a cpython implementation detail. And if you don't like that argument (although it is a perfectly sound and correct argument), think of the module name space: ret = spam spam = 23 will net you a simple NameError, because spam has not yet been created. > If a compliant Python implementation is allowed > to have this return the value of a global or builtin spam, then I > would agree that you can create variables at run time. See module example above. This behavior is not allowed in functions for scope and sanity (mostly sanity) reasons. -- ~Ethan~
[toc] | [prev] | [next] | [standalone]
| From | MRAB <python@mrabarnett.plus.com> |
|---|---|
| Date | 2014-05-10 20:22 +0100 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9861.1399749735.18130.python-list@python.org> |
| In reply to | #71240 |
On 2014-05-10 20:10, Ethan Furman wrote: > On 05/10/2014 02:32 AM, Chris Angelico wrote: >> >> Tell me, what may this function do in a compliant Python? >> >> def demo(): >> ret = spam >> spam = 23 >> return ret >> >> In CPython, that'll raise UnboundLocalError, because the local >> variable 'spam' does already exist, and currently has no value (no >> object bound to it). > > No, it does not exist -- or, more accurately, it does not exist *yet* but will. The fact that there is a slot waiting > for what will be spam is a cpython implementation detail. > > And if you don't like that argument (although it is a perfectly sound and correct argument), think of the module name space: > > ret = spam > spam = 23 > > will net you a simple NameError, because spam has not yet been created. > > >> If a compliant Python implementation is allowed >> to have this return the value of a global or builtin spam, then I >> would agree that you can create variables at run time. > > See module example above. This behavior is not allowed in functions for scope and sanity (mostly sanity) reasons. > UnboundLocalError is like NameError, except that Python knows that the name is local because somewhere in the function you're binding to that name and you haven't said that it's global or nonlocal. Having a different exception for that case makes it clearer to the user what the problem is.
[toc] | [prev] | [next] | [standalone]
| From | Ethan Furman <ethan@stoneleaf.us> |
|---|---|
| Date | 2014-05-10 12:28 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9863.1399751488.18130.python-list@python.org> |
| In reply to | #71240 |
On 05/10/2014 12:22 PM, MRAB wrote: > > UnboundLocalError is like NameError, except that Python knows that the > name is local because somewhere in the function you're binding to that > name and you haven't said that it's global or nonlocal. Having a > different exception for that case makes it clearer to the user what the > problem is. Absolutely. At one point NameError was raised in both cases, which could be very confusing to track down. -- ~Ethan~
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2014-05-10 16:16 -0400 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9864.1399753025.18130.python-list@python.org> |
| In reply to | #71240 |
On 5/10/2014 3:10 PM, Ethan Furman wrote: > On 05/10/2014 02:32 AM, Chris Angelico wrote: >> >> Tell me, what may this function do in a compliant Python? >> >> def demo(): >> ret = spam >> spam = 23 >> return ret >> >> In CPython, that'll raise UnboundLocalError, Note: >>> issubclass(UnboundLocalError, NameError) True I am not sure if adding the specificity is helpful or not. >> because the local >> variable 'spam' does already exist, and currently has no value (no >> object bound to it). > > No, it does not exist -- or, more accurately, it does not exist *yet* > but will. The fact that there is a slot waiting for what will be spam > is a cpython implementation detail. > > And if you don't like that argument (although it is a perfectly sound > and correct argument), think of the module name space: > > ret = spam > spam = 23 > > will net you a simple NameError, because spam has not yet been created. In other words, those two lines raise a NameError in either case. -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2014-05-10 16:24 -0400 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9865.1399753484.18130.python-list@python.org> |
| In reply to | #71240 |
On 5/10/2014 3:22 PM, MRAB wrote: > UnboundLocalError is like NameError, More specifically, >>> isinstance(UnboundLocalError(), NameError) True This means that 'except NameError:' clauses written before the UnboundLocalError subclass was added still work and do not necessarily need to be modified. (I am allowing for the possibility that the body of the clause tries to separate the specific error from other NameErrors). -- Terry Jan Reedy
[toc] | [prev] | [next] | [standalone]
| From | Devin Jeanpierre <jeanpierreda@gmail.com> |
|---|---|
| Date | 2014-05-10 14:03 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9867.1399757236.18130.python-list@python.org> |
| In reply to | #71240 |
On Sat, May 10, 2014 at 12:10 PM, Ethan Furman <ethan@stoneleaf.us> wrote: > On 05/10/2014 02:32 AM, Chris Angelico wrote: >> >> >> Tell me, what may this function do in a compliant Python? >> >> def demo(): >> ret = spam >> spam = 23 >> return ret >> >> In CPython, that'll raise UnboundLocalError, because the local >> variable 'spam' does already exist, and currently has no value (no >> object bound to it). > > > No, it does not exist -- or, more accurately, it does not exist *yet* but > will. The fact that there is a slot waiting for what will be spam is a > cpython implementation detail. The name of the exception is "UnboundLocalError". And the message says that we referred to a "local variable". Also see the language reference: "When a name is not found at all, a NameError exception is raised. If the name refers to a local variable that has not been bound, a UnboundLocalError exception is raised. UnboundLocalError is a subclass of NameError." spam is referring to a local variable that has not been bound. This is not an implementation detail. > And if you don't like that argument (although it is a perfectly sound and > correct argument), think of the module name space: > > > ret = spam > spam = 23 > > will net you a simple NameError, because spam has not yet been created. Because module level variables work differently from local variables. -- Devin
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-05-11 03:17 +0000 |
| Subject | Re: Values and objects |
| Message-ID | <536eebc1$0$29980$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #71275 |
On Sat, 10 May 2014 14:03:11 -0700, Devin Jeanpierre wrote: > On Sat, May 10, 2014 at 12:10 PM, Ethan Furman <ethan@stoneleaf.us> > wrote: >> On 05/10/2014 02:32 AM, Chris Angelico wrote: >>> >>> >>> Tell me, what may this function do in a compliant Python? >>> >>> def demo(): >>> ret = spam >>> spam = 23 >>> return ret >>> >>> In CPython, that'll raise UnboundLocalError, because the local >>> variable 'spam' does already exist, and currently has no value (no >>> object bound to it). >> >> >> No, it does not exist -- or, more accurately, it does not exist *yet* >> but will. The fact that there is a slot waiting for what will be spam >> is a cpython implementation detail. > > The name of the exception is "UnboundLocalError". And the message says > that we referred to a "local variable". > > Also see the language reference: > > "When a name is not found at all, a NameError exception is raised. If > the name refers to a local variable that has not been bound, a > UnboundLocalError exception is raised. UnboundLocalError is a subclass > of NameError." > > spam is referring to a local variable that has not been bound. This is > not an implementation detail. Of course not. What is an implementation detail is that there is a slot waiting to be filled for it, just like Ethan said. It's the existence of pre-allocated slots for locals which is an implementation detail, not whether a name is treated as local or not. >> And if you don't like that argument (although it is a perfectly sound >> and correct argument), think of the module name space: >> >> >> ret = spam >> spam = 23 >> >> will net you a simple NameError, because spam has not yet been created. > > Because module level variables work differently from local variables. But that is an implementation detail. IronPython and Jython use an ordinary dict for local variable namespaces, just like globals. Consider this example from Jython: >>> spam = 9999 >>> def modify(namespace): ... namespace['spam'] = 42 ... >>> def demo(): ... modify(locals()) ... spam = spam ... return spam ... >>> demo() 42 -- Steven D'Aprano http://import-that.dreamwidth.org/
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-05-11 13:30 +1000 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9874.1399779013.18130.python-list@python.org> |
| In reply to | #71284 |
On Sun, May 11, 2014 at 1:17 PM, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote: > But that is an implementation detail. IronPython and Jython use an > ordinary dict for local variable namespaces, just like globals. Consider > this example from Jython: > >>>> spam = 9999 >>>> def modify(namespace): > ... namespace['spam'] = 42 > ... >>>> def demo(): > ... modify(locals()) > ... spam = spam > ... return spam > ... >>>> demo() > 42 All you're proving here is that, in some Pythons, locals() is writeable. What happens if you remove the "spam = spam" line? Would demo() not then return spam from the global scope, because the variable does not exist at local scope? Every example you've shown is simply giving a value to something that you've created by the normal method of having an assignment inside the function. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-05-11 05:11 +0000 |
| Subject | Re: Values and objects |
| Message-ID | <536f069b$0$29980$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #71285 |
On Sun, 11 May 2014 13:30:03 +1000, Chris Angelico wrote:
> On Sun, May 11, 2014 at 1:17 PM, Steven D'Aprano
> <steve+comp.lang.python@pearwood.info> wrote:
>> But that is an implementation detail. IronPython and Jython use an
>> ordinary dict for local variable namespaces, just like globals.
>> Consider this example from Jython:
>>
>>>>> spam = 9999
>>>>> def modify(namespace):
>> ... namespace['spam'] = 42
>> ...
>>>>> def demo():
>> ... modify(locals())
>> ... spam = spam
>> ... return spam
>> ...
>>>>> demo()
>> 42
>
> All you're proving here is that, in some Pythons, locals() is writeable.
> What happens if you remove the "spam = spam" line? Would demo() not then
> return spam from the global scope,
Yes, this. See my previous email, and take careful note of Rule #2: in
the absence of a binding operation, variables are not treated as local.
> because the variable does not exist at local scope?
No to this. Consider this example:
>>> spam = 9999
>>> def modify(namespace):
... namespace['spam'] = 42
...
>>> def demo2():
... assert 'spam' not in locals()
... modify(locals())
... assert 'spam' in locals()
... return spam
...
>>> demo2()
9999
This proves that the spam variable *does* exist in locals, but it is not
seen because the "return spam" doesn't check the local scope, so it sees
the global spam.
Sadly, the version of Jython I have doesn't provide a working dis module,
but if it did I expect it would show the equivalent of what CPython does:
the first version uses LOAD_FAST to look up "spam", and the second
version used LOAD_GLOBAL (a misnomer since it doesn't *just* look up
globals).
> Every example you've shown is simply giving a value to
> something that you've created by the normal method of having an
> assignment inside the function.
Nonsense. Look at the original examples again, more closely. Here they
are again, this time with comments:
def test():
if False: spam = None # Dead code, never executed.
d = locals()
d['spam'] = 23 # Not a normal assignment.
return spam
def test():
locals()['spam'] = 42 # Not a normal assignment.
return spam
spam = None # Dead code.
and from my reply to Devin:
def modify(namespace):
namespace['spam'] = 42
def demo():
modify(locals()) # Not an ordinary assignment.
spam = spam # Where does the initial value of spam come from?
return spam
The *only* purpose of the dead code in the two test() functions is to
force the compiler to use LOAD_FAST (or equivalent) rather than
LOAD_GLOBAL. But they aren't ever executed. At no time do I use normal
name binding assignment to create local variables. In the demo()
function, if I expand the line "spam = spam" out:
temp = spam # Look up of spam occurs first.
spam = temp # Binding occurs second.
the difficulty should be even more obvious. Where does the value of spam
come from before the binding?
The answer is that it comes from writing directly to the namespace (a
dict). There is no fixed slot for spam waiting for a value, because
Jython and IronPython don't use fixed slots. There's only a dict.
If we were using globals, it would be be more obvious what was going on,
and there would be no argument about whether or not a variable exists
before you give it a value. The answer would be, of course it doesn't
exist before it has a value. Python declarations (whether implicit or
explicit) don't create variables, they just instruct the compiler how to
perform lookups on them.
# Global scope
print spam # fails, because there is no spam variable yet
"spam" in globals() # returns False
globals()['spam'] = 42 # now it exists
spam = spam # a no-op
print spam
It's only because CPython is special, and locals() is special, that the
equivalent code is indeterminate inside functions.
--
Steven D'Aprano
http://import-that.dreamwidth.org/
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-05-11 15:22 +1000 |
| Subject | Re: Values and objects |
| Message-ID | <mailman.9875.1399785752.18130.python-list@python.org> |
| In reply to | #71288 |
On Sun, May 11, 2014 at 3:11 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Nonsense. Look at the original examples again, more closely. Here they
> are again, this time with comments:
>
> def test():
> if False: spam = None # Dead code, never executed.
> d = locals()
> d['spam'] = 23 # Not a normal assignment.
> return spam
>
> def test():
> locals()['spam'] = 42 # Not a normal assignment.
> return spam
> spam = None # Dead code.
>
>
> The *only* purpose of the dead code in the two test() functions is to
> force the compiler to use LOAD_FAST (or equivalent) rather than
> LOAD_GLOBAL.
In a C-like language, locals are created by a declaration, and
assigned a value separately. In Python, locals are created by the
presence of assignment within the function, which in simple cases
coincides with giving the value to it; but guarding the assignment
with "if False" prevents the giving of the value, while still being an
assignment for the sake of creating a local variable. Same if the
assignment happens further down, or even in the same statement ("spam
= spam"). It's still an assignment, so it has the declarative effect
of telling the compiler "this is now local, unless declared
global/nonlocal". It's that declaration that creates the variable, not
changing locals().
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-05-10 22:31 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <3fb2d95e-2fb6-43a5-a725-c6d38444b80c@googlegroups.com> |
| In reply to | #71289 |
On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote: > > Personally, I don't imagine that there ever could be a language where > variables were first class values *exactly* the same as ints, strings, > floats etc. Otherwise, how could you tell the difference between a > function which operated on the variable itself, and one which operated on > the value contained by the value? Its standard fare in theorem proving languages - see eg twelf: https://www.cs.cmu.edu/~fp/papers/cade99.pdf where the distinction is made between variables in the meta-language (ie twelf itself) and variables in the the object theory What you mean by *exactly* the same mean, I am not sure... Also I note that I was not meaning first-classness of variables in C in that literal sense. Its just I consider them more first-class than say Pascal but less than say Lisp. [The wikipedia link that Chris posted links to an article that makes the claim that firstclassness is not really defined but can be used in a vague/relative way ]
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2014-05-11 09:21 +0300 |
| Subject | Re: Values and objects |
| Message-ID | <87ppjksum0.fsf@elektro.pacujo.net> |
| In reply to | #71290 |
Rustom Mody <rustompmody@gmail.com>: > On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote: >> >> Personally, I don't imagine that there ever could be a language where >> variables were first class values *exactly* the same as ints, >> strings, floats etc. > > [...] > > What you mean by *exactly* the same mean, I am not sure... Lisp variables (symbols) are on an equal footing with other objects. IOW, lisp variables are objects in the heap. Marko
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-05-10 23:48 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <9d950f96-3457-4c13-b9e2-8e4e1b20cd54@googlegroups.com> |
| In reply to | #71297 |
On Sunday, May 11, 2014 11:51:59 AM UTC+5:30, Marko Rauhamaa wrote: > Rustom Mody : > > > > > On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote: > > >> > > >> Personally, I don't imagine that there ever could be a language where > >> variables were first class values *exactly* the same as ints, > >> strings, floats etc. > > > > [...] > > > > What you mean by *exactly* the same mean, I am not sure... > > > > Lisp variables (symbols) are on an equal footing with other objects. > IOW, lisp variables are objects in the heap. But is a symbol a variable?? Sure, by providing a data-structure symbol, lisp provides one of the key building blocks for developing language processing systems. However I would argue that a variable is not a merely a symbol (identifier in more usual programming language-speak) but a relation between identifiers/symbols and some 'rhs' For an (interpreted?) language like python, rhs is naturally value/object For a C like language it is memory. [Just invoking the standard denotational semantics fare: Env : Symbol → Value for interpreted languages For 'compiled' languages Env : Symbol → Location (at compile time) Store : Location → Value (at run time)
[toc] | [prev] | [next] | [standalone]
| From | Marko Rauhamaa <marko@pacujo.net> |
|---|---|
| Date | 2014-05-11 18:10 +0300 |
| Subject | Re: Values and objects |
| Message-ID | <87eh00s65j.fsf@elektro.pacujo.net> |
| In reply to | #71301 |
Rustom Mody <rustompmody@gmail.com>: > On Sunday, May 11, 2014 11:51:59 AM UTC+5:30, Marko Rauhamaa wrote: >> Lisp variables (symbols) are on an equal footing with other objects. >> IOW, lisp variables are objects in the heap. > > But is a symbol a variable?? Yes. A classic lisp symbol is even more "variable" than most other variables! It can hold *two* values. One is called a value binding and the other one the function binding. Scheme has unified the two; scheme symbols have only one value binding, which can be a function. > Sure, by providing a data-structure symbol, lisp provides one of the > key building blocks for developing language processing systems. > > However I would argue that a variable is not a merely a symbol > (identifier in more usual programming language-speak) but a relation > between identifiers/symbols and some 'rhs' The lisp symbol really is a data object with several fields: I can think of name, value, function and properties. They can be accessed with accessor functions. (Interestingly, scheme doesn't have the 'symbol-value accessor function of lisp's.) If lisp didn't have a way to rebind symbols (i.e., if it were purely functional and had no side effects), they wouldn't be so much variables as substitution spots in the code. > For an (interpreted?) language like python, rhs is naturally > value/object For a C like language it is memory. Symbols in lisp are memory slots, conceptually and physically. Marko
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2014-05-11 11:26 +0300 |
| Subject | Re: Values and objects |
| Message-ID | <qot4n0wd8la.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #71297 |
Marko Rauhamaa writes: > Rustom Mody: > > > On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote: > >> > >> Personally, I don't imagine that there ever could be a language > >> where variables were first class values *exactly* the same as > >> ints, strings, floats etc. > > > > [...] > > > > What you mean by *exactly* the same mean, I am not sure... > > Lisp variables (symbols) are on an equal footing with other objects. > IOW, lisp variables are objects in the heap. Only some, or only in quite old or special members of the family. But yes, I suppose when Lisp was still LISP, it was the kind of language that Steven fails to imagine in the quotation above. Variables really were symbols, which still are objects that can be passed around and stored in data structures. Or maybe not - wasn't the essential binding component (originally an "association list", later a more abstract "environment", called "namespace" in Python culture) separate from the symbol even then? Global bindings aside. But default in Common Lisp is lexical binding, and Scheme has only lexical bindings. An ordinary lexical variable is not an object in any reasonable sense that I can see. (let ((f (let ((x 3)) (lambda () x)))) ;; The binding of x is still relevant here but not in scope and not ;; accessible through the symbol x (funcall f)) ;==> 3 # That's (lambda f : f())((lambda x : (lambda : x))(3)) #=> 3 # Roughly, f = (lambda x : (lambda : x))(3) ; f() #=> 3
[toc] | [prev] | [next] | [standalone]
| From | Rustom Mody <rustompmody@gmail.com> |
|---|---|
| Date | 2014-05-11 01:48 -0700 |
| Subject | Re: Values and objects |
| Message-ID | <455a3dc0-c492-498b-9593-d30b8a967898@googlegroups.com> |
| In reply to | #71308 |
On Sunday, May 11, 2014 1:56:41 PM UTC+5:30, Jussi Piitulainen wrote: > Marko Rauhamaa writes: > > Rustom Mody: > > > > > On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote: > > >> > > >> Personally, I don't imagine that there ever could be a language > > >> where variables were first class values *exactly* the same as > > >> ints, strings, floats etc. > > > > > > > > [...] > > > > > > > > What you mean by *exactly* the same mean, I am not sure... > > > > > > Lisp variables (symbols) are on an equal footing with other objects. > > > IOW, lisp variables are objects in the heap. > > > Only some, or only in quite old or special members of the family. But > yes, I suppose when Lisp was still LISP, it was the kind of language > that Steven fails to imagine in the quotation above. Variables really > were symbols, which still are objects that can be passed around and > stored in data structures. Or maybe not - wasn't the essential binding > component (originally an "association list", later a more abstract > "environment", called "namespace" in Python culture) separate from the > symbol even then? Global bindings aside. > A symbol is a first-class data structure in any lisp (that I know) http://en.wikipedia.org/wiki/Homoiconicity is a defining characteristic of lisp Environments are first class in many schemes: http://sicp.ai.mit.edu/Fall-2004/manuals/scheme-7.5.5/doc/scheme_14.html (The '+'es there indicate its an MIT scheme extension; but its quite common) In my understanding a symbol can be called a variable only wrt some environment IOW there is no meaning to the word 'variable' without some notion of scope. I am not sure what your references to old and new lisps and static vs dynamic scope has to do with this. Or are you saying that in the 1960s lisps, a symbol was the string (name) along with its (dynamic binding) stack?? Python to qualify for this not only would the namespacing of locals have to be systematic with globals, the nesting structure of environments would have to be introspectively available as in the scheme example. Note the functions: environment-parent and environment-bound-names
[toc] | [prev] | [next] | [standalone]
| From | Jussi Piitulainen <jpiitula@ling.helsinki.fi> |
|---|---|
| Date | 2014-05-11 15:22 +0300 |
| Subject | Re: Values and objects |
| Message-ID | <qot61lcmrna.fsf@ruuvi.it.helsinki.fi> |
| In reply to | #71309 |
Rustom Mody writes:
> On Sunday, May 11, 2014 1:56:41 PM UTC+5:30, Jussi Piitulainen wrote:
> > Marko Rauhamaa writes:
> > > Rustom Mody:
> > >
> > > > On Saturday, May 10, 2014 2:39:31 PM UTC+5:30, Steven D'Aprano wrote:
> > > >>
> > > >> Personally, I don't imagine that there ever could be a
> > > >> language where variables were first class values *exactly*
> > > >> the same as ints, strings, floats etc.
> >
> > > > [...]
> >
> > > > What you mean by *exactly* the same mean, I am not sure...
> >
> > > Lisp variables (symbols) are on an equal footing with other
> > > objects. IOW, lisp variables are objects in the heap.
> >
> > Only some, or only in quite old or special members of the
> > family. But yes, I suppose when Lisp was still LISP, it was the
> > kind of language that Steven fails to imagine in the quotation
> > above. Variables really were symbols, which still are objects that
> > can be passed around and stored in data structures. Or maybe not -
> > wasn't the essential binding component (originally an "association
> > list", later a more abstract "environment", called "namespace" in
> > Python culture) separate from the symbol even then? Global
> > bindings aside.
>
> A symbol is a first-class data structure in any lisp (that I know)
> http://en.wikipedia.org/wiki/Homoiconicity is a defining characteristic of lisp
I don't see the relevance of these observations.
The claim was that Lisp variables are symbols. What do you write in
Common Lisp in place of the "..." to have the following evaluate to
the the value of the variable x?
(let ((x (f)) (y 'x)) (... y ...))
No, (eval y) is not an answer, and (symbol-value y) is not an answer:
these do not do the thing at all. To suggest (progn y x) is to concede
my point that there is no way to get the value of x through the symbol
x that is the value of y.
> Environments are first class in many schemes:
> http://sicp.ai.mit.edu/Fall-2004/manuals/scheme-7.5.5/doc/scheme_14.html
> (The '+'es there indicate its an MIT scheme extension; but its quite common)
It's not very common. A couple of top-level environment specifiers are
in the reports (scheme-report-environment, null-environment, and
interaction-environment is optional, if I recall correctly) but the
crucial reifier of an arbitrary lexical environment is not, and
environment specifiers can only be used as an argument to eval.
Even if that were common, it seems to me a joke to say that the symbol
itself is the variable, which is the claim that I responded to. It's
like saying that pairs of integers are first class variables because
they can be interpreted as lexical addresses wrt an environment. You
know, (0, 0) refers to the first variable in the current environment
frame, (3, 1) to the second variable in a specific ancestor frame, and
so on.
> In my understanding a symbol can be called a variable only wrt some
> environment
>
> IOW there is no meaning to the word 'variable' without some notion
> of scope.
Agreed.
So you consider it reasonable to say that variables are symbols in
Lisp, and then clarify that a symbol means a symbol together with a
first-class lexical environment, as if that was implicit in the
original claim (and as if such environments were widely available in
Lisp)?
If so, I admit I've been fooled, and I've spent far too much time on
this already. At least I was responding in good faith.
> I am not sure what your references to old and new lisps and static
> vs dynamic scope has to do with this.
I'm saying that lexical variables are not accessible through the
symbol that happens to look like the variable in the source code.
And I'm saying that it's the lexical variables that need to be
considered, because they are the default kind even in Lisp today.
Dynamic variables are special. (They are even _called_ special.)
I'm not saying that a dynamic variable cannot be accessed through the
symbol, because that doesn't seem to be true. (I installed a Common
Lisp and experimented a little when I wrote my original response.)
> Or are you saying that in the 1960s lisps, a symbol was the string
> (name) along with its (dynamic binding) stack??
It seems to be the case today, in Common Lisp, that a special variable
is accessible through the symbol. For example, (symbol-value y) would
work in my example above if x had been declared special. The dynamic
environment is implicit.
In the 1960s, before Scheme AFAIUI, things were that way.
> Python to qualify for this not only would the namespacing of locals
> have to be systematic with globals, the nesting structure of
> environments would have to be introspectively available as in the
> scheme example.
>
> Note the functions: environment-parent and environment-bound-names
If Marko meant MIT Scheme when he said Lisp, and reification of
arbitrary lexical environments when he said symbol, I've responded to
a quite different claim than he intended, and spent far too much
effort on this.
[toc] | [prev] | [next] | [standalone]
Page 2 of 4 — ← Prev page 1 [2] 3 4 Next page →
Back to top | Article view | comp.lang.python
csiph-web