What other languages use the same data model as Python?

  • Thread starter Steven D'Aprano
  • Start date
S

Steven D'Aprano

Python is pass-by-value in a
meaningful sense, it's just that by saying that we say that the values
being passed are references/pointers. This is maybe one level of
abstraction below what's ideal,

"Maybe"?

Given the following statement of Python code:

what is the value of the variable x? Is it...?

(1) The string "spam".

(2) Some invisible, inaccessible, unknown data structure deep in the
implementation of the Python virtual machine, which the coder cannot
access in any way using pure Python code.

(Possibly a pointer, but since it's an implementation detail, other
implementations may make different choices.)

(3) Something else.


I argue that any answer except for (1) is (almost always) counter-
productive: it adds more confusion than shedding light. It requires
thinking at the wrong level, at the implementation level instead of the
level of Python code. If we define "value" to mean the invisible,
inaccessible reference, then that leaves no word to describe was the
string "spam" is.

(I say "almost always" counter-productive because abstractions leak, and
sometimes you do need to think about implementation.)

but Scheme, Java, etc. share this
terminology. (Ruby calls it pass-by-reference AFAIK.

The intellectual contortions that some people will go through to hammer
the square peg of actual programming language behaviour into the two
round holes of "pass by value" and "pass by reference" never cease to
astonish me.

Whatever, a rose by any other name...)

Do you really think that roses would be the symbol of romantic love if
they were called "disgusting stink-weeds of perversion and death"?

"How was the date last night?"
"Oh, it was marvelous! He presented me with a single red stink-weed, and
then we went to a disgusting little restaurant. I had the swill."

When people cannot agree on the definition of words, how can they
communicate? Pass by reference Ruby is completely different from the
older usage in Pascal, VB and other languages. Likewise, pass by value in
Java is completely different from that in older languages. Pass by
reference in Ruby, and pass by value in Java, describe the same thing.
What were these people thinking?
 
H

Hans Georg Schaathun

Eh, that example doesn't say what you think it does. It has the same
: behavior in C: http://ideone.com/Fq09N . Python is pass-by-value in a
: meaningful sense, it's just that by saying that we say that the values
: being passed are references/pointers.

No, Python is not pass-by-value, because the pointer is abstracted
away. You transmit arguments by reference only and cannot access the
value of the reference. In C it is pass by value, as the pointer
is explicit and do whatever you want with the pointer value.

So, even though you have the same mechanism in C and Python, they
do not have the same name. In the low-level C you only have pass
by value, but you can use the pointer syntax to do whatever you want
within pass by value. In the higher-level python, you do not have
the flexibility provided by explicit pointers, so you need to explain
the semantics without having a pointer concept defined a priori.

: This is maybe one level of
: abstraction below what's ideal, but Scheme, Java, etc. share this
: terminology. (Ruby calls it pass-by-reference AFAIK. Whatever, a rose
: by any other name...)

Now, this is confusing, because the terminology is not universal and
hardly intuitive. What is called transmission by reference in a
Simula context (Bjørn Kirkerud's textbook on OO Programming with Simula
for instance) is called object sharing in Wikipedia. What Wikipedia
calls call by reference is transmission by name in the Simula context.
 
P

Paul Rubin

Steven D'Aprano said:
what is the value of the variable x? Is it...?
(1) The string "spam".

Python works about the same way as Lisp or Scheme with regard to this
sort of thing, and those languages have been described with quite a bit
of mathematical formality. So if you want a precise theoretical
treatment you might look at the Scheme report. It should be pretty
clear how it carries over to Python.
 
D

Devin Jeanpierre

"Maybe"?

Given the following statement of Python code:


what is the value of the variable x? Is it...?

(1) The string "spam".

(2) Some invisible, inaccessible, unknowndatastructure deep in the
implementation of the Python virtual machine, which the coder cannot
access in any way using pure Python code.

