Live data from Hacker News

There is no pass by reference in Go

dave.cheney.net

21–30 of 70 posts

Re: There is no pass by reference in Go

#21
post #11
post #7

Earlier quoted context omitted.

I guess in every language with pointers, people often confuse passing the pointer as a value with passing the object as a reference.

I'm still confused and I've been working in various languages for 15 years. If I pass a java object to a function, I'm passing a (probably) 8-byte pointer to some memory with a class tag, fields, whatever. It goes on the stack just like an 8 byte long. In languages that support pointers more directly, I'm doing the same thing, maybe minus the class tag in the pointed-to memory. Address is in an 8 byte type, put it on…

In all of those cases, you're probably passing a reference by value, semantically. ("Probably", because you didn't specify which languages, so I'm making an educated guess.)

The usual litmus test is having two objects (or ints or whatever), write a fn `swap(a, b)` where the two are swapped after the call is over. Can't do that in Java or Go or Python or C; but you can in e.g. C++ and you sorta-can in Lisp. In C++, you'd see int& (or whatever) show up in the arguments of swap().

Re: There is no pass by reference in Go

#22
post #21
post #11

Earlier quoted context omitted.

I'm still confused and I've been working in various languages for 15 years. If I pass a java object to a function, I'm passing a (probably) 8-byte pointer to some memory with a class tag, fields, whatever. It goes on the stack just like an 8 byte long. In languages that support pointers more directly, I'm doing the same thing, maybe minus the class tag in the pointed-to memory. Address is in an 8 byte type, put it on…

In all of those cases, you're probably passing a reference by value, semantically. ("Probably", because you didn't specify which languages, so I'm making an educated guess.) The usual litmus test is having two objects (or ints or whatever), write a fn `swap(a, b)` where the two are swapped after the call is over. Can't do that in Java or Go or Python or C; but you can in e.g. C++ and you sorta-can in Lisp. In C++, yo…

Ok, yeah, I saw upthread about C++ and Pascal having a more formal reference type.

But in C and Go you can pass pointers to pointers, in Java and Python objects with mutable object references..

It seems like the whole article could have been "Go does not have the C++ reference type, so it's not really in the mix when calling functions".

Re: There is no pass by reference in Go

#23

It's a question of semantics and the poorly chosen word "reference". The roots come from C, where pretty much every book on the subject talked about the difference between passing a huge, expensive value to a function vs passing a cheap pointer "reference" to it. And while the semantic purists will scream and holler, the fact remains that, colloquially, a pointer is a reference to something, not the something itself.…

Nobody is debating what the word "reference" means. The debate is that "pass-by-reference" is already a different thing from passing something __as__ a reference.

I appreciate that it's confusing to someone who isn't familiar with the term, but so's most of CS. We had a term and it referred to a thing, and having it refer to two different things is worse.

Re: There is no pass by reference in Go

#24
post #22
post #21

Earlier quoted context omitted.

In all of those cases, you're probably passing a reference by value, semantically. ("Probably", because you didn't specify which languages, so I'm making an educated guess.) The usual litmus test is having two objects (or ints or whatever), write a fn `swap(a, b)` where the two are swapped after the call is over. Can't do that in Java or Go or Python or C; but you can in e.g. C++ and you sorta-can in Lisp. In C++, yo…

Ok, yeah, I saw upthread about C++ and Pascal having a more formal reference type. But in C and Go you can pass pointers to pointers, in Java and Python objects with mutable object references.. It seems like the whole article could have been "Go does not have the C++ reference type, so it's not really in the mix when calling functions".

Yep. "Reference type" is a confused and overloaded term, so I prefer to say "pass-by-reference" when I meant int& and "pass-as-reference" (or the, in my opinion confused and confusing, pass-by-object, if that's helpful to the listener).

Re: There is no pass by reference in Go

#25

Earlier quoted context omitted.

Indeed. Definition 2 is broadly in line with what "reference" means in general usage, while definition 1 is a term of art in the vocabulary of certain languages. Before languages had reference types or pointers, the distinction between pass-by-reference and pass-by-value (or also pass-by-name in Lisp and Algol) told you important things about the semantics of the language, such as whether a function you called could…

Don't know of any mainstream Lisp with "pass by name". Which dialects have or had that?

Not the author, but they may be referring to NLAMBDA/FEXPR. (That hasn't been in Lisp since the eighties, because, well, Lisp had better tools. NLMABDA/FEXPR basically made AOT compiling Lisp impossible, and all of the use cases were much more neatly handled by a macro system.)

Re: There is no pass by reference in Go

#26
post #14

Doesn't the post stumble over right in the second section? "It is not possible to create a Go program where two variables share the same storage location in memory". So what? The C example didn't show that either.

You are correct that C also does not have pass-by-reference. However, the second listing is a C++ program, not a C program, and C++ very much has pass-by-reference. The C++ program demonstrates true aliases, as you can tell from the output of the printf (see comment on same line).

Re: There is no pass by reference in Go

#27
post #23

It's a question of semantics and the poorly chosen word "reference". The roots come from C, where pretty much every book on the subject talked about the difference between passing a huge, expensive value to a function vs passing a cheap pointer "reference" to it. And while the semantic purists will scream and holler, the fact remains that, colloquially, a pointer is a reference to something, not the something itself.…

Nobody is debating what the word "reference" means. The debate is that "pass-by-reference" is already a different thing from passing something __as__ a reference. I appreciate that it's confusing to someone who isn't familiar with the term, but so's most of CS. We had a term and it referred to a thing, and having it refer to two different things is worse.

And yet this is the reality we live in. No matter how much talk of "should", the reality stares you implacably in the face. This is a UX problem.

Practically speaking, the most important concept is that of cost, which the naive answer covers. The distinction only matters in a language that actually differentiates the two. Otherwise it's little more than trivia, and certainly nothing to get worked up over.

Re: There is no pass by reference in Go

#28
Minor nit...

> It is not possible to create a Go program where two variables share the same storage location in memory.

It is possible to do so, because the empty struct occupies no space. For example:

    s := []struct{}{
        struct{}{},
        struct{}{},
    }
    fmt.Printf("%p %p\n", &s[0], &s[1])

    > 0x176f44 0x176f44
But that's kind of a fringe case, and I suppose one might argue that the two variables occupy no space so in a sense they don't share that space. Either way it doesn't detract from the original point of the post :)

Re: There is no pass by reference in Go

#29
post #26
post #14

Doesn't the post stumble over right in the second section? "It is not possible to create a Go program where two variables share the same storage location in memory". So what? The C example didn't show that either.

You are correct that C also does not have pass-by-reference. However, the second listing is a C++ program, not a C program, and C++ very much has pass-by-reference. The C++ program demonstrates true aliases, as you can tell from the output of the printf (see comment on same line).

I have always found that is conflating the semantics of using with the method of passing. Even with/out aliases you are still passing a reference.

Re: There is no pass by reference in Go

#30
post #25

Earlier quoted context omitted.

Don't know of any mainstream Lisp with "pass by name". Which dialects have or had that?

Not the author, but they may be referring to NLAMBDA/FEXPR. (That hasn't been in Lisp since the eighties, because, well, Lisp had better tools. NLMABDA/FEXPR basically made AOT compiling Lisp impossible, and all of the use cases were much more neatly handled by a macro system.)

It has been a while since I used any form of Lisp, but nlambda seems to be what I was remembering as pass-by-name (and hand-annotated as deprecated, here:) https://www.cl.cam.ac.uk/teaching/1213/ConceptsPL/l4.pdf
Post reply on HN