Live data from Hacker News

There is no pass by reference in Go

dave.cheney.net

31–40 of 70 posts

Re: There is no pass by reference in Go

#31
post #23

Earlier quoted context omitted.

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.

The difference between pass-as-reference and pass-by-reference is more than trivia - if you were ignorant of it in a language, you might find trouble in the future when a function decides to alter its argument values in a way that negatively affects the caller. Part of the reason we should work to clarify the language is to avoid misconceptions about behaviour based on what kind of "reference" is meant.

Re: There is no pass by reference in Go

#32
post #10

An extended explanation missing from Dave Cheney's answer is that the "reference" etymology has at least 2 meanings. This is why his explanation is virtually the same as the one 20 years ago in the C Language FAQ[1] compiled by Steve Summit. - "reference" definition 1: an alias that cannot be null which is what a "reference type" is in Pascal and C++. This might be thought of as a stricter "computer-science" definiti…

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…

Object Pascal (Delphi, Free Pascal) allows this. You can use a var (variable) parameter to pass any type by reference to a function/procedure/method. This is used quite a bit in the Win32 API interface units in the run-time library because it simplifies the usage of the API by removing the requirement for double indirection when dealing with pointer parameters that need to be updated by the callee, as well as pointers in general for other type/structure parameters that need to be updated by the callee. As the caller, instead of passing a pointer to a structure as a parameter, you simply pass the structure. There are also out parameters that work similarly, but are, obviously, output-only.

In general, you can use pointers in Object Pascal, but the language offers a lot of options for avoiding them, if you want to, and you get type-checked references in the process. Records (structs) are stack-based and pass-by-value, by default, and class references/class instances (instances are always heap-allocated) are pass-by-reference, by default. So, for the majority of applications, you can use parameters in a myriad number of ways in order to improve performance or provide the proper calling semantics, without any of the hassle of address-of or de-referencing operators.

Re: There is no pass by reference in Go

#33
"Maps and channels are not references."

But then refer to the Go team's article on maps:

  Map types are reference types, like pointers or slices, and so the value of m above is nil; it doesn't point to an initialized map. A nil map behaves like an empty map when reading, but attempts to write to a nil map will cause a runtime panic; don't do that. To initialize a map, use the built in make function:
  
  m = make(map[string]int)
  
  The make function allocates and initializes a hash map data structure and returns a map value that points to it. The specifics of that data structure are an implementation detail of the runtime and are not specified by the language itself. In this article we will focus on the use of maps, not their implementation.
Saying maps are not passed by reference is a bit deceiving. The map's pointer location is not passed by reference.

Source: https://blog.golang.org/go-maps-in-action

Re: There is no pass by reference in Go

#34
post #20

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…

It may be what reference means, but just because a language has references doesn't mean that it is passing-by-reference. There are plenty of languages that allow actual pass-by-ref, like C++. The usual litmus test is writing a function that takes two ints (not int refs!) and they're swapped at the end. In C++, you can tell because of "int&" in the signature of the function you're calling; as opposed to plain int. In…

Whenever a word with a general meaning is adopted, and specialized, as a term of art, a double meaning is created. I get the impression that philosophy prefers to invent new words (unless it is reaching into the darkest corners of the vocabulary.)

What has happened here is that the double meaning of 'reference' has caused some confusion over the term pass-by-reference, which is purely a term of art. So long as a person understands what gets passed and, especially, its implications, I am not particularly bothered by the mistaken usage.

Re: There is no pass by reference in Go

#35
post #10

An extended explanation missing from Dave Cheney's answer is that the "reference" etymology has at least 2 meanings. This is why his explanation is virtually the same as the one 20 years ago in the C Language FAQ[1] compiled by Steve Summit. - "reference" definition 1: an alias that cannot be null which is what a "reference type" is in Pascal and C++. This might be thought of as a stricter "computer-science" definiti…

Aren't reference variables just syntactic sugar on top of pointers? I've seen this debate about pointers vs. references so many times that I'm starting to think I might be missing something.

Re: There is no pass by reference in Go

#36
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.)

https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_na...

Call by name is actually a closure based mechanism under the hood. It's like lazy evaluation, but with side effects allowed:

  (let ((0 42))
        (a #(1 2 3))
    (foo (aref a (incf i))))
If foo is call by name, then it receives a thunk (basically a lexical closure) for the argument. The aref expression is then evaluated inside foo whenever foo refers to the corresponding argument. (Unfortunately, repeating the incf side effect). We could simulate this with:

   (foo (lambda () (aref a (incf i)))
with foo using (funcall arg) to get the argument's value.

Call by need, described below that, seems exactly like the insertion of delay and force. The call-by-need argument expression is basically wrapped in an implicit delay, and callee refers to the argument value using implicit force. delay and force are just additional wrapping around a closure to add a flag to squash multiple evaluations.

Re: There is no pass by reference in Go

#37
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.)

Ah!

I just remembered I implemented some macros to simulate call by name in the TXR solution to the "Man or boy test" task on Rosetta Code:

https://rosettacode.org/wiki/Man_or_boy_test#TXR

With these macros, Knuth's test is expressed exactly in the original form (modulo the Algol being cast into S-exp syntax).

Call by name isn't just lambda with funcall (as might be wrongly inferred from my comments in the other reply), because it supports assignment. If we pass a variable A with call by name, the caller can assign to it. This all works with the given macros, and it probably more or less corresponds to the Algol mechanisms.

(The task description is "Imitate Knuth's example in Algol 60 in another language, as far as possible." so the solutions which don't actually implement a call-by-name syntax and semantics don't go as far as this solution.)

Re: There is no pass by reference in Go

#38
By this obtuse definition of 'pass by reference', Nothing with a C-like function call stack will 'pass by reference'. Programming languages that approximate 'pass by reference' will actually pass a pointer to the called function that points to a value in the callee's stack frame. The pointer in the called function is a local variable, so changing the value of that has no effect in the callee's scope. Changing the contents of the thing pointed to is the only _meaningful_ 'pass by reference', and practically most languages have that. (including Go)

Re: There is no pass by reference in Go

#39
post #20

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…

It may be what reference means, but just because a language has references doesn't mean that it is passing-by-reference. There are plenty of languages that allow actual pass-by-ref, like C++. The usual litmus test is writing a function that takes two ints (not int refs!) and they're swapped at the end. In C++, you can tell because of "int&" in the signature of the function you're calling; as opposed to plain int. In…

[deleted]

Re: There is no pass by reference in Go

#40
post #35
post #10

An extended explanation missing from Dave Cheney's answer is that the "reference" etymology has at least 2 meanings. This is why his explanation is virtually the same as the one 20 years ago in the C Language FAQ[1] compiled by Steve Summit. - "reference" definition 1: an alias that cannot be null which is what a "reference type" is in Pascal and C++. This might be thought of as a stricter "computer-science" definiti…

Aren't reference variables just syntactic sugar on top of pointers? I've seen this debate about pointers vs. references so many times that I'm starting to think I might be missing something.

Yes.
Post reply on HN