(Possibly a pointer, but since it's an implementation detail, other
implementations may make different choices.)

(3) Something else.

As I said, a pointer or reference.
I argue that any answer except for (1) is (almost always) counter-
productive: it adds more confusion than shedding light. It requires
thinking at the wrong level, at the implementation level instead of the
level of Python code. If we define "value" to mean the invisible,
inaccessible reference, then that leaves no word to describe was the
string "spam" is.

(I say "almost always" counter-productive because abstractions leak, and
sometimes you do need to think about implementation.)

I don't know why you want to argue that it's counter-productive when
all I said was that it was meaningful / worked.

I don't think of "pass-by-value" involving references as being an
implementation-level thing. It's a way of thinking about Python's
behavior: a model. There don't even need to be actual references or
anything resembling them inside the implementation in order to apply
the model (for example, we probably all accept that Python could be
implemented using a turing machine, which lacks references/pointers).

Also, the word you suspected did not exist is "object". So if we have
var = "spam", var is a variable containing a reference to the object
"spam". Alternatively, it's a handle for the object "spam". I think
that's the call-by-sharing terminology, anyway.
The intellectual contortions that some people will go through to hammer
the square peg of actual programming language behaviour into the two
round holes of "pass by value" and "pass by reference" never cease to
astonish me.

It isn't particularly contorted. I learned Python this way and it
makes perfect sense. It's just perhaps one level of abstraction away
from the ideal of what some programmers would think in. Python's "pass-
by-value" conforms exactly to the "pass-by-value" of other languages
such as C. The only twist is that you never get to dereference
pointers in Python, but you can in C. Not much of a twist if you ask
me, but then again, I've been thinking in this model for years. Maybe
I'm brainwashed. :)
Do you really think that roses would be the symbol of romantic love if
they were called "disgusting stink-weeds of perversion and death"?

"How was the date last night?"
"Oh, it was marvelous! He presented me with a single red stink-weed, and
then we went to a disgusting little restaurant. I had the swill."

Please don't argue with me in this manner. The point is that words
don't matter, the meaning behind them does. As long as it's clear
what's meant, and what's meant is internally-consistent, I don't have
much problem with it. Of course, this is a rule of thumb and you could
draw extreme scenarios where it just becomes a bother.

Devin Jeanpierre
 
D

Devin Jeanpierre

:  Eh, that example doesn't say what you think it does. It has the same
:  behavior in C:http://ideone.com/Fq09N. Python is pass-by-value in a
:  meaningful sense, it's just that by saying that we say that the values
:  being passed are references/pointers.

No, Python is not pass-by-value, because the pointer is abstracted
away.  You transmit arguments by reference only and cannot access the
value of the reference.  In C it is pass by value, as the pointer
is explicit and do whatever you want with the pointer value.  

The same argument applies to every language I know but two, all of
which describe themselves as pass-by-value. What you say certainly has
a consistency to it, it's just at odds with how I generally see the
term being applied. Forgive me if I don't share the same definition as
you, even if I do appreciate its elegance.

Devin Jeanpierre
 
H

Hans Georg Schaathun

I don't think of "pass-by-value" involving references as being an
: implementation-level thing. It's a way of thinking about Python's
: behavior: a model. (...)
: It isn't particularly contorted. I learned Python this way and it
: makes perfect sense. It's just perhaps one level of abstraction away
: from the ideal of what some programmers would think in. Python's "pass-
: by-value" conforms exactly to the "pass-by-value" of other languages
: such as C.

It is contorted and implementation-level because it is one level below
the abstraction assumed by the language. It only works by assuming
knowledge of C, which is language which has proved unsuitable for
complex and abstract data modelling. Digging down into C should be
unnecessary to explain Python.

By calling it pass-by-value you introduce a new data type which is
unknown to Python, namely the pointer.

: The only twist is that you never get to dereference
: pointers in Python, but you can in C. Not much of a twist if you ask
: me, but then again, I've been thinking in this model for years. Maybe
: I'm brainwashed. :)

