I think we already have enough of C.
On 7/5/2024 3:09 AM, Keith Thompson wrote:
BGB <[email protected]> writes:
On 7/4/2024 8:05 PM, Lawrence D'Oliveiro wrote:[...]
It’s called “Rust”.
If anything, I suspect may make sense to go a different direction:
Not to a bigger language, but to a more narrowly defined language.
Basically, to try to distill what C does well, keeping its core
essence intact.
Goal would be to make it easier to get more consistent behavior across
implementations, and also to make it simpler to implement (vs an
actual C compiler); with a sub-goal to allow for implementing a
compiler within a small memory footprint (as would be possible for K&R
or C89).
Say for example:
Integer type sizes are defined;
Nominally, integers are:
Twos complement;
Little endian;
Wrap on overflow.
Dropped features:
VLAs
Multidimensional arrays (*1)
Bitfields
...
Simplified declaration syntax (*2):
{Modifier|Attribute}* TypeName Declarator
*1: While not exactly that rare, and can be useful, it is debatable if
they add enough to really justify their complexity and relative
semantic fragility. If using pointers, one almost invariably needs to
fall back to doing "arr[y*N+x]" or similar anyways, so it is arguable
that it could make sense to drop them and have people always do their
multidimensional indexing manually.
Note that multidimensional indexing via multiple levels of pointer
indirection would not be effected by this.
Multidimensional arrays in C are not a distinct language feature.
They are simply arrays of arrays, and all operations on them follow
from operations on ordinary arrays and pointers.
Are you proposing (in this hypothetical new language) to add
an arbitrary restriction, so that arrays can have elements of
arithmetic, pointer, struct, etc. type, but not of array type?
I'm not sure I see the point.
As-is, the multidimensional arrays require the compiler to realize that it needs to multiply one index by the product of all following indices.
So, say:
int a[4][4];
int j, k, l;
l=a[j][k];
Essentially needs to be internally translated to, say:
l=a[j*4+k];
Eliminating multidimensional arrays eliminates the need for this
translation logic, and the need to be able to represent this case in the typesystem handling logic (which is, as I see it, in some ways very
different from what one needs for a struct).
While eliminating structs could also simplify things; structs also tend to
be a lot more useful.
On 7/5/2024 6:20 AM, Ben Bacarisse wrote:
BGB <[email protected]> writes:
On 7/5/2024 3:09 AM, Keith Thompson wrote:How can it be eliminated? All your plan does is force me to wrap the
BGB <[email protected]> writes:
On 7/4/2024 8:05 PM, Lawrence D'Oliveiro wrote:[...]
It’s called “Rust”.
If anything, I suspect may make sense to go a different direction:
Not to a bigger language, but to a more narrowly defined language. >>>>>
Basically, to try to distill what C does well, keeping its core
essence intact.
Goal would be to make it easier to get more consistent behavior across >>>>> implementations, and also to make it simpler to implement (vs an
actual C compiler); with a sub-goal to allow for implementing a
compiler within a small memory footprint (as would be possible for K&R >>>>> or C89).
Say for example:
Integer type sizes are defined;
Nominally, integers are:
Twos complement;
Little endian;
Wrap on overflow.
Dropped features:
VLAs
Multidimensional arrays (*1)
Bitfields
...
Simplified declaration syntax (*2):
{Modifier|Attribute}* TypeName Declarator
*1: While not exactly that rare, and can be useful, it is debatable if >>>>> they add enough to really justify their complexity and relative
semantic fragility. If using pointers, one almost invariably needs to >>>>> fall back to doing "arr[y*N+x]" or similar anyways, so it is arguable >>>>> that it could make sense to drop them and have people always do their >>>>> multidimensional indexing manually.
Note that multidimensional indexing via multiple levels of pointer
indirection would not be effected by this.
Multidimensional arrays in C are not a distinct language feature.
They are simply arrays of arrays, and all operations on them follow
from operations on ordinary arrays and pointers.
Are you proposing (in this hypothetical new language) to add
an arbitrary restriction, so that arrays can have elements of
arithmetic, pointer, struct, etc. type, but not of array type?
I'm not sure I see the point.
As-is, the multidimensional arrays require the compiler to realize that it >>> needs to multiply one index by the product of all following indices.
So, say:
int a[4][4];
int j, k, l;
l=a[j][k];
Essentially needs to be internally translated to, say:
l=a[j*4+k];
Eliminating multidimensional arrays eliminates the need for this
translation logic, and the need to be able to represent this case in the >>> typesystem handling logic (which is, as I see it, in some ways very
different from what one needs for a struct).
inner array in a struct in order to get anything like the convenience of
the above:
struct a { int a[4]; };
struct a a[4];
l = a[j].a[k];
Most compilers with generate the same arithmetic (indeed exactly the
same code) for this as for the more convenient from that you don't like.
All you can do to eliminate this code generation is to make it so hard
to re-write the convenient code you dislike. (And yes, I used the same
name all over the place because you are forcing me to.)
It is not so much a dislike of multidimensional arrays as a concept, but rather, the hair they add to the compiler and typesystem.
Granted, one would still have other complex types, like structs and
function pointers, so potentially the complexity savings would be
limited.
While eliminating structs could also simplify things; structs also tend to >>> be a lot more useful.Indeed. And I'd have to use them for this!
Errm, the strategy I would assume is, as noted:
int a[4][4];
...
l=a[j][k];
Becomes:
int a[16];
...
l=a[j*4+k];
Much like what one would typically need to do anyways if the array was heap-allocated.
Though, the major goal for this sort of thing is mostly to try to limit the complexity required to write a compiler (as opposed to programmer convenience).
Like, for example, I had tried (but failed) to write a usable C compiler in less than 30k lines (and also ideally needing less than 4MB of RAM). But,
if the language design is simplified some, this might be a little
closer. Might still be doable, but a C compiler in 50-75k lines is much
less impressive.
On 7/5/2024 5:40 PM, Ben Bacarisse wrote:...
BGB <[email protected]> writes:
On 7/5/2024 6:20 AM, Ben Bacarisse wrote:
BGB <[email protected]> writes:
That's what you want to force me to write, but I can use and array ofWhile eliminating structs could also simplify things; structs also tend toIndeed. And I'd have to use them for this!
be a lot more useful.
Errm, the strategy I would assume is, as noted:
int a[4][4];
...
l=a[j][k];
Becomes:
int a[16];
...
l=a[j*4+k];
arrays despite your arbitrary ban on them by simply putting the array in
a struct.
IN most contexts, I don't really see how a struct is preferable to a multiply, but either way...
Whole language design is still a hypothetical at this point anyways (and my actual compiler does support multidimensional arrays).
On Fri, 05 Jul 2024 19:00:58 -0700, Keith Thompson wrote:
C assumes byte addressibility, but it doesn't assume that bytes are 8
bits.
The PDP-10 had 36-bit words and could operate on bit fields of any size
from 1 to 36 bits.
But it couldn’t address them.
Ben Bacarisse <[email protected]> writes:
BGB <[email protected]> writes:
On 7/5/2024 5:40 PM, Ben Bacarisse wrote:
[...]
Whole language design is still a hypothetical at this point anyways (and my >>> actual compiler does support multidimensional arrays).
Ah. I think that when you've written most of it, you will see that
ruling out arrays of arrays will have not simplifying effect.
Indeed. I believe (based on no direct experience) that you could write
a fully conforming C compiler without even thinking about
multidimensional arrays, and if you get the array code right, multidimensional arrays will just work.
On Fri, 05 Jul 2024 19:00:58 -0700, Keith Thompson wrote:
C assumes byte addressibility, but it doesn't assume that bytes are 8
bits.
The PDP-10 had 36-bit words and could operate on bit fields of any size
from 1 to 36 bits.
But it couldn't address them.
On 2024-07-07, James Kuyper <[email protected]> wrote:
On 7/7/24 16:10, BGB wrote:
On 7/7/2024 9:03 AM, James Kuyper wrote:
On 7/7/24 00:55, BGB wrote:
On 7/6/2024 5:38 PM, Keith Thompson wrote:...
...No, there is no implicitly defined pointer.
This implicit pointer need not exist at a location in memory...
Which is why C doesn't give you access to it's location in memory -
something you complained about earlier.
I don't think I was claiming that one should have direct access to its
location or value within the language, rather that their existence and
behaviors could be acknowledged in the language design (for a "not
quite C" language).
I think that the existence of an implicit pointer would be a bad thing
to acknowledge, given that the language doesn't require that it exist,
and typical implementations don't use them. From what I understand, the
fact that your implementation does have implicit pointers makes it a rarity.
Ritchie's B language had arrays which contained a pointer to their
first element. Via a hack, it was possible to relocate an array.
On 2024-07-07, James Kuyper <[email protected]> wrote:
On 7/7/24 16:10, BGB wrote:
On 7/7/2024 9:03 AM, James Kuyper wrote:
On 7/7/24 00:55, BGB wrote:
On 7/6/2024 5:38 PM, Keith Thompson wrote:
...
No, there is no implicitly defined pointer.
...
This implicit pointer need not exist at a location in memory...
Which is why C doesn't give you access to it's location in memory -
something you complained about earlier.
I don't think I was claiming that one should have direct access to its
location or value within the language, rather that their existence and
behaviors could be acknowledged in the language design (for a "not
quite C" language).
I think that the existence of an implicit pointer would be a bad thing
to acknowledge, given that the language doesn't require that it exist,
and typical implementations don't use them. From what I understand, the
fact that your implementation does have implicit pointers makes it a rarity.
Ritchie's B language had arrays which contained a pointer to their
first element. Via a hack, it was possible to relocate an array.
In C, such a thing is not simply not required; it is ruled out
by the detailed semantic description of arrays. [...]
Arrays are passed by reference:
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
Although the type of 'a' inside 'F' will be int* rather than
int(*)[20].
On 09/07/2024 16:58, Ben Bacarisse wrote:
bart <[email protected]> writes:
Arrays are passed by reference:This is the sort of thing that bad tutors say to students so that they
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
never learn C properly. All parameter passing in C is by value. All of
it. You just have to know (a) what the syntax means and (b) what values
get passed.
The end result is that a parameter declared with value-array syntax is
passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires
it. A 2-byte array is also passed by reference.
void F(int a[20]) ... declares a to be of type int *. Feel free to rail
about that as much as you like but that is what that syntax means.
The x in F(x) is converted to a pointer to x[0] since the x is not an
operand of &, sizeof etc. F(x) passes a pointer by value. F receives a
pointer value in a.
Although the type of 'a' inside 'F' will be int* rather thanNo. a is of type int *.
int(*)[20].
And that is different 'int*' how, about from having an extra space which C says is not signigicant in this context?
On 09/07/2024 18:22, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 09/07/2024 16:58, Ben Bacarisse wrote:
bart <[email protected]> writes:
Arrays are passed by reference:
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
This is the sort of thing that bad tutors say to students so that they >>>> never learn C properly. All parameter passing in C is by value. All of >>>> it. You just have to know (a) what the syntax means and (b) what values >>>> get passed.
The end result is that a parameter declared with value-array syntax is
passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires
it. A 2-byte array is also passed by reference.
An address value is passed by value. C has only one parameter passing
mechanism. You can spin it as much as you like, but C's parameter
passing is simple to understand, provided learner tune out voices like
yours.
Little about C's type system is simple. You're doing your students a disservice if you try and hide all the quirks.
On 7/9/2024 12:22 PM, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 09/07/2024 16:58, Ben Bacarisse wrote:An address value is passed by value. C has only one parameter passing
bart <[email protected]> writes:
Arrays are passed by reference:This is the sort of thing that bad tutors say to students so that they >>>> never learn C properly. All parameter passing in C is by value. All of >>>> it. You just have to know (a) what the syntax means and (b) what values >>>> get passed.
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
The end result is that a parameter declared with value-array syntax is
passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires
it. A 2-byte array is also passed by reference.
mechanism. You can spin it as much as you like, but C's parameter
passing is simple to understand, provided learner tune out voices like
yours.
Though, in ABI specs, this would usually still be termed as "pass by reference"
On 09/07/2024 18:22, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 09/07/2024 16:58, Ben Bacarisse wrote:An address value is passed by value. C has only one parameter passing
bart <[email protected]> writes:
Arrays are passed by reference:This is the sort of thing that bad tutors say to students so that they >>>> never learn C properly. All parameter passing in C is by value. All of >>>> it. You just have to know (a) what the syntax means and (b) what values >>>> get passed.
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
The end result is that a parameter declared with value-array syntax is
passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires
it. A 2-byte array is also passed by reference.
mechanism. You can spin it as much as you like, but C's parameter
passing is simple to understand, provided learner tune out voices like
yours.
Little about C's type system is simple.
You're doing your students a
disservice if you try and hide all the quirks.
- int (f[3])(void) { }, function returning array of 3 int,
is a constraint violation.
On 10/07/2024 00:35, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 09/07/2024 18:22, Ben Bacarisse wrote:Parameter passing is relatively simple though since there is only one
bart <[email protected]> writes:
On 09/07/2024 16:58, Ben Bacarisse wrote:An address value is passed by value. C has only one parameter passing >>>> mechanism. You can spin it as much as you like, but C's parameter
bart <[email protected]> writes:
Arrays are passed by reference:This is the sort of thing that bad tutors say to students so that they >>>>>> never learn C properly. All parameter passing in C is by value. All of >>>>>> it. You just have to know (a) what the syntax means and (b) what values >>>>>> get passed.
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
The end result is that a parameter declared with value-array syntax is >>>>> passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires >>>>> it. A 2-byte array is also passed by reference.
passing is simple to understand, provided learner tune out voices like >>>> yours.
Little about C's type system is simple.
mechanism -- pass by value.
Except when it comes to arrays.
I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed
by reference, then how the hell ARE they passed?!"
On 10/07/2024 14:32, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 10/07/2024 00:35, Ben Bacarisse wrote:The oddity is that, in C, one can't pass arrays to functions at all.
bart <[email protected]> writes:
On 09/07/2024 18:22, Ben Bacarisse wrote:Parameter passing is relatively simple though since there is only one
bart <[email protected]> writes:
On 09/07/2024 16:58, Ben Bacarisse wrote:An address value is passed by value. C has only one parameter passing >>>>>> mechanism. You can spin it as much as you like, but C's parameter >>>>>> passing is simple to understand, provided learner tune out voices like >>>>>> yours.
bart <[email protected]> writes:
Arrays are passed by reference:This is the sort of thing that bad tutors say to students so that they >>>>>>>> never learn C properly. All parameter passing in C is by value. All of
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
it. You just have to know (a) what the syntax means and (b) what values
get passed.
The end result is that a parameter declared with value-array syntax is >>>>>>> passed using a reference rather than by value.
And it does so because the language says, not because the ABI requires >>>>>>> it. A 2-byte array is also passed by reference.
Little about C's type system is simple.
mechanism -- pass by value.
Except when it comes to arrays.
That is one of the quirks that people learning C need to learn. It does
not alter the fact that there is only parameter passing mechanism -- by
value.
Your plan, of course, is to take that one place where C is relatively
simple
It is not that simple. It is confusing. It is error prone.
I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed by reference, then how the hell ARE they passed?!"
I haven't had a reply yet.
I still consider arrays in C to be 'passed' by a
mechanism which is near-indistinguishable from actual
pass-by-reference.
If somebody had proposed adding pass-by-reference for arrays, you'd say C doesn't need it, because whatever benefits it might have you, C already
has!
On 11/07/2024 00:01, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 10/07/2024 14:32, Ben Bacarisse wrote:
I still consider arrays in C to be 'passed' by aI don't really care how you consider it, but I do care about how you
mechanism which is near-indistinguishable from actual
pass-by-reference.
misrepresent the facts in public.
In another post you said that your language has pass by reference, and
we also know you have implemented C. Either you are just very confused
and your language simply has call by value (after all, you think C has
pass by reference), or you know that pass by reference in your language
needs something from the implementation that was not needed when you
implemented C. I can't decide if you are confused or just lying.
The way it works in my language is very simple...
But when T is an array, its behaviour is more like that of my H function.
So, my remark about arrays in C being passed by reference is understandable.
If somebody had proposed adding pass-by-reference for arrays, you'd say C >>> doesn't need it, because whatever benefits it might have you, C alreadyI see you are running out of statements to argue against so you have
has!
started to make up your own. I am sure you have thoroughly refuted this
made up person in your head.
Anyone proposing adding pass-by-reference for arrays would be told (by
me at last) to start by allowing arrays to be passed by value first.
Why anyone would propose adding pass by reference for a type that can't
be currently be passed at all is a mystery that only you (as the
inventor of this person) can know.
This is my point. Clearly true pass-by-reference for arrays wouldn't add anything in C;
it already works alike that!
On Thu, 11 Jul 2024 08:41:14 -0000 (UTC)...
Kaz Kylheku <[email protected]> wrote:
First class functions could do something like this:
// multiplier takes a coefficient and returns a pointer to
// function
int (*multiplier(int coefficient))(int) {
// fantasy lambda syntax. Return type int is written after
// parameter list.
return lambda(int x) int {
return coefficient * x;
}
}
int (*doubler)(int) = multiplier(2);
int x = doubler(42); // x becomes 84
Even though the lambda is returned out of multiplier, whose execution
terminates, when the returned function is invoked, it can refer to the
coefficient, which is captured in a lexical closure.
With a C-like typedef, we can declutter the definition of mutiplier:
typedef int (*int_int_fn)(int);
int_int_fn multiplier(int coefficient) {
return lambda(int x) int {
return coefficient * x;
}
}
Thank you.
Your example confirms my suspicion that the difference between first
and second class of functions doesn't become material until language
supports closures.
On 10/07/2024 16:48, Tim Rentsch wrote:
bart <[email protected]> writes:
I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed
by reference, then how the hell ARE they passed?!"
They aren't. C allows lots of things to be passed as an argument
to a function: several varieties of numeric values, structs,
unions, and pointers, including both pointers to object types and
pointers to function types. C does not have a way for a function
to take an argument that is either an array or a function. There
is a way to take pointers to those things, but not the things
themselves. Arrays and functions are second-class values in C.
That's a good point. It's not just arrays that can't be passed by
value (because the language says so) but also functions (because its
not meaningful).
Yet, although pointers to arrays and function can be passed (without
even doing anything special like using &), you are not allowed to say
that anything is passed by reference in C!
On 11/07/2024 00:01, Ben Bacarisse wrote:
bart <[email protected]> writes:
On 10/07/2024 14:32, Ben Bacarisse wrote:
I still consider arrays in C to be 'passed' by a
mechanism which is near-indistinguishable from actual
pass-by-reference.
I don't really care how you consider it, but I do care about how you
misrepresent the facts in public.
In another post you said that your language has pass by reference, and
we also know you have implemented C. Either you are just very confused
and your language simply has call by value (after all, you think C has
pass by reference), or you know that pass by reference in your language
needs something from the implementation that was not needed when you
implemented C. I can't decide if you are confused or just lying.
The way it works in my language is very simple (this is what I do
after all):
type T = int
proc F(T x)= # Pass by value
println x.typestr
end
proc G(ref T x)= # Manual pass-by-reference
println x^.typestr
end
proc H(T &x)= # Auto pass-by-reference
println x.typestr
end
proc main=
T a
F(a)
G(&a)
H(a)
end
I've written 3 functions using pass-by-value, pass-by-value emulating pass-by-reference, and actual pass-by-reference. [...]
On 10/07/2024 19:39, Michael S wrote:
On Wed, 10 Jul 2024 18:30:54 +0100
bart <[email protected]> wrote:
On 10/07/2024 16:48, Tim Rentsch wrote:
bart <[email protected]> writes:
>>>> I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed
by reference, then how the hell ARE they passed?!"
They aren't. C allows lots of things to be passed as an argument
to a function: several varieties of numeric values, structs,
unions, and pointers, including both pointers to object types and
pointers to function types. C does not have a way for a function
to take an argument that is either an array or a function. There
is a way to take pointers to those things, but not the things
themselves. Arrays and functions are second-class values in C.
That's a good point. It's not just arrays that can't be passed by
value (because the language says so) but also functions (because its
not meaningful).
Yet, although pointers to arrays and function can be passed (without
even doing anything special like using &), you are not allowed to say
that anything is passed by reference in C!
The automatic conversion to a pointer, which is also a feature of
true pass-by-reference, doesn't count.
Not needing an explicit deref inside the callee (another
characteristic of pass-by-reference) doesn't count either.
It does not count, because automatic conversion to a pointer is not
something that happens only during parameter passing. For arrays, it
happens in all contexts except sizeof(). For functions, it happens in
all contexts except function call. Or, may be, including function call,
in this case (but not in case of arrays) it depends on point of view.
Suppose that was to happen in all contexts, not just for arrays and functions, but for all types.
That means that if A, B, C were numbers, then any call such as F(A, B,
C) would pass the addresses of the numbers rather than their values.
According to what people have said, C would STILL be a language that
passed thing by value, and never by automatic reference.
On 11/07/2024 12:49, Tim Rentsch wrote:
bart <[email protected]> writes:
According to what people have said, C would STILL be a language that
passed thing by value, and never by automatic reference.
First, the scheme that you outline is either dumb or disingenuous
(or perhaps both).
Second, the argument you're making is purely ad hominem: it
isn't about what is true but about what it is people will say, or
at least what you think they would say.
Third, none of this changes the underlying reality. Whatever
people might say about your hypothetical scenario, or whatever it
is you think they would say, it doesn't alter the fact that in C
all function arguments are passed by value, and not by reference.
People don't write software based on the the precise, pedantic details
of what a language reference says, which are always to use the same
carefully selected set of terms.
They want to write programs that do useful tasks.
If that task calls for a function that manipulates arrays as though
they were passed by reference, then, guess what, they will use a C
function that the standard says always passes things by value.
For that purpose, in the mind of the user, it does the same job as 'by
by reference'. That it does so by some other quirks (array decay, and
the ability to index pointers as thought they were arrays), is by the
by.
I understand that in this newsgroup, most posters are only interested
in what the Standard says and little else, and will pounce upon any
turns of phrase, any nomenclature, that deviate even slightly from
what it says in that document.
I also understand that this is not comp.std.c
Meanwhile, the internet abounds with quotes like this about C:
"When we pass the address of an array while calling a function then
this is called function call by reference."
"Basically, in C, function parameters that are arrays are passed by reference, by default."
Yes, I get that such lax informality would annoy the people here.
On Wed, 10 Jul 2024 08:48:05 -0700
Tim Rentsch <[email protected]> wrote:
bart <[email protected]> writes:
I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed
by reference, then how the hell ARE they passed?!"
They aren't. C allows lots of things to be passed as an argument
to a function: several varieties of numeric values, structs,
unions, and pointers, including both pointers to object types and
pointers to function types. C does not have a way for a function
to take an argument that is either an array or a function. There
is a way to take pointers to those things, but not the things
themselves. Arrays and functions are second-class values in C.
I'd like to see an example of the language that permits ahead-of-time compilation and has functions as first-class values.
On 7/11/2024 9:02 AM, Tim Rentsch wrote:
Michael S <[email protected]> writes:
On Wed, 10 Jul 2024 08:48:05 -0700
Tim Rentsch <[email protected]> wrote:
bart <[email protected]> writes:
I earlier asked this:
"So if arrays aren't passed by value in C, and they aren't passed
by reference, then how the hell ARE they passed?!"
They aren't. C allows lots of things to be passed as an argument
to a function: several varieties of numeric values, structs,
unions, and pointers, including both pointers to object types and
pointers to function types. C does not have a way for a function
to take an argument that is either an array or a function. There
is a way to take pointers to those things, but not the things
themselves. Arrays and functions are second-class values in C.
I'd like to see an example of the language that permits ahead-of-time
compilation and has functions as first-class values.
C is almost that language. Pointers to functions are first class
in C. If for every C function definition a pattern like this:
static int
foo_implementation( int x ){
return x > 0 ? -x : x;
}
int (*foo)( int ) = foo_implementation;
is used, and there are no other references to the _implementation
names, then "functions" like foo() are essentially first-class
functions. The "function" foo can be assigned into. It can be
called just like an actual C function. The type of a "function"
is not like an actual function type, and so for example how the
address-of operator works is different for "functions" than it is
for actual C functions. Also pre-declarations for "functions"
obviously need to be different than they would be for actual C
functions. If the necessary adjustments are made, we would have
a language with first-class "functions".
Incidentally, whether a language has closures is orthogonal to
the question of whether functions are first class. Closures
might or might not be interoperable with functions (they are
in some languages, and not in others). But that needn't have
any bearing on whether functions (or closures) are first class.
Note: strictly speaking a closure is a run-time value, not a
compile-time definition. I trust my readers are able to make
the needed linguistic accommodations.
FWIW, there was a proposal to add C++ style lambdas to C23, but
apparently didn't get in. [...]
But maybe he has looked up some things, since lately he's squirming
by introducing terms like "_true_ pass-by-reference" [emphasis by me] obviously trying to bend the semantics of the established technical "pass-by-reference" term to fit his argument. (Introducing new terms
for existing mechanisms or bending semantics of existing terms with
well established meaning is certainly not helpful in any way.)
But, yes, that person is a phenomenon.
Janis
On Fri, 12 Jul 2024 13:12:53 +0200
Janis Papanagnou <[email protected]> wrote:
But maybe he has looked up some things, since lately he's squirming
by introducing terms like "_true_ pass-by-reference" [emphasis by me]
obviously trying to bend the semantics of the established technical
"pass-by-reference" term to fit his argument. (Introducing new terms
for existing mechanisms or bending semantics of existing terms with
well established meaning is certainly not helpful in any way.)
But, yes, that person is a phenomenon.
I don't share your optimistic belief that the term "pass by reference"
is really established. Very few terms in computer science (science?
really?) are established firmly. Except, may be, in more theoretical branches of it.
Michael S <[email protected]> writes:
On Fri, 12 Jul 2024 13:12:53 +0200
Janis Papanagnou <[email protected]> wrote:
But maybe he has looked up some things, since lately he's squirming
by introducing terms like "_true_ pass-by-reference" [emphasis by me]
obviously trying to bend the semantics of the established technical
"pass-by-reference" term to fit his argument. (Introducing new terms
for existing mechanisms or bending semantics of existing terms with
well established meaning is certainly not helpful in any way.)
But, yes, that person is a phenomenon.
I don't share your optimistic belief that the term "pass by reference"
is really established. Very few terms in computer science (science?
really?) are established firmly. Except, may be, in more theoretical
branches of it.
The terms
call by name
call by value
call by reference
call by value-result
are all well-defined and firmly established, going back more than
60 years. I learned all of these in standard early course in
computer science sometime in the early 1970s. Of course I can't
be sure about the source after all these years, but I expect
they were defined in the textbook we were using in the class.
Much later, probably under the influence of people learning
by reading blogs rather than books, some of these terms were
expressed as, eg, "pass by value" or "pass by reference".
However there is no indication that the change was meant to
express a different meaning, except insofar as the person(s)
using the revised terms were confused.
On 7/13/2024 4:01 AM, Tim Rentsch wrote:
Michael S <[email protected]> writes:
On Fri, 12 Jul 2024 13:12:53 +0200
Janis Papanagnou <[email protected]> wrote:
But maybe he has looked up some things, since lately he's squirming
by introducing terms like "_true_ pass-by-reference" [emphasis by me]
obviously trying to bend the semantics of the established technical
"pass-by-reference" term to fit his argument. (Introducing new terms
for existing mechanisms or bending semantics of existing terms with
well established meaning is certainly not helpful in any way.)
But, yes, that person is a phenomenon.
I don't share your optimistic belief that the term "pass by reference"
is really established. Very few terms in computer science (science?
really?) are established firmly. Except, may be, in more theoretical
branches of it.
The terms
call by name
call by value
call by reference
call by value-result
are all well-defined and firmly established, going back more than
60 years. I learned all of these in standard early course in
computer science sometime in the early 1970s. Of course I can't
be sure about the source after all these years, but I expect
they were defined in the textbook we were using in the class.
Much later, probably under the influence of people learning
by reading blogs rather than books, some of these terms were
expressed as, eg, "pass by value" or "pass by reference".
However there is no indication that the change was meant to
express a different meaning, except insofar as the person(s)
using the revised terms were confused.
Anyone who refuses to stick to the firmly established meanings
is in all likelihood just someone who enjoys being fractious.
As I see it, they are not exactly the same:
"call by reference", is from the POV of how arguments themselves are
passed to functions during a function call;
"pass by reference" has more to do with the data or object being
conveyed (usually means that a pointer to the object is being passed,
but generally used in cases where no explicit pointer exists).
"Call by reference" would be N/A for C, since this in not how C
function calls work.
Whereas something like object instance semantics in Java, could be interpreted as an example of the latter (versus primitive arguments
which are still by-value in Java).
On 12/07/2024 12:44, Janis Papanagnou wrote:
On 11.07.2024 22:37, bart wrote:
On 11/07/2024 21:29, Keith Thompson wrote:
bart <[email protected]> writes:
This my first comment on the subject:
"Arrays are passed by reference:
...
Although ..."
And that statement was incorrect, even with the "Although".
So arrays are passed by value? Gotcha.
Neither is true. - Tertium datur!
"Array passing" is in "C" realized using a pointer passing
mechanism where the pointer is passed "by value".
Neither an array is passed [by value] nor there's a "call
by reference" mechanism in "C".
So how are the elements of the caller's array accessed?
Tim Rentsch <[email protected]> writes:
Michael S <[email protected]> writes:
On Fri, 12 Jul 2024 13:12:53 +0200
Janis Papanagnou <[email protected]> wrote:
But maybe he has looked up some things, since lately he's squirming
by introducing terms like "_true_ pass-by-reference" [emphasis by me]
obviously trying to bend the semantics of the established technical
"pass-by-reference" term to fit his argument. (Introducing new terms
for existing mechanisms or bending semantics of existing terms with
well established meaning is certainly not helpful in any way.)
But, yes, that person is a phenomenon.
I don't share your optimistic belief that the term "pass by reference"
is really established. Very few terms in computer science (science?
really?) are established firmly. Except, may be, in more theoretical
branches of it.
The terms
call by name
call by value
call by reference
call by value-result
are all well-defined and firmly established, going back more than
60 years. I learned all of these in standard early course in
computer science sometime in the early 1970s. Of course I can't
be sure about the source after all these years, but I expect
they were defined in the textbook we were using in the class.
Much later, probably under the influence of people learning
by reading blogs rather than books, some of these terms were
expressed as, eg, "pass by value" or "pass by reference".
I think it's reasonable to assume that this change of term was partly motivated simply by the meaning of the words. Call by value (to pick
one) is an odd term to use about a parameter and/or argument. The
function or procedure is called, but the arguments are passed and subsequently accessed. Nowadays, sentences like "Specifications of parameters called by value must be supplied" just feel a bit strange, at least to me.
Had I been CS King, I would have promulgated the terms "accessed by
value", "accessed by name" and so on since it's the access method that
really what matters to my mind.
Because as AFAIK this whole subthread seems to about people trying
to catch me out on some pedantry.
All it needed was for someone to agree that yes, arrays are
/effectively/ passed by reference, [...]
On 06/07/2024 19:28, James Kuyper wrote:[...]
It is that conversion [from array designator to a pointer to the
first element of the array] which creates the illusion of array
indexing, but since it's been converted to a pointer, it is
actually pointer indexing.
Isn't that how all languages work 'under the hood'?
The net affect from the user's point of view is that you have an
array object, and use 'indexing' to access its individual
elements.
[...] the differences [between C rules and true call-by-reference]
can be summarised here; [...]
Call Array access in callee
C call-by-value F(A) A[i]
true call-by-reference H(A) A[i]
What the user has to write is what's important, and here it is clear
that they write the same thing [in the two cases shown].
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
[on comparing array arguments in C with call-by-reference]
[...] the differences [between C rules and true call-by-reference]
can be summarised here; [...]
Call Array access in callee
C call-by-value F(A) A[i]
true call-by-reference H(A) A[i]
What the user has to write is what's important, and here it is clear
that they write the same thing [in the two cases shown].
The comparison above is misleading because it is incomplete.
Let's compare the two modes more fully:
C call-by-value call-by-reference
=============== =================
at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's pass-by-value
was remarkably similar to pass-by-reference.
However your entry for pointers is not correct:
you can pass pointers by
reference (in C, it means passing a T** type instead of T* to emulate
that).
(null argument) F(0) (disallowed)
Pass-by-reference necessarily requires an lvalue at the call-site
since it effectively applies & to the argument.
inside function:
(access) A[i] A[i]
(update) A[i] = ... A[i] = ...
sizeof A (pointer size) (array size)
That's one of the small differences. But you only get the array size in a language where the array type includes its length. Otherwise, you only get
it if it's part of the parameter type.
A++ (changes A variable) (disallowed)
(In my language ++A is allowed. I'm not sure why, it's likely a bug.)
A = (new value) (changes A variable) (disallowed)
This is allowed too in my language, if the array has a fixed size. It reassigns the whole array.
In C you can't do A = B for other reasons, since arrays aren't manipulated
by value.
The more complete comparion illustrate why C semantics should not
be thought of as call-by-reference.
It was made clear more than once that it wasn't exact
call-by-reference.
It was also made clear that there were enough similarities that adding real call-by-reference arrays to C would buy you very little.
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
[on comparing array arguments in C with call-by-reference]
[...] the differences [between C rules and true call-by-reference]
can be summarised here; [...]
Call Array access in callee
C call-by-value F(A) A[i]
true call-by-reference H(A) A[i]
What the user has to write is what's important, and here it is clear
that they write the same thing [in the two cases shown].
The comparison above is misleading because it is incomplete.
Let's compare the two modes more fully:
C call-by-value call-by-reference
=============== =================
at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's
pass-by-value was remarkably similar to pass-by-reference.
On 15/08/2024 15:33, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
Which is why, presumably, you didn't show the differences. YourC call-by-value call-by-reference
=============== =================
at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's pass-by-value >>> was remarkably similar to pass-by-reference.
post was all polemic not part of a collegiate discussion of the
similarities and differences.
However your entry for pointers is not correct:No, the entry is correct. H(p) would be (is?) disallowed when H's
parameter is a reference to an array.
Sorry, what language does the right-hand column pertain to? /Any/ language that has call-by-reference, or Tim's hypthetical language?
Or any that could be used to prove him right?
In general there is no reason, in a language with true call-by-reference,
why any parameter type T (which has the form U*, a pointer to anything), cannot be passed by reference. It doesn't matter whether U is an array type or not.
you can pass pointers byH's parameter is /not/ what you claim "emulates" a reference to a
reference (in C, it means passing a T** type instead of T* to emulate
that).
pointer -- it's a hypothetical reference to an array.
In my original post it was G() that was C emulating pass-by-reference.
It wasn't stated that p was an array pointer, only pointer, but it doesn't make any difference in H which we can assume is not C, and therefore
doesn't have C's hangups about arrays and pointers.
Maybe you missed what Tim was doing. He is showing a fuller comparison
for one F and one H. A different function could, in this hypothetical
C with call-by-reference, be passed a pointer, but then it could not be
passed an array.
Neither of you have explained this well. Are you both projecting C's craziness with arrays and pointers onto this hypothetical language?
If so, then if this fantasy language has true pass-by-reference, then let
it have real value-arrays too!
Yes, that is one of the differences you failed to illustrate.(null argument) F(0) (disallowed)
Pass-by-reference necessarily requires an lvalue at the call-site
I illustrated some conveniences which C's array-passing idiom which match those of true pass-by-reference.
since it effectively applies & to the argument.No. Passing a reference is /not/ like using & to pass a pointer.
Funny, in my language that is EXACTLY how it is implemented. Instead of my writing:
F(&x) and in F having to write: *x
you instead write:
F(x) and in F you write: x
So it will insert & and * operators for you. Why, how would /you/ do it? (I'm talking about this level of language; higher level ones might do everthing with references anyway, and might not have & or * operators.)
In the hypothetical C with call-by-reference, it's another differenceinside function:
(access) A[i] A[i]
(update) A[i] = ... A[i] = ...
sizeof A (pointer size) (array size)
That's one of the small differences. But you only get the array size in a >>> language where the array type includes its length. Otherwise, you only get >>> it if it's part of the parameter type.
A++ (changes A variable) (disallowed)
(In my language ++A is allowed. I'm not sure why, it's likely a bug.)
you chose not to show.
Yes, as I said, I concentrate on the ones which allowed you to write F(A), and A[i] inside F, just like pass-by-reference, rather than F(&A), and (*A[i]) inside F. Did I claim it was full by pass-by-reference?
Your language (for which we have no reference material) is beside theA = (new value) (changes A variable) (disallowed)
This is allowed too in my language, if the array has a fixed size. It
reassigns the whole array.
point. This is another difference you failed to point out in your
comparison
It doesn't matter; any call-by-reference worth its salt will allow you to change variables in the caller. That's half the point it!
C doesn't have A=B syntax for arrays, but it can do memcpy for the same effect.
In C you can't do A = B for other reasons, since arrays aren't manipulated >>> by value.One way or another, this is a difference you failed to illustrate. If
this hypothetical C is very close to C then the difference is as Tim
posted. But in a another quasi-C that permits array assignment there
would still be a difference: the pointer assignment would be disallowed
but the array assignment (by reference) would be permitted.
What pointer assignment? You're mixing actual C with fantasy C. You can't
do that: if you add array assignment to C, then it changes everything.
So why did you give only one side of the comparison? You have nothing
to lose by being open about the differences if your objective is an
open, collegiate discussion of C. By presenting a polemic, you make the
whole exchange more antagonistic than it needs to be.
These were my original comments on the subject made to DB:
DB:
. In C, there is no "pass by reference" or "return by reference". It isall done by value.
BC:
Arrays are passed by reference:
void F(int a[20]) {}
int main(void) {
int x[20];
F(x);
}
Although the type of 'a' inside 'F' will be int* rather than int(*)[20].
It was in reply to DB which appear to imply that arrays were passed by
value. Obviously they're not passed by value, so what then? (Please, don't rerun the thread! This is where everyone jumped in.)
On 16/08/2024 02:08, Ben Bacarisse wrote:
Bart <[email protected]> writes:
In general there is no reason, in a language with true call-by-reference, >>> why any parameter type T (which has the form U*, a pointer to anything), >>> cannot be passed by reference. It doesn't matter whether U is an array type >>> or not.I can't unravel this. Take, as a concrete example, C++. You can't pass
a pointer to function that takes an array passed by reference. You can,
of course, pass a pointer by reference, but that is neither here nor
there.
In C++, you can't pass arrays as parameters at all - the language inherited C's handling of arrays. You can, of course, pass objects of std::array<> type by value or by reference, just like any other class types.
On Fri, 16 Aug 2024 01:08:15 +0100
Ben Bacarisse <[email protected]> wrote:
Bart <[email protected]> writes:
On 15/08/2024 15:33, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
Which is why, presumably, you didn't show the differences. YourC call-by-value
call-by-reference =============== =================
at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's
pass-by-value was remarkably similar to pass-by-reference.
post was all polemic not part of a collegiate discussion of the
similarities and differences.
However your entry for pointers is not correct:No, the entry is correct. H(p) would be (is?) disallowed when H's
parameter is a reference to an array.
Sorry, what language does the right-hand column pertain to? /Any/
language that has call-by-reference, or Tim's hypthetical language?
Tim said that case was "disallowed". You call that an error on his
part. What language did you have in mind that permits such a gross
warping of types? I would describe /any/ language that allowed it as
having a design error.
Or any that could be used to prove him right?
In general there is no reason, in a language with true
call-by-reference, why any parameter type T (which has the form U*,
a pointer to anything), cannot be passed by reference. It doesn't
matter whether U is an array type or not.
I can't unravel this. Take, as a concrete example, C++. You can't
pass a pointer to function that takes an array passed by reference.
You can, of course, pass a pointer by reference, but that is neither
here nor there.
IMHO, C++ is a particularly bad example.
Yes, C++ has call-by-reference misfeature. But arrays in C++ are
2nd class citizen, same as in C. They can't be assigned and can't be
passed to callee, neither by value nor by reference.
Also, I suspect that if you ask Ken Thompson, he will tell you that C++
does not really have 'call by reference'. Instead, it has references as
1st class object, so, naturally, values of references can be used
during 'call by value'.
I have enough of respect to KT to consider that his POV is not a
nonsense.
On 16/08/2024 01:08, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 15/08/2024 15:33, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
C call-by-value call-by-reference >>>>>> =============== ================= >>>>>> at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's pass-by-value >>>>> was remarkably similar to pass-by-reference.
Which is why, presumably, you didn't show the differences. Your
post was all polemic not part of a collegiate discussion of the
similarities and differences.
However your entry for pointers is not correct:
No, the entry is correct. H(p) would be (is?) disallowed when H's
parameter is a reference to an array.
Sorry, what language does the right-hand column pertain to? /Any/ language >>> that has call-by-reference, or Tim's hypthetical language?
Tim said that case was "disallowed". You call that an error on his
part. What language did you have in mind that permits such a gross
warping of types? I would describe /any/ language that allowed it as
having a design error.
You or he would have to go into more detail, such as an actual
example, to demonstrate whatever it is that you think is wrong about
passing a pointer argument by-reference.
I assume here that the language in the right column is not C.
Or any that could be used to prove him right?
In general there is no reason, in a language with true call-by-reference, >>> why any parameter type T (which has the form U*, a pointer to anything), >>> cannot be passed by reference. It doesn't matter whether U is an array
type or not.
I can't unravel this. Take, as a concrete example, C++. You can't pass
a pointer to function that takes an array passed by reference. You can,
of course, pass a pointer by reference, but that is neither here nor
there.
OK. So why do you agree with this:
C call-by-value call-by-reference >>>>>> =============== ================= >>>>>> (pointer argument) F(p) (disallowed)
What is 'pointer argument' here?
On 17/08/2024 15:41, Tim Rentsch wrote:
Bart <[email protected]> writes:
OK. So why do you agree with this:
C call-by-value call-by-reference
=============== =================
(pointer argument) F(p) (disallowed)
What is 'pointer argument' here?
Try thinking harder. Everyone else understood.
I could equally say that everyone understood what was meant by
implicit cast'.
But here you really have to explain what you mean by a pointer
argument, since there is no reason why such a type can't be passed
by reference.
Lacking such an explanation, I'd have to say still that
'disallowed' is generally incorrect.
On 16/08/2024 01:08, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 15/08/2024 15:33, Ben Bacarisse wrote:Tim said that case was "disallowed". You call that an error on his
Bart <[email protected]> writes:
On 15/08/2024 09:43, Tim Rentsch wrote:
Bart <[email protected]> writes:
Which is why, presumably, you didn't show the differences. YourC call-by-value call-by-reference >>>>>> =============== ================= >>>>>> at call:
(array argument) F(A) H(A)
(pointer argument) F(p) (disallowed)
My posts were about passing *arrays* and the fact that C's pass-by-value >>>>> was remarkably similar to pass-by-reference.
post was all polemic not part of a collegiate discussion of the
similarities and differences.
However your entry for pointers is not correct:No, the entry is correct. H(p) would be (is?) disallowed when H's
parameter is a reference to an array.
Sorry, what language does the right-hand column pertain to? /Any/ language >>> that has call-by-reference, or Tim's hypthetical language?
part. What language did you have in mind that permits such a gross
warping of types? I would describe /any/ language that allowed it as
having a design error.
You or he would have to go into more detail, such as an actual example, to demonstrate whatever it is that you think is wrong about passing a pointer argument by-reference.
I assume here that the language in the right column is not C.
Or any that could be used to prove him right?I can't unravel this. Take, as a concrete example, C++. You can't pass
In general there is no reason, in a language with true call-by-reference, >>> why any parameter type T (which has the form U*, a pointer to anything), >>> cannot be passed by reference. It doesn't matter whether U is an array type >>> or not.
a pointer to function that takes an array passed by reference. You can,
of course, pass a pointer by reference, but that is neither here nor
there.
OK. So why do you agree with this:
C call-by-value call-by-reference >>>>>> =============== ================= >>>>>> (pointer argument) F(p) (disallowed)
What is 'pointer argument' here?
On 16/08/2024 12:00, Ben Bacarisse wrote:
David Brown <[email protected]> writes:
On 16/08/2024 02:08, Ben Bacarisse wrote:The best way to think about C++ (in my very non-expert opinion) is to
Bart <[email protected]> writes:
In general there is no reason, in a language with true call-by-reference, >>>>> why any parameter type T (which has the form U*, a pointer to anything), >>>>> cannot be passed by reference. It doesn't matter whether U is an array typeI can't unravel this. Take, as a concrete example, C++. You can't pass >>>> a pointer to function that takes an array passed by reference. You can, >>>> of course, pass a pointer by reference, but that is neither here nor
or not.
there.
In C++, you can't pass arrays as parameters at all - the language inherited >>> C's handling of arrays. You can, of course, pass objects of std::array<> >>> type by value or by reference, just like any other class types.
consider references as values that are passed by, err..., value. But
you seem prepared to accept that some things can be "passed by reference"
in C++.
That seems a subtle distinction - I'll have to think about it a little. I like your description of arguments being like local variable initialisation
- it makes sense equally well regardless of whether the parameter is "int", "int*", or "int&". (It's probably best not to mention the other one in
this group...)
So if this:
#include <iostream>
void g(int &i) { std::cout << i << "\n"; }
int main(void)
{
int I{0};
g(I);
}
shows an int object, I, being passed to g, why does this
#include <iostream>
void f(int (&ar)[10]) { std::cout << sizeof ar << "\n"; }
int main(void)
{
int A[10];
f(A);
}
not show an array, A, being passed to f?
That's backwards compatibility with C array handling at play.
David Brown <[email protected]> writes:
On 16/08/2024 12:00, Ben Bacarisse wrote:
David Brown <[email protected]> writes:
On 16/08/2024 02:08, Ben Bacarisse wrote:
Bart <[email protected]> writes:
In general there is no reason, in a language with true
call-by-reference, why any parameter type T (which has the form
U*, a pointer to anything), cannot be passed by reference. It
doesn't matter whether U is an array type or not.
I can't unravel this. Take, as a concrete example, C++. You
can't pass a pointer to function that takes an array passed by
reference. You can, of course, pass a pointer by reference, but
that is neither here nor there.
In C++, you can't pass arrays as parameters at all - the language
inherited C's handling of arrays. You can, of course, pass
objects of std::array<> type by value or by reference, just like
any other class types.
The best way to think about C++ (in my very non-expert opinion) is
to consider references as values that are passed by, err...,
value. But you seem prepared to accept that some things can be
"passed by reference" in C++.
That seems a subtle distinction - I'll have to think about it a
little. I like your description of arguments being like local
variable initialisation - it makes sense equally well regardless of
whether the parameter is "int", "int*", or "int&". (It's probably
best not to mention the other one in this group...)
So if this:
#include <iostream>
void g(int &i) { std::cout << i << "\n"; }
int main(void)
{
int I{0};
g(I);
}
shows an int object, I, being passed to g, why does this
#include <iostream>
void f(int (&ar)[10]) { std::cout << sizeof ar << "\n"; }
int main(void)
{
int A[10];
f(A);
}
not show an array, A, being passed to f?
That's backwards compatibility with C array handling at play.
I'm not sure how this answers my question. Maybe you weren't
answering it and were just making a remark...
On 19/08/2024 01:01, Ben Bacarisse wrote:
Bart <[email protected]> writes:
You or he would have to go into more detail, such as an actual example, to >>> demonstrate whatever it is that you think is wrong about passing a pointer >>> argument by-reference.No one has said any such thing, so I can't see how any more detail could
help. I suspect you've lost track of the point being made.
Probably, and perhaps not just me! But I'd still quite like to know exactly what it is that is marked as 'disallowed'.
I can't see what is confusing you about this. I agree with the aboveI can't unravel this. Take, as a concrete example, C++. You can't pass >>>> a pointer to function that takes an array passed by reference. You can, >>>> of course, pass a pointer by reference, but that is neither here nor
there.
OK. So why do you agree with this:
C call-by-value call-by-reference >>>>>>>> =============== ================= >>>>>>>> (pointer argument) F(p) (disallowed)
What is 'pointer argument' here?
for exactly the reasons I wrote.
Do you mean: 'You can't pass a pointer to a function that takes an array passed by reference'?
It would be wrong (and is wrong in
C++) to pass a pointer where an array reference is expected.
Well, putting aside pass-by-reference, that would be wrong in C too, if you interpret 'array reference' to be a type like T(*)[], and a 'pointer' a
type like T*.
With pass-by-reference added to C, there would be stronger type checking,
so if something is disallowed, it would be for a good reason, not just because Tim said so.
On 19/08/2024 03:03, Tim Rentsch wrote:...
Ben Bacarisse <[email protected]> writes:
David Brown <[email protected]> writes:
On 16/08/2024 12:00, Ben Bacarisse wrote:
David Brown <[email protected]> writes:
My guess is he didn't understand the question. The code shownIn C++, you can't pass arrays as parameters at all - the language
inherited C's handling of arrays. You can, of course, pass
objects of std::array<> type by value or by reference, just like
any other class types.
The best way to think about C++ (in my very non-expert opinion) is
to consider references as values that are passed by, err...,
value. But you seem prepared to accept that some things can be
"passed by reference" in C++.
That seems a subtle distinction - I'll have to think about it a
little. I like your description of arguments being like local
variable initialisation - it makes sense equally well regardless of
whether the parameter is "int", "int*", or "int&". (It's probably
best not to mention the other one in this group...)
So if this:
#include <iostream>
void g(int &i) { std::cout << i << "\n"; }
int main(void)
{
int I{0};
g(I);
}
shows an int object, I, being passed to g, why does this
#include <iostream>
void f(int (&ar)[10]) { std::cout << sizeof ar << "\n"; }
int main(void)
{
int A[10];
f(A);
}
not show an array, A, being passed to f?
That's backwards compatibility with C array handling at play.
I'm not sure how this answers my question. Maybe you weren't
answering it and were just making a remark...
has nothing to do with backwards compatibility with C array
handling.
I had intended to make a brief remark and thought that was all that was needed to answer the question. But having thought about it a bit more (prompted by these last two posts), and tested the code (on the assumption that the gcc writers know the details better than I do), you are correct -
I did misunderstand the question. I was wrong in how I thought array reference parameters worked in C++, and the way Ben worded the question re-enforced that misunderstanding.
I interpreted his question as saying that the code "f" does not show an
array type being passed by reference, with the implication that the
"sizeof" showed the size of a pointer, not the size of an array of 10 ints, and asking why C++ was defined that way. The answer, as I saw it, was that C++ made reference parameters to arrays work much like pointer parameters
to arrays, and those work like in C for backwards compatibility.
Of course, it turns out I was completely wrong about how array type
reference parameters work in C++. It's not something I have had use for in my own C++ programming or something I have come across in other code that I can remember, and I had made incorrect assumptions about it. Now that I corrected that, it all makes a lot more sense.
And so I presume Ben was actually asking why I /thought/ this was not
passing an array type (thus with its full type information, including its size). Then answer there is now obvious - I thought that because I had jumped to incorrect conclusions about array reference parameters in
C++.
On 19/08/2024 02:30, Ben Bacarisse wrote:
Bart <[email protected]> writes:
On 19/08/2024 01:01, Ben Bacarisse wrote:I don't know how to explain it any better. If you really want to know,
Bart <[email protected]> writes:
You or he would have to go into more detail, such as an actual example, toNo one has said any such thing, so I can't see how any more detail could >>>> help. I suspect you've lost track of the point being made.
demonstrate whatever it is that you think is wrong about passing a pointer
argument by-reference.
Probably, and perhaps not just me! But I'd still quite like to know exactly >>> what it is that is marked as 'disallowed'.
maybe you could say what /you/ think was incorrectly marked as
disallowed so I can see how you were interpreting the table.
I think I already said that several times!
But I need to use concrete code, and there is no existing mainstream
language with pass-by-reference that is simple enough to use for such examples. Except for mine and that is not acceptable here.
So I'll use an extended C where a '&' in front of a parameter's base-type marks it as pass-by-reference.
First an example written in standard C:
#include <stdio.h>
void F(int* p) {
printf("%d\n", *p);
++p;
}
int main(void) {
int A[] = {10,20,30};
int* p = &A[0];
F(p);
printf("%d\n", *p);
}
This passes a normal pointer. The output is 10 10 from both printfs,
because the ++p within F does not affect the original pointer in 'main'.
Now the same program, but using pass-by-reference for 'p'; I won't show the whole thing, as the program looks exactly the same except for this line:
void F(&int* p) {
The output should now be 10 20 (as verified using my language; if
interested, that is shown below, and below that is the standard C that
might be generated by a transpiler from this fantasy C).
So this is passing a pointer, by reference, and it is allowed!
Or maybe, just maybe, Tim said it for good reason.
And yet, he continues to be cagey about it, and you're defending him. Just give me a freakin' example!
WHAT EXACTLY IS IT THAT IS DISALLOWED?
Kaz Kylheku <[email protected]> writes:
On 2024-07-12, bart <[email protected]> wrote:
It's clearly not by value. It's apparently not by reference. You
can't get away with saying they are not passed, as clearly
functions *can* access array data via parameters.
Actually, you probably can get away with saying that it is "passed
by reference".
The formal term that doesn't apply is "call by reference"; that's
what C doesn't have.
"call by reference" emphasizes that the function call mechanism
provides the reference semantics for a formal parameter, not that
some arbitrary means of passage of the data has reference
semantics.
[...]
I know that "call by reference" is the usual formal term, but I
personally prefer "pass by reference".
The terms "call by reference" and "call by value" emphasize the
call, implying that all arguments in a given call are passed with
the same mechanism. In some languages that's true (C argument
passing is purely by value, and Fortran, as I understand it, is
purely by reference), but in others (C++, Pascal, Ada) you can
select by-value or by-reference for each parameter. "Pass by (reference|value)" feels more precise.
I haven't checked, but I suspect the terms "call by (reference|value)" predate languages that allowed the mechanism to be specified for each parameter.
Tim Rentsch <[email protected]> writes:
Keith Thompson <[email protected]> writes:
Kaz Kylheku <[email protected]> writes:
On 2024-07-12, bart <[email protected]> wrote:
It's clearly not by value. It's apparently not by reference. You
can't get away with saying they are not passed, as clearly
functions *can* access array data via parameters.
Actually, you probably can get away with saying that it is "passed
by reference".
The formal term that doesn't apply is "call by reference"; that's
what C doesn't have.
"call by reference" emphasizes that the function call mechanism
provides the reference semantics for a formal parameter, not that
some arbitrary means of passage of the data has reference
semantics.
[...]
I know that "call by reference" is the usual formal term, but I
personally prefer "pass by reference".
The terms "call by reference" and "call by value" emphasize the
call, implying that all arguments in a given call are passed with
the same mechanism. In some languages that's true (C argument
passing is purely by value, and Fortran, as I understand it, is
purely by reference), but in others (C++, Pascal, Ada) you can
select by-value or by-reference for each parameter. "Pass by
(reference|value)" feels more precise.
I haven't checked, but I suspect the terms "call by (reference|value)"
predate languages that allowed the mechanism to be specified for each
parameter.
I suspect that your guess here is influenced more by what you would
like to be true than what is likely to be true.
I was influenced by what I thought made the most sense.
What is likely to be true is that these terms entered the language
at essentially the same time as the original Algol. Algol 60 has
both call by name and call by value, referred to by those names in
the Algol 60 Report, and selectable on a per-parameter basis.
By contrast the precursor to Algol 60, the International Algebraic
Language or IAL for short (and referred to after the fact as Algol
58) did not use either term, and described the coupling between
arguments and parameters only in somewhat vague English prose that
left unclear exactly what the binding mechanism(s) were to be.
(There was a description for functions and a separate description
for procedures, not quite the same, and both not completely clear
exactly what the mechanism was meant to be.)
Thus it seems likely that the terms call by name, call by value,
and perhaps other similar terms, first arose during the discussions
of the Algol 60 working group in the late 1950s, and entered the
general lexicon with or perhaps slightly before the publication of
the Algol 60 Report, which describes and allows both call by name
and call by value, selectable on a per-parameter base, and referred
to by those names in the published Algol 60 Report.
Yes, that does seem likely.
I'm mildly disappointed. Since arguments are *passed* and functions/procedures are *called*, surely it would have made more sense
to use "pass by value" rather than "call by value", especially in a
language where the mechanism can vary per parameter.
(Yes, this is my opinion.)
If there's some reason why "call by value" actually made more sense than "pass by value", I'm not aware of it.
Since the phrase "pass by value" is now in common use, I'll continue to
use that term in preference to "call by value" (likewise "by
reference").
Keith Thompson <[email protected]> writes:
Tim Rentsch <[email protected]> writes:
Keith Thompson <[email protected]> writes:
Kaz Kylheku <[email protected]> writes:
On 2024-07-12, bart <[email protected]> wrote:
It's clearly not by value. It's apparently not by reference. You >>>>>> can't get away with saying they are not passed, as clearly
functions *can* access array data via parameters.
Actually, you probably can get away with saying that it is "passed
by reference".
The formal term that doesn't apply is "call by reference"; that's
what C doesn't have.
"call by reference" emphasizes that the function call mechanism
provides the reference semantics for a formal parameter, not that
some arbitrary means of passage of the data has reference
semantics.
[...]
I know that "call by reference" is the usual formal term, but I
personally prefer "pass by reference".
The terms "call by reference" and "call by value" emphasize the
call, implying that all arguments in a given call are passed with
the same mechanism. In some languages that's true (C argument
passing is purely by value, and Fortran, as I understand it, is
purely by reference), but in others (C++, Pascal, Ada) you can
select by-value or by-reference for each parameter. "Pass by
(reference|value)" feels more precise.
I haven't checked, but I suspect the terms "call by (reference|value)" >>>> predate languages that allowed the mechanism to be specified for each
parameter.
I suspect that your guess here is influenced more by what you would
like to be true than what is likely to be true.
I was influenced by what I thought made the most sense.
What is likely to be true is that these terms entered the language
at essentially the same time as the original Algol. Algol 60 has
both call by name and call by value, referred to by those names in
the Algol 60 Report, and selectable on a per-parameter basis.
By contrast the precursor to Algol 60, the International Algebraic
Language or IAL for short (and referred to after the fact as Algol
58) did not use either term, and described the coupling between
arguments and parameters only in somewhat vague English prose that
left unclear exactly what the binding mechanism(s) were to be.
(There was a description for functions and a separate description
for procedures, not quite the same, and both not completely clear
exactly what the mechanism was meant to be.)
Thus it seems likely that the terms call by name, call by value,
and perhaps other similar terms, first arose during the discussions
of the Algol 60 working group in the late 1950s, and entered the
general lexicon with or perhaps slightly before the publication of
the Algol 60 Report, which describes and allows both call by name
and call by value, selectable on a per-parameter base, and referred
to by those names in the published Algol 60 Report.
Yes, that does seem likely.
I'm mildly disappointed. Since arguments are *passed* and
functions/procedures are *called*, surely it would have made more sense
to use "pass by value" rather than "call by value", especially in a
language where the mechanism can vary per parameter.
All that is, I think, due to subsequent changes in (English) language
use. In Algol 60, procedures were invoked and /parameters/ were called
by value or name. Maybe the term was intended to reflect the idea that
the code in the body "called for the value" of the parameter.
The word "call" now refers, almost universally, to invoking a function
or procedure. As a result, the idea of "calling a parameter" reads
oddly, but at the time I'm sure it seemed perfectly reasonable.
(Yes, this is my opinion.)
If there's some reason why "call by value" actually made more sense
than "pass by value", I'm not aware of it.
Since the phrase "pass by value" is now in common use, I'll
continue to use that term in preference to "call by value"
(likewise "by reference").
I use those terms too. It would be confusing these days to talk
about calling a parameter, and the phrase "call by value" suggests
(as it never did at the time) something so do with the function
calling mechanism in general.
This is compounded by the fact that modern programming languages
has almost universally settled on calling all parameters by value
(to the use the old phrase) so, usually, the terms can, in fact,
be used to talk about the function calling mechanism.
Ben Bacarisse <[email protected]> writes:
Keith Thompson <[email protected]> writes:
Tim Rentsch <[email protected]> writes:
Keith Thompson <[email protected]> writes:
Kaz Kylheku <[email protected]> writes:
On 2024-07-12, bart <[email protected]> wrote:
It's clearly not by value. It's apparently not by reference. You >>>>>>> can't get away with saying they are not passed, as clearly
functions *can* access array data via parameters.
Actually, you probably can get away with saying that it is "passed >>>>>> by reference".
The formal term that doesn't apply is "call by reference"; that's >>>>>> what C doesn't have.
"call by reference" emphasizes that the function call mechanism
provides the reference semantics for a formal parameter, not that
some arbitrary means of passage of the data has reference
semantics.
[...]
I know that "call by reference" is the usual formal term, but I
personally prefer "pass by reference".
The terms "call by reference" and "call by value" emphasize the
call, implying that all arguments in a given call are passed with
the same mechanism. In some languages that's true (C argument
passing is purely by value, and Fortran, as I understand it, is
purely by reference), but in others (C++, Pascal, Ada) you can
select by-value or by-reference for each parameter. "Pass by
(reference|value)" feels more precise.
I haven't checked, but I suspect the terms "call by (reference|value)" >>>>> predate languages that allowed the mechanism to be specified for each >>>>> parameter.
I suspect that your guess here is influenced more by what you would
like to be true than what is likely to be true.
I was influenced by what I thought made the most sense.
What is likely to be true is that these terms entered the language
at essentially the same time as the original Algol. Algol 60 has
both call by name and call by value, referred to by those names in
the Algol 60 Report, and selectable on a per-parameter basis.
By contrast the precursor to Algol 60, the International Algebraic
Language or IAL for short (and referred to after the fact as Algol
58) did not use either term, and described the coupling between
arguments and parameters only in somewhat vague English prose that
left unclear exactly what the binding mechanism(s) were to be.
(There was a description for functions and a separate description
for procedures, not quite the same, and both not completely clear
exactly what the mechanism was meant to be.)
Thus it seems likely that the terms call by name, call by value,
and perhaps other similar terms, first arose during the discussions
of the Algol 60 working group in the late 1950s, and entered the
general lexicon with or perhaps slightly before the publication of
the Algol 60 Report, which describes and allows both call by name
and call by value, selectable on a per-parameter base, and referred
to by those names in the published Algol 60 Report.
Yes, that does seem likely.
I'm mildly disappointed. Since arguments are *passed* and
functions/procedures are *called*, surely it would have made more sense
to use "pass by value" rather than "call by value", especially in a
language where the mechanism can vary per parameter.
All that is, I think, due to subsequent changes in (English) language
use. In Algol 60, procedures were invoked and /parameters/ were called
by value or name. Maybe the term was intended to reflect the idea that
the code in the body "called for the value" of the parameter.
The word "call" now refers, almost universally, to invoking a function
or procedure. As a result, the idea of "calling a parameter" reads
oddly, but at the time I'm sure it seemed perfectly reasonable.
This view simply doesn't match the language and phrasing used
during the time Algol was being developed. Both the Algol 60
report and the preliminary IAL report (aka Algol 58) routinely
use the word call in connection with outside use of a procedure.
Algol 60 uses the word "invoke" exactly twice: once in relation
to procedures (where "call" is also used), and once in relation
to functions. Algol 58 uses the word call pretty much the same
way that Algol 60 does, but doesn't use the word "invoke" at all;
the verb "initiate" a procedure in Algol 58 turned into "invoke"
a procedure in Algol 60. Clearly using "call" was already well
established in the late 1950s, and "invoke" came later.
Algol 58 (loosely) defined the semantics of procedure call by
textual expansion of the procedure body at the call site,
substituting the text of actual parameters for each occurrence of
the corresponding formal parameter in the procedure body. The
actual rules are more complicated, due to there being different
"styles" (my word) of parameters, and because there were output
parameters as well as input parameters. Basically though the
meaning was what would later be termed "call by name", with some
restrictions on what forms of actual parameters were allowed.
Algol 60 simplified the rules by reducing the number of cases to
just two: either the actual parameter was textually substituted
for the formal parameter in the expansion (call by name), or the
value of the actual parameter expression was in effect assigned
to a local variable corresponding to the formal parameter (call
by value), which did not have a corresponding case in Algol 58.
The "call by" in "call by name" and "call by value" refers to how
the expansion is done in elaborating the procedure call. The
"call by" is not what sort of thing is passed, but what action is
taken in doing the substitution/expansion.
(Yes, this is my opinion.)
If there's some reason why "call by value" actually made more sense
than "pass by value", I'm not aware of it.
Since the phrase "pass by value" is now in common use, I'll
continue to use that term in preference to "call by value"
(likewise "by reference").
I use those terms too. It would be confusing these days to talk
about calling a parameter, and the phrase "call by value" suggests
(as it never did at the time) something so do with the function
calling mechanism in general.
Yes it did. It is only now that we have a different idea about
how functions and procedures are called that it seems like it
doesn't. But in Algol 60 it certainly did have something to do
with how a function reference was elaborated (aka called).
This is compounded by the fact that modern programming languages
has almost universally settled on calling all parameters by value
(to the use the old phrase) so, usually, the terms can, in fact,
be used to talk about the function calling mechanism.
The rationale here seems circular to me, and also not an accurate
picture of the programming language landscape.
Passing a pointer by value is not the same as a call be reference.
Passing a lambda by value is not the same as a call by name.
Shortly after Algol 60, FORTRAN adopted call by value/result,
also called call by copy in/copy out. Ada has INOUT, does
it not?
Logic programming languages have call by unification.
All of these cases show why "pass by" is not a good universal
fit.
At their lowest level, computers are simply slinging bits around.
In some sense everything is done in terms of "values". Thinking
in terms of what "value" is "passed" serves to reinforce an
imperative mind set, and there is already too much of that. For
these reasons and more I disdain the hoi polloi phrasing of "pass
by" for distinguishing different parameter modalities.
In the domain of German speaking countries - isn't Tim located there?
(I somehow got the impression) - we've heard about "Parameterubergabe";
[..] means passing, transferring, handing over, transmitting, etc.
Because of that - and because I could not follow the thoughts of Tim's
last paragraph with his conclusion; I didn't find it convincing - I'd
think that "passing" would fit better, also in the light of historic
usage [hereabouts], even though I've often heared (and also used) the
phrase "call by" in the English CS domain in the past (and probably
still used to it).
On 17.09.2024 15:15, Tim Rentsch wrote:
Janis Papanagnou <[email protected]> writes:
[excerpted for brevity]
In the domain of German speaking countries - isn't Tim located there?
(I somehow got the impression) - we've heard about "Parameterubergabe";
[..] means passing, transferring, handing over, transmitting, etc.
Because of that - and because I could not follow the thoughts of Tim's
last paragraph with his conclusion; I didn't find it convincing - I'd
think that "passing" would fit better, also in the light of historic
usage [hereabouts], even though I've often heared (and also used) the
phrase "call by" in the English CS domain in the past (and probably
still used to it).
If you have something to say to me please respond to my posting
directly.
I respond at the place that appears most appropriate for what
I want to say in the context I want to reply to. I'm not here
to serve your, umm, "standards" (to avoid the word "idee fixe");
and you just have to accept that[*], I fear.
I'm sure others here have no problem to go upward the thread
hierarchy one more level to find your text that I deliberately
didn't quote for the reason (still quoted above) I mentioned;
I don't think they're worth quoting, they provide no argument,
they were fuzzy. (Of course all only IMO.)
Tim Rentsch <[email protected]> writes:
Ben Bacarisse <[email protected]> writes:
Keith Thompson <[email protected]> writes:
Tim Rentsch <[email protected]> writes:
Keith Thompson <[email protected]> writes:
I know that "call by reference" is the usual formal term, but
I personally prefer "pass by reference".
The terms "call by reference" and "call by value" emphasize
the call, implying that all arguments in a given call are
passed with the same mechanism. In some languages that's
true (C argument passing is purely by value, and Fortran, as
I understand it, is purely by reference), but in others (C++,
Pascal, Ada) you can select by-value or by-reference for each
parameter. "Pass by (reference|value)" feels more precise.
I haven't checked, but I suspect the terms "call by
(reference|value)" predate languages that allowed the
mechanism to be specified for each parameter.
I suspect that your guess here is influenced more by what
you would like to be true than what is likely to be true.
I was influenced by what I thought made the most sense.
What is likely to be true is that these terms entered the
language at essentially the same time as the original Algol.
Algol 60 has both call by name and call by value, referred to
by those names in the Algol 60 Report, and selectable on a
per-parameter basis.
By contrast the precursor to Algol 60, the International
Algebraic Language or IAL for short (and referred to after the
fact as Algol 58) did not use either term, and described the
coupling between arguments and parameters only in somewhat
vague English prose that left unclear exactly what the binding
mechanism(s) were to be. (There was a description for
functions and a separate description for procedures, not quite
the same, and both not completely clear exactly what the
mechanism was meant to be.)
Thus it seems likely that the terms call by name, call by
value, and perhaps other similar terms, first arose during the
discussions of the Algol 60 working group in the late 1950s,
and entered the general lexicon with or perhaps slightly before
the publication of the Algol 60 Report, which describes and
allows both call by name and call by value, selectable on a
per-parameter base, and referred to by those names in the
published Algol 60 Report.
Yes, that does seem likely.
I'm mildly disappointed. Since arguments are *passed* and
functions/procedures are *called*, surely it would have made
more sense to use "pass by value" rather than "call by value",
especially in a language where the mechanism can vary per
parameter.
All that is, I think, due to subsequent changes in (English)
language use. In Algol 60, procedures were invoked and
/parameters/ were called by value or name. Maybe the term was
intended to reflect the idea that the code in the body "called
for the value" of the parameter.
The word "call" now refers, almost universally, to invoking a
function or procedure. As a result, the idea of "calling a
parameter" reads oddly, but at the time I'm sure it seemed
perfectly reasonable.
This view simply doesn't match the language and phrasing used
during the time Algol was being developed. Both the Algol 60
report and the preliminary IAL report (aka Algol 58) routinely
use the word call in connection with outside use of a procedure.
Algol 60 uses the word "invoke" exactly twice: once in relation
to procedures (where "call" is also used), and once in relation
to functions. Algol 58 uses the word call pretty much the same
way that Algol 60 does, but doesn't use the word "invoke" at all;
the verb "initiate" a procedure in Algol 58 turned into "invoke"
a procedure in Algol 60. Clearly using "call" was already well
established in the late 1950s, and "invoke" came later.
Algol 58 (loosely) defined the semantics of procedure call by
textual expansion of the procedure body at the call site,
substituting the text of actual parameters for each occurrence of
the corresponding formal parameter in the procedure body. The
actual rules are more complicated, due to there being different
"styles" (my word) of parameters, and because there were output
parameters as well as input parameters. Basically though the
meaning was what would later be termed "call by name", with some
restrictions on what forms of actual parameters were allowed.
Algol 60 simplified the rules by reducing the number of cases to
just two: either the actual parameter was textually substituted
for the formal parameter in the expansion (call by name), or the
value of the actual parameter expression was in effect assigned
to a local variable corresponding to the formal parameter (call
by value), which did not have a corresponding case in Algol 58.
The "call by" in "call by name" and "call by value" refers to how
the expansion is done in elaborating the procedure call. The
"call by" is not what sort of thing is passed, but what action is
taken in doing the substitution/expansion.
(Yes, this is my opinion.)
If there's some reason why "call by value" actually made more
sense than "pass by value", I'm not aware of it.
Since the phrase "pass by value" is now in common use, I'll
continue to use that term in preference to "call by value"
(likewise "by reference").
I use those terms too. It would be confusing these days to talk
about calling a parameter, and the phrase "call by value" suggests
(as it never did at the time) something so do with the function
calling mechanism in general.
Yes it did. It is only now that we have a different idea about
how functions and procedures are called that it seems like it
doesn't. But in Algol 60 it certainly did have something to do
with how a function reference was elaborated (aka called).
This is compounded by the fact that modern programming languages
has almost universally settled on calling all parameters by value
(to the use the old phrase) so, usually, the terms can, in fact,
be used to talk about the function calling mechanism.
The rationale here seems circular to me, and also not an accurate
picture of the programming language landscape.
Passing a pointer by value is not the same as a call be reference.
Passing a lambda by value is not the same as a call by name.
Shortly after Algol 60, FORTRAN adopted call by value/result,
also called call by copy in/copy out. Ada has INOUT, does
it not?
Logic programming languages have call by unification.
All of these cases show why "pass by" is not a good universal
fit.
How? All I see is that you've used the word "call" rather than
"pass" in each instance -- and in each instance, I find "pass"
clearer (except perhaps in the case of "call by name", for reasons
I won't go into for the moment).
At their lowest level, computers are simply slinging bits around.
In some sense everything is done in terms of "values". Thinking
in terms of what "value" is "passed" serves to reinforce an
imperative mind set, and there is already too much of that. For
these reasons and more I disdain the hoi polloi phrasing of "pass
by" for distinguishing different parameter modalities.
I honestly do not understand the argument you're making in favor of
"call by" over "pass by". ("Hoi polloi"? Seriously?)
Procedures and functions are "called", yes? They're not "passed",
except perhaps as an argument to another procedure or function.
Arguments to procedures and functions are "passed", yes? Would it
make sense to say that an argument is "called"? (I note that the
Algol 60 report never refers to parameters being "called" other than
in the phrases "call by value" and "call by name".)
If you think that "calling an argument" or "calling a parameter"
makes sense, perhaps that's the root of the disagreement. Do you?
In most languages that supports by both by-value and by-reference
mechanisms, a single call can have one by-value argument and one
by-reference argument, or any other combination. Using C++ as a
convenient example:
void func(int by_value, int& by_reference) { /* ... */ }
int x, y;
func(x, y);
In the third line, there is just one call, but two arguments,
corresponding to two parameters. It's not the call that's by-value
or by-reference, it's each argument that's *passed* (using the
mechanism specified on the parameter).
Other than historical precedent from Algol and friends, why do you
think it's better to use "call by value" and "call by reference"
rather than "pass by value" and "pass by reference", when the
mechanism applies individually to each argument, not to the call as
a whole?
Do you object to using the word "pass" (without "by ...") to refer
to the arguments to a function? If not, why do you object to "pass
by ..." to refer to the mechanism?
I won't ask you to reply to this.
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 12:06:32 |
| Calls: | 12,100 |
| Files: | 15,003 |
| Messages: | 6,517,999 |