5 ms·
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 t
by jasode 10y ago
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" definition. The C and Go languages don't have this type of "reference".
- "reference" definition 2: a pointer variable that lets programmers change the "thing pointed to" instead of the pointer variable itself to avoid copying unnecessary bytes. This is the colloquial usage. It also doesn't help that we call the star operator the "de-REFERENCING" operator[2] instead of the "de-POINTERIZING" operator. (What are we "derefencing" if it's not a "reference"?!?)
Cheney is talking about definition 1.
[1] http://www.di-srv.unisa.it/~vitsca/LAB/C-faq.html http://www.di-srv.unisa.it/~vitsca/LAB/C-faq.html excerpt:
4.11: Does C even have "pass by reference"?
A: Not really. Strictly speaking, C always uses pass by value.
You can simulate pass by reference yourself, by defining
functions which accept pointers and then using the & operator
when calling, and the compiler will essentially simulate it for
you when you pass an array to a function (by passing a pointer
instead, see question 6.4 et al.). However, C has nothing truly
equivalent to formal pass by reference or C++ reference
parameters. (On the other hand, function-like preprocessor
macros can provide a form of "pass by name".)
[2] https://en.wikipedia.org/wiki/Dereference_operator https://en.wikipedia.org/wiki/Dereference_operator
- dtzur 10y agoYap, your comment is better than the entire article. Thanks!
- mannykannot 10y agoIndeed. 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 modify the objects you gave as arguments, or incorporate them by reference into some other object, and how arguments that are expressions are handled. Some of those distinctions become blurred when pointers or references are passed by value; the distinction on how you pass them now becomes a distinction on what you pass. In practice, is there any language that passes pointers or references by reference?
- kazinator 10y agoDon't know of any mainstream Lisp with "pass by name". Which dialects have or had that?
- lvh 10y agoNot 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.)
- mannykannot 10y agoIt 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 https://www.cl.cam.ac.uk/teaching/1213/ConceptsPL/l4.pdf
- kazinator 10y agohttps://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_name 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.
- kazinator 10y agoAh! 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 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.)
- jobu 10y agoAren'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.
- fjdlwlv 10y agoYes.
- thinkpad20 10y agoThis has always bugged me too. I don't understand why people make such a big deal about pass-by-value and pass-by-reference when the latter is essentially a small layer of syntactic sugar over the former. Anything you can do with reference variables can be done with pointers, with a few more characters (and arguably easier to read, if you're not used to reference variables), so from a semantic point of view it doesn't add anything new. PBV and PBR seems to be a tiny distinction and yet, we have blog posts and interview questions and online debates about whether a language falls into the first or second category.
- paulddraper 10y agoAnd Java just added to the problem. For PR reasons, they didn't want to have "pointers" (arithmetic, etc. ew). So Java has "references". But what happens when you call a method on a null reference? Not NullReferenceException, but NullPointerException.
- coldtea 10y ago>For PR reasons, they didn't want to have "pointers" (arithmetic, etc. ew). So Java has "references" Well, it's just a rename for PR reasons. They actually don't have pointers. >But what happens when you call a method on a null reference? Not NullReferenceException, but NullPointerException. That's because it's the underlying pointer access that causes the exception. Doesn't mean the reference is itself a pointer -- it just abstracts over one.
- paulddraper 10y ago> They actually don't have pointers. They do. Everywhere. Every Java variable of Object type is a pointer. (Also, they're all nullable....ugh.) If Java had real references (see original comment by jasode) you'd be able to write something like C#'s int.TryParse ( https://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/f02979c7(v=vs.110).... ).
- coldtea 10y ago>Every Java variable of Object type is a pointer. No, it's a reference. It just has a pointer underneath. >If Java had real references (see original comment by jasode) you'd be able to write something like C#'s int.TryParse If Java had one specific type of references. The common use of the term though is still what Java has.
- paulddraper 10y ago> The common use of the term though is still what Java has. The way you are defining "reference" makes it immaterially different from "pointer". Can a pointer be null? Yes, in C. Can a "reference" be null? Yes, in Java. Can a pointer be used in arithmetic operations? Yes, in C. Can a pointer not be used in arithmetic operations? Yes, in Go. If this is really the common definition, it isn't a useful one.
- wyuenho 10y agoThank you sir for pointing this out. I recently ran into a similar argument with an Oracle trainer whether Java has pass-by-reference semantics. The entire Java community seems adamant that Java has no pass-by-reference, but only pass-by-value. This blog post reminds me of that argument. In Java, Python, Javascript and many other languages, objects pointers are passed by value, but the contents of which are shared between the caller and the callee, so the modification of which is visible from both sides. If we take the definition of pass-by-reference or call-by-reference semantics to mean that, then these languages are pass by reference by default. Apparently, that's not the definition, which in my opinion is rather strange that we are still stuck in a definition that predates OOP, when people mostly concerned with simple primitive values as opposed to composites. It appears that Barbara Liskov has recognised this and coined call-by-sharing in 1974. 43 years later, practitioners are still arguing in the C++ frame of mind and failed to disseminate the more modern and suitable term of call-by-sharing. This is rather disappointing to me.
- lowbloodsugar 10y agoI've got a credit in a game by pointing out that the reason the teams tools kept segfaulting was because the authors believed that if they had a reference they didn't need to check it for null. Unfortunately, they'd assign these references from pointers that could totally be null, and didn't error check at that point. References in C++ can totally be null.
- evanpw 10y agoThat's undefined behavior. References in valid C++ cannot be null.
- lowbloodsugar 10y agoI can write a method that is valid C++, but it gets called by something that isn't valid C++. If I don't check for null references, then my method will crash. My method is valid C++, and yet it gets a null reference. So clearly, references in valid C++ can be null, and must be checked for.