You are. You explain Python in terms of C. That's useful when you
talk to other speakers of C.

If you want to explain the language to a broader audience, you should
use terminology from the language's own level of abstraction.
 
M

Michael Torrie

def identify_call (a_list):
a_list[0] = "If you can see this, you don't have call-by-value"
a_list = ["If you can see this, you have call-by-reference"]


The first one is a mistake. If it were pass-by-value, it would
assign the string to a list unseen by the caller -- i.e. a copy
of the caller's argument (same value, different object).
<snip>
Clearly Python has neither call-by-value nor call-by-reference.

Python uses a third mechanism.

Which is exactly what the code showed. The first one isn't a mistake.
You just read it wrong.
 
D

Devin Jeanpierre

: The only twist is that you never get to dereference
: pointers in Python, but you can in C. Not much of a twist if you ask
: me, but then again, I've been thinking in thismodelfor years. Maybe
: I'm brainwashed. :)

You are. You explain Python in terms of C. That's useful when you
talk to other speakers of C.

If you want to explain the language to a broader audience, you should
use terminology from the language's own level of abstraction.

No, I explained Python in terms of pointers/reference. I don't speak C
or come from a C background, I'm primarily a Python programmer. Also,
I don't agree with your notions of "should", I have seen it taught
this way to plenty of undergraduate students learning Python as their
first programming language, and they do fine. The precise notational
difference between sharing an object and copying a reference doesn't
matter, as long as you can draw a diagram of it and write/read code --
which they can, and they do fine.

I'm a bit uncomfortable with the vibe here. It's one thing for me to
self-deprecatingly suggest I'm brainwashed (with a smile), and another
for you to agree in complete seriousness.

Devin Jeanpierre
 
H

Hans Georg Schaathun

I'm a bit uncomfortable with the vibe here. It's one thing for me to
: self-deprecatingly suggest I'm brainwashed (with a smile), and another
: for you to agree in complete seriousness.

I am sorry. It was not meant to be an insult. I do think that you
sit tightly in a frame of reference which is obviously not the only
one appropriate, and IMNHO not the optimal one for the purpose.
"Brainwashed" was not a word I meant to take seriously. Apologies.

I should have cut the C reference too; the same frame of reference
could be adopted from any number of languages.

Note that it was not the use of references as a concept I objected to,
but that they might be passed by value. With the references being
purely abstract entities and not data objects, the idea that they
have values do not make sense. And pass-by-value where the value
is a reference is just confusing.
 
H

Hans Georg Schaathun

Sometimes, to explain Python, you need to dig down to the underlying
: hardware - even deeper than C, if you like.

Sometimes you may need to narrow down the scope and explain a particular
implementation of python with its hardware, OS, and interpreter.
However, explaining just python, you do not know what the underlying
hardware/OS/interpreter is, and digging down into it is not possible.

: And that's always going to
: be the way, because abstractions leak from time to time. Or I should
: say, they occasionally have confidential briefings with the press.
: Abstracting everything perfectly is neither possible nor desirable.

Sure, but every language assumes a certain level of abstraction, and
when the abstraction breaks the language fails to be unambiguous and/or
portable.
 
B

Benjamin Kaplan

No, I read "call-by-value" but it does not make a copy. Call-by-value
dictates a deep copy or copy-on-write. Python does neither. Python
pass a handle to the object, not a handle to a copy of the object. If
you want to see call-by-value in practice, take a look at MATLAB,
SciLab or Octave; or consider what C++ copy constructors do in
function calls with value types.

You missed a word in the sentence.

"If you can see this, you DON'T have call-by-value"
 
H

harrismh777

Hans said:
It only works by assuming
knowledge of C, which is language which has proved unsuitable for
complex and abstract data modelling.

