Anyone you find in the real world under ~30 years old may not even be aware that you can pass a reference and modify it directly without having to make a method return a value.
It's super cool to have someone explain to you side effects yet you show them a method with a null return and run it for them showing that the value has changed and they are mesmerized.
This is false and ageist. I got a computer engineering degree at a non elite state school very recently and this was covered in the first c++ and c classes. For that matter c# has an “out” variable that mimics this functionality, and the intro Java class covered primitive types vs. reference types. While reference types in Java aren’t the exact same thing, they do allow a void function to modify the state of the caller by modifying a parameter passed to the function.
I doubt that you can make an absolute "this is false and ageist" statement in any context, but here on HN, I would have at least expected you to supply information on what location in the world and level of institutional schooling you have.
Here in north-west EU C and C++ haven't been a part of the core curriculum for over 25 years (unless you do embedded work), and code with side-effects in desktop-class systems has been frowned upon for nearly as long due to the need for more cookie-cutter engineers to fill positions and write code that might still be OOP but has to be almost as side-effect free as functional code.
Basic/core languages are still (last time I checked when doing guest lectures ~ 6mo ago) Java, C#, Python and the mixed bag that is web languages.
This is also influenced by the core program required to be an accredited institution and the large amount of consultancies people end up working at straight out of college/school/uni. This even still happens in infrastructure-centric programs where you do lean a bit about TCP/IP and OSI layers, but then essentially get dumped into Juniper/Cisco/vmware/microsoft school which almost always gets them vendor-locked and unaware of the actual concepts and abstractions they implement.
So no, not knowing the difference between passing references or values, or pointers and dereferencing them is not as strange as you seem to think it is. It is not a piece of knowledge or experience that is seen as valuable enough by the people that create the curriculum or the companies that employ the largest quantities of inexperienced workers in this part of the world.
The core project for my compilers course in Germany in 2016 was about writing a C compiler in C++. I didn't do my intro courses at that university, but the professor clearly assumed all the students were already familiar with the language.
A lot of people seem to underestimate the prevalence of C/C++. I've had people tell me that C/C++ is completely dead and the future is machine learning entirely written in Python, but the machine learning models they're using still usually have parts hand-tuned in C/C++, or even assembly.
I work at a fairly large Python shop and we have some real performance problems with Python.
Most real world software will use many core libraries implemented in C/C++ for doing the heavy lifting. Just the FFI and creating all those Python objects makes it slow.
Python is a great language for prototyping and/or usage as a glue code.
Personally, I am more inclined to use Go for anything quick and performant. If Carbon language becomes a reality, I would bet on that since it allows seamless interoperability with C++ (and there is a large existing eco system). Else, time to learn Rust.
There isn't even a compilers course here, unless you go for a science masters. This likely got shaped this way due to the lack of interest and a push from industry to deliver more 'ready to use' engineers.
I went to a small Wisconsin state school, grad with a BS in CS in 2009. We learned C, operating systems, and had a compiler class. Definitely not useful in my day job, but it was fundamental in my understanding of programming languages and computing. Can’t believe there would be a CS program out there that would skip this.
I do know there are programs out there that focus on different aspects though, and not surprised they would be geared to make people more job ready. We actually didn’t really learn about unit testing, and such, so it’s a balance.
I'm a PM and I ended up graduating with an econ BA instead of a CS degree, but I took a few intro CS classes at UCLA in...2011/2012.
Intro to Programming 1 and 2 were taught in C++. Can't remember which one taught pass by reference, but it was definitely in one of those two.
Third class I took was Intro to Systems or something like that. The whole class was C and x86 ASM. Lots of binary operations in that one, used K&R a fair amount in that class (also learned debugging assembly in GDB and some other "low-level"-ish stuff).
Just looked it up, can't say 100% it's still C++, but the syllabus looks about the same as I remember for both class. It gets to pointers by week 7, and then in the second class goes deeper:
And again, I didn't even get a CS degree. This was all lower-div CS work at a public university, and I'm not even a career engineer.
> So no, not knowing the difference between passing references or values, or pointers and dereferencing them is not as strange as you seem to think it is. It is not a piece of knowledge or experience that is seen as valuable enough by the people that create the curriculum or the companies that employ the largest quantities of inexperienced workers in this part of the world.
This attitude is why you're getting flak in this thread. Your claim that "We don't teach pass by reference these days" was too absolute, and not accurate for a ton of people. Then someone came back and told you that, and you told them that their claim was too absolute.
I'll also say that it's something that was absolutely valued around the orgs I worked in at Microsoft (Azure, DevDiv, Windows, very roughly bottom half of the stack teams). If not C/C++ pointers, than __absolutely__ passing by reference in C#.
Point being: __knowing__ about pointers, passing by ref vs. value, etc. is not as strange as __you__ seem to think it is.
I never stated my own position on this piece of knowledge, so no, __I__ did not have anything to do with your point.
C and C++ (and Assembly and compilers) are not part of the standard college software engineering curriculum here. Your opinion on that doesn't matter (just like mine doesn't matter) because it is a verifiable fact. And as such, it is also not strange to not see this bit of knowledge being prevalent. K&R isn't used much except if you are either taking the purely theoretical CS degree courses or if you tack them on to the normal required courses. Even the Gang of Four is only mentioned in passing when talking about patterns.
You __could__ argue if this is foundational knowledge, and if so, you __could__ argue that therefore the curriculum is in need of adjustment. But I didn't.
Regarding what this was all about (WrtCdEvrydy's comment), he might be talking out of the wrong hole, or he might be in a similar location as I am where this is how it works and that might be different from where you are.
My 2014 undergraduate degree from an engineering school on the east coast included two required tracks, one for data structures/algorithms taught in Java and a computer systemsey track that taught C, Linux, and some operating system essentials.
I think an operating systems course, or something approaching it, is a pretty standard piece of good CS curriculums in the US still from talking with other folks I've worked with. And I live/work very far from where I got my degree.
C# also has “ref” arguments. The difference is that out arguments are required to be assigned during the execution of the method while ref arguments don’t have to be set.
I don't think any of the languages you mentioned support true pass-by-reference. (maybe C# and Java, but it's not common) I've heard what you're describing as "pass-by-value-reference" Go, however, supports pass-by-reference which allows you to write a function like this:
func swap(x *int, y *int) {
var temp int
temp = *x /* save the value at address x */
*x = *y /* put y into x */
*y = temp /* put temp into y */
}
Sure, you can't have the same code for Python, for instance, even if it was using objects, but you can have the same effect using a hack by copying the __dict__ from one object to another. However, you are still passing the object to a function by reference because the function can mutate the object and the object that the callee passed will also be mutated the same way, i.e. mutable objects are passed by reference, and values are passed as values. Which is how python, javascript, Java and the rest work. Obviously, you don't get to change what the reference is pointing to in most of these languages, but you can change the value that is being pointed to.
Passing a reference is semantically different from passing by reference (the latter being a functionality of the language); doing the former (behind the scenes) doesn't imply that the language supports the latter (if one wants to be rigorous, not even C supports pass by reference).
The canonical example is a function that swaps the variables passed to a function:
a, b = 10, 20
swap_fn(&a, &b)
a == 20 # true
Since the above are primitive data types (ints), in order to make this work, the language needs to generically support passing the address (reference) of the variables. Java¹/Python² etc. are not able to do this; they copy the value of the variable and send it to the function, which will operate on the copy.
¹=at least, last time I've checked, which was long ago :)
²=funny to think that at least in Python, one can mess with the global register of the variables, and actually accomplish that
I understand it is semantically different, but the interviewer should not be surprised you can change a variable in a function without returning it, which is the context of this thread. It's syntactic sugar for pointers.
Python 3.10.8 (main, Oct 13 2022, 09:48:40) [Clang 14.0.0 (clang-1400.0.29.102)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def f(d):
... d['foo'] = 'bar'
...
>>> a = {}
>>> f(a)
>>> a
{'foo': 'bar'}
That example actually holds with what the parent comment said. You aren't trying to modify d exactly, you're modifying d's contents.
Python 3.8.10 (default, Jun 22 2022, 20:18:18)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more
information.
>>> def f(d):
... d = {'foo': 'bar'}
...
>>> a = {}
>>> f(a)
>>> a
{}
does not modify the passed in dictionary, because the reference 'd' itself is passed by value. So the function doesn't change what d references for the caller. Java works the same way.
My understanding of what's going on with python is it passes by reference (hence what your code does), but if the data type is immutable any modification results in a new instance being created in the scope of the function, and the object passed in is not modified. Which mostly looks like pass-by-value behaviour.
I guess my understanding could be technically wrong in some way, but it seems to reflect what happens.
The issue is that Python passes references by value, so you cannot overwrite what the arguments of a function reference from the perspective of the caller. However, if you pass something like a dictionary or a class the function gets a copy of the reference and can use it to update the members of what was passed. Java operates on the same principle, although there may be some edge cases I'm not aware of where the two differ.
I don't believe they're saying the feature doesn't exist or never gets used, but rather it's rarely something that's taught to junior developers, and rarely something you see highlighted as a best practice.
I've been developing for 25+ years in any language you can imagine, and know how to use pass by ref just fine, and know there are situations where it might be the best solution.
But I can't remember the last time I've used pass by ref. It's really just a coding style quirk for me, I find it "ugly" and it breaks my train of thought when reasoning through the flow of code. I certainly don't begrudge anyone who uses it though.
And OP's anecdote about the interview is certainly disheartening. You'd hope the interviewer would at least be open to the idea of learning something new. I've learned countless things from developers I've interviewed over the years, and I was incredibly happy about it each time.
Edit: In re-reading your comment and below replies it seems you may be misunderstanding what's being discussed. Yes, the things we pass into and out of functions tend to be object references by default. But when we say "pass by ref" (in some languages at least) we mean, essentially, modifying a value in a calling function without actually returning anything from the called function. That's a horrible way to explain it, but the MS documents for the "ref" keyword do a good job of showing examples:
It's like the other day there was a post where someone wrote an entire blog post about how they changed a tight loop with a function call in Golang to pass a pointer to a struct instead of by-value so they stopped allocating and copying on each call.
Like...duh?
I suppose that's why I find Golang less weird to work with than others in my cohort. I spent a semester in the depths of C and OpenGL so I'm intimately familiar with by-value vs by-ref.
Yes, I understand... But the result, practically speaking, is objects are passed by reference, just like I said. Methods/functions can modify their parameters.
It's been a while, but my understanding was that actual C++ references were immutable, and what you are describing can only happen as a result of passing a pointer by value.
All those languages pass by value and it's kind of embarrassing that you mixed it up while criticizing someone else for not knowing it.
One necessary (but insufficient) test you can use to determine if your language has call by reference or call by value is whether you can implement a swap function. In the languages you list, a swap function is not possible to implement, whereas in C++ it is, which tells you that those languages do not implement pass by reference.
We are actually both wrong. If they passed objects by value you'd be modifying a copy. They technically "pass by object reference" as another poster mentioned.
ECMAScript's Language Specification also states in section 10.6 that it uses pass by value semantics, although it's much more formal about the specific approach it uses:
I can't link to the specific section but you can review the semantics of MakeArgGetter and MakeArgSetter which are specified to produce arguments bound to the *value* associated with the name, as opposed to a reference.
Python does not have a spec that I can reference, but given that its argument semantics follows those of Java, and once again the inability to write a swap function, it should not be too difficult to deduce that Python also passes by value.
This is indeed correct. Object references themselves in Java/Python are passed by value, which is why the following two code samples do not have the same effect:
Python 3.8.10 (default, Jun 22 2022, 20:18:18)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def f(d):
... d['foo'] 'bar'}
...
>>> a = {}
>>> f(a)
>>> a
{'foo': 'bar'}
Python 3.8.10 (default, Jun 22 2022, 20:18:18)
[GCC 9.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def f(d):
... d = {'foo': 'bar'}
...
>>> a = {}
>>> f(a)
>>> a
{}
I said they pass objects by reference, which is true. Technically, yes, Java is pass by value. However, objects are not passed by value. The value you are passing is a reference (pointer) to that object. If this were not the case, you would not be able to see modifications to method parameters reflected in the caller because you're modifying a copy. You are not modifying a copy.
I'm definitely nitpicking here, but I'd say almost all languages use pass-by-value, and what you're talking about is copying a pointer. C++ actually has true pass by reference, nothing is copied in memory.
In addition to pass by value and by reference, there's also a pass by descriptor mechanism. It's not widely supported, but it's just another way to glue different conventions for defining arrays in various languages, where it's not just a raw pointer to alloc'd memory.
At one interview, as a joke at the end, the set of interviewers asked me if I could write code to reverse a string. I replied, "In place, or...?" which apparently confused some of them.
Anyone you find in the real world under ~30 years old may not even be aware that you can pass a reference and modify it directly without having to make a method return a value.
It's super cool to have someone explain to you side effects yet you show them a method with a null return and run it for them showing that the value has changed and they are mesmerized.