After a long history with C
and C++
, I've only relatively recently become a programming-language polyglot started working in earnest with newer languages, specifically Groovy
, and to a far lesser degree, Python
.
RE: "pass-by-reference languages", I'd like to understand the rule (or rule-of-thumb) which variables are passed by function and which are passed by value ^.
I've written two equivalent programs in Jenkins/Groovy
and Python
. The programs demonstrate that an integer is passed by value, but a dictionary is passed by reference:
def dfunc(v) {
v.foo = "dolor"
v = [a:"a", b:"b"]
}
def podfunc(v) { v = 42 }
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
def my_dict = [foo: "lorem", bar: "ipsum"]
def my_int = 5
echo my_dict.toString()
dfunc(my_dict)
echo my_dict.toString()
echo my_int.toString()
podfunc(my_int)
echo my_int.toString()
}
}
}
}
}
def dfunc(d):
d["foo"] = "dolor"
d = { "a": "a", "b": "b" }
def podfunc(d):
d = 42
my_dict = { "foo": "lorem", "bar": "ipsum" }
my_int = 5
print(my_dict)
dfunc(my_dict)
print(my_dict)
print(my_int)
podfunc(my_int)
print(my_int)
The output of both the above are effectively:
{'foo': 'lorem', 'bar': 'ipsum'}
{'foo': 'dolor', 'bar': 'ipsum'}
5
5
(with language-specific variation on bracing, etc.)
I think that another way of looking at this -- but I'm not sure if this is correct -- is perhaps that the languages aren't so much "pass-by-reference" as they are "pass-by-value, but certain variables are implicitly created on the heap".
In other words, I'm inferring that in Groovy
and Python
, when I call either dfunc(d)
or podfunc(d)
, in both cases, I am technically passing by value; it's just "primitives" like the implicit integer my_int
are created on the stack, and "other variables", like the implicit dictionary my_dict
are created on the heap.
Is this a correct interpretation of why some variables appear to be passed by value and others passed by reference?
If so, which variables are implicitly created on the stack/heap, and why? And is this coder-controllable?
To my poor C
-biased eyes, there's nothing about these two variables' declarations that self-evidences which is created on the stack and which is created on the heap:
def my_dict = [foo: "lorem", bar: "ipsum"]
def my_int = 5
The closest existing discussion I was able to find were these:
Groovy (or Java) - Pass by reference into a wrapper object
What's the difference between passing by reference vs. passing by value?
...but either I'm not fully appreciating the existing answers, or they're not quite addressing my question as stated above.
Thanks for helping me grok this.
^ @juanpa.arrivillaga corrected me: the programs do not demonstrate that anything is passed by reference - this question, inevitably, becomes about the misapplication of the phrase "pass by reference".