That statement is untrue; evidenced by the very fact the CPython's
complex and abstract data modeling has been very suitably handled by C.
You cannot possibly mean what you have asserted... I realize there
must be a contextual problem. I have been handling complex data
abstractions with C for more than 20 years... its quite well suited to
the task... although, I am able to do my research today faster and with
less lines of code in CPython. That does not in any way impugn C..;.
quite the contrary, given enough time, C is better suited for modeling
on a von Neumann processor, period.

Here is the thing that everyone forgets... all we have to work with
is a von Neumann processor. (same as EDVAC, ENIAC, the VIC20, etc).
Assembler is still the best language on that processor. 'C' is still
the best high-level language on that processor. CPython is implemented
in C for a reason: gcc and the von Neumann processor make it a no-brainer.

Its silly to claim that one high-level language or another is better
suited to complex data abstraction... don't go there.

Digging down into C should be unnecessary to explain Python.


huh? You have to be kidding. Why do you suppose we want it to be
open-sourced? Use the force Luke, read the source. If you really
want to know how Python is working you *must* dig down into the C code
which implements it. The folks who document Python should be able to
tell us enough to know how to use the language, but to really 'know' you
need the implementation source.



kind regards,
m harris
 
H

harrismh777

Hans said:
In C it is pass by value, as the pointer
is explicit and do whatever you want with the pointer value.

You clearly are not a C programmer.

Most of my C data abstractions use dual circular linked lists of
pointers to structures of pointers. *All* of that is only ever passed
(at least in my programming) as references. My code almost never passes
data by value.

We do not consider passing a pointer as *by value* because its an
address; by definition, that is pass-by-reference. We are not passing
the *value* of the data, we are passing the memory location (the
reference) to the data. Pass by *value* on the other hand actually
places the *value* of the data item on the call stack as a parameter.

Much of this conversation has more to do with semantics.


kind regards,
m harris
 
B

Benjamin Kaplan

  That statement is untrue; evidenced by the very fact the CPython's complex
and abstract data modeling has been very suitably handled by C.
  You cannot possibly mean what you have asserted... I realize there must be
a contextual problem.  I have been handling complex data abstractions with C
for more than 20 years... its quite well suited to the task... although, I
am able to do my research today faster and with less lines of code in
CPython.  That does not in any way impugn C..;. quite the contrary, given
enough time,  C is better suited for modeling on a von Neumann processor,
period.

  Here is the thing that everyone forgets... all we have to work with is a
von Neumann processor. (same as EDVAC, ENIAC, the VIC20, etc). Assembler is
still the best language on that processor.  'C'  is still the best
high-level language on that processor.  CPython is implemented in C fora
reason:  gcc and the von Neumann processor make it a no-brainer.

CPython is implemented in C because that's the language chosen. Python
is also implemented in Java, C#, Python, and several other languages.
And it's not tied to the von Neumann architecture either. Only the
current implementations of it are.
  Its silly to claim that one high-level language or another is better
suited to complex data abstraction... don't go there.




  huh?   You have to be kidding. Why do you suppose we want it to be
open-sourced?   Use the force Luke, read the source.   If you really want to
know how Python is working you *must* dig down into the C code which
implements it.  The folks who document Python should be able to tell us
enough to know how to use the language, but to really 'know' you need the
implementation source.

Reading the CPython sources will show you how CPython works under the
hood, but it has nothing to do with how Python works. There are lots
of things that CPython does that "Python" does not. For instance, the
GIL is not a part of Python. Reference counting is not a part of
Python. Caching small integers and strings is not a part of Python.
Why not read the Jython sources instead of the CPython? It's the same
language, after all.
 
H

harrismh777

Please don't argue with me in this manner.

D'Aprano takes a little getting used to. He likes strawmen,
red-hearings, and the venerable bogus analogy. Just read around them, he
usually has some good points in there...


kind regards,
m harris
 
H

Hans Georg Schaathun

That statement is untrue; evidenced by the very fact the CPython's
: complex and abstract data modeling has been very suitably handled by C.

That's an implementation. Not modelling.

: You cannot possibly mean what you have asserted... I realize there
: must be a contextual problem. I have been handling complex data
: abstractions with C for more than 20 years...

I did not say that it is impossible. On the other hand, you are
clearly not talking about abstraction or modelling at all, but
rather about computation or data processing.

: its quite well suited to
: the task... although, I am able to do my research today faster and with
: less lines of code in CPython. That does not in any way impugn C..;.
: quite the contrary, given enough time, C is better suited for modeling
: on a von Neumann processor, period.

What has that got to do with abstraction?

: Here is the thing that everyone forgets... all we have to work with
: is a von Neumann processor. (same as EDVAC, ENIAC, the VIC20, etc).
: Assembler is still the best language on that processor. 'C' is still
: the best high-level language on that processor. CPython is implemented
: in C for a reason: gcc and the von Neumann processor make it a no-brainer.

Again, what has that got to do with abstraction?

: Its silly to claim that one high-level language or another is better
: suited to complex data abstraction... don't go there.

:
: > Digging down into C should be unnecessary to explain Python.
:
: huh? You have to be kidding. Why do you suppose we want it to be
: open-sourced?

Python is a /language/. The /implementation/ is may be open-source
(and may or may not be written in C).

: Use the force Luke, read the source. If you really
: want to know how Python is working you *must* dig down into the C code
: which implements it.

Except that whatever you learn by doing so is only valid for that one
interpreter.
 
H

harrismh777

Benjamin said:
CPython is implemented in C because that's the language chosen. Python
is also implemented in Java, C#, Python, and several other languages.

True enough. If I used Jython, I would want to take a look at those
sources... as well as the Java sources... which were wrtten in, um, C.
And it's not tied to the von Neumann architecture either. Only the
current implementations of it are.

Oh, yes they are. That is the $10,000,000 dollar problem... how to
extricate ourselves from the von Neumann processor. *Everthing* comes
down to that... its hilarious to hear folks talk about lambda the
ultimate (especially those guys on Lambda the Ultimate) when there is no
such thing until such time as we have lambda the hardware architecture.
As long as we are all constrained to funnel data through the von
Neumann ALU, that really is *all* that matters. Another way of saying
this is that no matter how sophisticated our high level coding gets, it
all has to be translated somehow one way or another into von Neumann
codes toggling 1's and 0's on and off in the registers of the von
Neumann ALU.

Reading the CPython sources will show you how CPython works under the
hood, but it has nothing to do with how Python works.

Not conceptually, but practically. For instance, for a C programmer
to see that Python's object references are C void pointers, tells the
newbie Python ( C programmer ) much about how Python considers
variables... as references... to objects.
There are lots
of things that CPython does that "Python" does not. For instance, the
GIL is not a part of Python. Reference counting is not a part of
Python. Caching small integers and strings is not a part of Python.

This is not something I was aware of... caching of small ints is
unique to CPython implementation only ?? I guess I'll have to go read
the "sources" of the other implementations to check that out... ;-)
Why not read the Jython sources instead of the CPython? It's the same
language, after all.

Yep. Agreed. .... on both counts.
 
G

Grant Edwards

Hans Georg Schaathun wrote:

You clearly are not a C programmer.

Most of my C data abstractions use dual circular linked lists of
pointers to structures of pointers. *All* of that is only ever passed
(at least in my programming) as references. My code almost never
passes data by value.

We do not consider passing a pointer as *by value* because its an
address; by definition, that is pass-by-reference.

No, it isn't. It's pass by value. The fact that you are passing a
value that is a pointer to another value is not relevent.

Pass by reference means that if I call

foo(x)

And foo looks like this:

foo(param)
param = 4

Then 'x' in the caller's namespace ends up set to 4.
We are not passing the *value* of the data, we are passing the memory
location (the reference) to the data.

You're pass a value. That value is a pointer to some other value.
Pass by *value* on the other hand actually places the *value* of the
data item on the call stack as a parameter.

C is pass by value.

if I call foo(x)

And this is foo:

void foo (float param)
{
param = 1.23
}

The value of x in the caller's namespace is not changed. If C used
pass by reference, x would change.
 
H

Hans Georg Schaathun

Hans Georg Schaathun wrote:
: > In C it is pass by value, as the pointer
: > is explicit and do whatever you want with the pointer value.
:
: You clearly are not a C programmer.

I am not really a programmer period. I am many things and run
into programming from many more angles than a typical programmer
does. And as to C, I no longer use C when I can avoid it (which
I can most but not all of the time).

A few words are missing though. C is semantically pass by value.
Always. But because you have pointers are data object, you can do
whatever you want with them, and pass a pointer by value. Thus you
can achieve the effect of transmission by reference or by name, if
you want to.

: Most of my C data abstractions use dual circular linked lists of
: pointers to structures of pointers. *All* of that is only ever passed
: (at least in my programming) as references. My code almost never passes
: data by value.

Not if you do not consider pointers as data, but C does, in the sense
that pointers can be manipulated in the same ways as any other kind of
data.

: We do not consider passing a pointer as *by value* because its an
: address; by definition, that is pass-by-reference. We are not passing
: the *value* of the data, we are passing the memory location (the
: reference) to the data. Pass by *value* on the other hand actually
: places the *value* of the data item on the call stack as a parameter.

That is a useful viewpoint, but it falls a bit short when you need
to explain how to deal with pointers to pointers to pointers. Pointers
in C are objects.

But mind you, I was not the one to suggested to refer to this
as pass by value. I was explaining why it makes more sense to
do so for C but not for Python.

You simply end up with different wordings if you try to explain how
C works, and how to model data in C. We can both be right, you know;
we are just addressing the issues at different levels of abstraction.

: Much of this conversation has more to do with semantics.

Of course. The concepts are used to explain the semantics of the
languages.
 
H

Hans Georg Schaathun

True enough. If I used Jython, I would want to take a look at those
: sources... as well as the Java sources... which were wrtten in, um, C.

And then, suddenly, you'll be developing code which fails on CPython
instead of code which fails on Jython. Except that it will still
fail on Jython too, unless you happen to have the right jvm.

Marvelous.

: Oh, yes they are. That is the $10,000,000 dollar problem... how to
: extricate ourselves from the von Neumann processor. *Everthing* comes
: down to that... its hilarious to hear folks talk about lambda the
: ultimate (especially those guys on Lambda the Ultimate) when there is no
: such thing until such time as we have lambda the hardware architecture.

The problem with your approach is that software development does not
scale. Assembly worked very well with a few 100 lines of codes half
a century ago. C and friends were a great step forward and reduced
the complexity to allow another magnitude of lines of codes. Then
came further languages further removed from von Neumann, but close
enough to human cognition to handle yet a magnitude or too.

Of course you can still gain useful understanding by studying assembly
or von Neumann, or the instruction set of the CPU you use. And in
some projects it may be an optimal strategy. However, there are
many skills necessary to make an efficient system and in many projects
assembly and hardware skills are far down the list.

Virtualisation is there to the cut costs of rethinking solutions for
multiple architectures. If you need to understand the implementation
to do your programming, you are in fact disregarding one of the most
significant achievements deployed in computing the last two decades.

: Not conceptually, but practically. For instance, for a C programmer
: to see that Python's object references are C void pointers, tells the
: newbie Python ( C programmer ) much about how Python considers
: variables... as references... to objects.

And of course, this is useful as /one/ way to consider python variables.
As long as one is aware that this is just an example, one approach out
of many, then it enhances understanding. If one blindly extrapolates
from one implementation, it enhances misunderstanding.
 

Ask a Question

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

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

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,143
Latest member
SterlingLa
Top