<p>One aspect of a dynamically typed language is that it is possible for a variable to change its type (the &quot;type&quot; of the value it holds) in the course of &quot;straight line code&quot;.</p>
<p>This would be code like:</p>
<pre><code>var a := readline(); // a is some string
a := length(a) &gt; 10; // a is now a boolean
if (a) {
   a := 5;            // a is now an integer
} else {
   a := &quot;foobar&quot;;     // a is now a string again
}
print a;
</code></pre>
<p>I'm specifically excluding the common case where a function formal argument (or a local in a function) gets a different type on separate <em>calls</em> to the function because on these separate calls the <em>actual</em> parameter is of a different type.</p>
<p>I'd also like to exclude the other common case where an ordinary expected conversion from string to some numeric type is done (or vice versa), e.g.,</p>
<pre><code>var a := readline(); // a is some string that represents a number, e.g., the string &quot;25&quot;
a := 3 * a;          // a is now represented internally as an integer
</code></pre>
<p>My question is: Are there any numbers (e.g., studies performed) on how often programmers of dynamic languages use variables this way?  Perhaps it is language specific (e.g., cultural)?  Or maybe there are particular algorithms where it is used while in others it is never used?  Maybe it just doesn't happen?</p>

<dynamic-typing><software-engineering>
Are there metrics on how often variables in dynamically-typed languages change their type (not "parametrically")
CC BY-SA 4.0
2023-08-14T17:40:38.977Z
I'm having some trouble understanding the last criterion. If we have `var a := <some string>; a := <some integer expression>;`, it will depend on whether or not `<some integer expression>` involves `a`? How do you determine whether or not to exclude this case?
David Young
CC BY-SA 4.0
2023-08-14T17:59:01.960Z
@DavidYoung - the example I gave the reassignment _does_ involve `a`.  BTW, to avoid a red herring due to the examples I gave: I'm not restricting this to _self_ assignment.  I just did that to make the examples small.  Any case where at some point in a function `a` is assigned an integer and then somewhere later in that function `a` is assigned something else (a struct, an array, a boolean, whatever) would count.  The point being that the _programmer_ deliberately used the _same variable_ to hold _different types_ during the same function (those types not due to an implicit conversion).
davidbak
CC BY-SA 4.0
2023-08-14T18:09:24.740Z
Is there a particular reason you want to exclude the most common cases?
kaya3
CC BY-SA 4.0
2023-08-14T19:27:34.263Z
@kaya3 - the parameter case - that's one of the frequently cited benefits of dynamic languages, that you get some form of polymorphism built-in, encouraging code reuse, etc.  the implicit coercion case - that (IMO) has wide variance between languages, how many different things get freely exchanged with the other (e.g., consider AWK and APL as two examples here), plus it is a common idiom in scripting languages.  What's left is _allowed_ by dynamic languages and it is sometimes touted as a benefit but I personally haven't seen any body of code that does it _as a rule_ and wondered about ...
davidbak
CC BY-SA 4.0
2023-08-14T19:27:49.250Z
... how often is it used by practicing programmers.  Plus, the answer, if known, may inform implementations and/or tools (e.g., IDEs, static analyzers).
davidbak
CC BY-SA 4.0
2023-08-14T21:13:57.950Z
@kaya3: If a language allows function overloading based upon the type of an argument, then each individual overload would always receive the same type.  In most cases where the lack of overloading in a dynamic language would make it necessary to check the type at runtime, therun-time type check would have been avoided if overloading were available.
supercat
CC BY-SA 4.0
2023-08-14T21:36:57.403Z
I strongly suspect that the answer to this question is currently “no”, but it is impossible to prove a negative. Still, there’s no harm in having the question around in case someone does such a study at some point in the future. It seems difficult to measure, though.
Alexis King
CC BY-SA 4.0
2023-08-15T00:13:58.597Z
I think you're asking the wrong question. You should ask how often this happens *after SSA renaming*. Any poly-type-ism that can be eliminated by renaming is "trivial" and won't affect the analysis of a compiler or IDE that's sophisticated enough to do partial type inference in the first place. All of your examples are eliminated by renaming except for `print a;` where `a` may be `5` or `"foobar"`.
benrg
CC BY-SA 4.0
2023-08-15T01:39:51.853Z
Do you count `null`/`undefined` as values of a separate type? Do structs with different fields have different types? How about class instances that share the same interface but not the same implementation?
Bergi
CC BY-SA 4.0
2023-08-15T01:57:01.497Z
@benrg - I'm not really asking about static analysis.  I totally get how that's done.  I'm asking about what we know about _programmers who code this way_.  Like I said, I haven't seen in in any code base.  (Though I quite agree it's unexceptional in REPLs.) I'm wondering what the _programmers_ think when they do this.  To put it in context: I'm a strong-typing kind of guy.  Starting with Pascal, on to Ada, various other paths, finally to ML/Haskell and rich type systems.  But how does the _other_ half live?
davidbak
CC BY-SA 4.0
2023-08-15T02:00:02.830Z
@Bergi - moving from null to some type and back - I get that.  That's standard in many languages.  E.g., C#/Java/anything with Optional.  So no, not that.  Structs with different fields/different types: That depends on the language surely - is a "struct" a bag of fields or is it something with ordered fields or fixed fields.  Interfaces are obviously not it, those are polymorphic by defn, and aren't really a feature of dynamic languages.  Seriously, I thought the question (and examples) were pretty clear.  These these are details of particular "type systems" but look at the big picture instead
davidbak
CC BY-SA 4.0
2023-08-15T08:03:27.527Z
its talked about in the TCL community as https://wiki.tcl-lang.org/page/shimmering not sure thaere are any stats ive seen on it though
jk.
CC BY-SA 4.0
2023-08-15T08:59:04.673Z
I would expect there is one factor which would significantly influence the result: whether the language makes rebinding/shadowing convenient (eg lisp) or not (eg python).  In the latter case, many cases of reassignment are logically intended to rebind, but in fact do not because that's inconvenient.  Another issue is subtyping.  If B <: A, C <: A, and a variable changes type from B to C, but the code only cares about its A-ness, does that count?
Moonchild
CC BY-SA 4.0
2023-08-16T04:22:24.257Z
I don't think the problem is well-defined. There are type systems and inference algorithms that will tell you that `a` has the consistent union type `string | boolean | integer` throughout the program, thus "no change" occurs. There are also systems that will say `a = 0; a = 1;` has moved `a` from one type to another.
Ryan Cavanaugh
<p>There have been many studies that touch on these questions, but none that I know of that follow the particular constraints you set out. A lot of work on type <em>inference</em> for dynamically-typed languages faces this issue, and often enough in practice that it comes up as something to be dealt with, while rarely enough that it's sometimes explicitly excluded from support. Some work has looked specifically at the use of dynamically-typed features on their own.</p>
<p>In most cases the relevant results are on the side of something else, either an inference engine or analysis of more complex dynamic features. It doesn't seem like anyone has looked specifically at reassignment, which I do find a little surprising. I can point at some previous work, but I think to match the specific goals you have in mind you'll need to run the study yourself.</p>
<p>Further down I'll note some limitations, and other cases that may or may not be in scope here. Exactly what it means for a variable to hold a new type is potentially a bit tricky to nail down. For example, what constitutes a type in these languages? is it necessary that the variable be reassigned?</p>
<hr />
<p>Xia et al. performed <a href="https://doi.org/10.1007/978-3-030-04272-1_6" rel="noreferrer">an empirical study on dynamic-typing behaviours in Python programs</a> on a substantial corpus of popular real Python systems, finding that at least 6.9% of identifiers had multiple types, and another 13.4% were undetermined by their methodology, while at least 79.7% of identifiers had only a single type. They show that even assigning <em>two different types of literal</em> to a variable sequentially has real incidence, while still being uncommon. They present a heat map of this matrix in Figure 5, but unfortunately an &quot;expression&quot; category squashes together what could be many different kinds of conversion into one (and I think the table over-eagerly aligns changes of type with changes of expression kind).</p>
<p>Chen et al. performed <a href="https://doi.org/10.1145/3387904.3389253" rel="noreferrer">another Python study</a> and found an average of 311 instances of variables being given different types across their benchmark. I don't think this average metric they reported is particularly useful, but all but one of the systems under study had more than 50, and these were the most common dynamic-typing behaviours they measured by a large margin. Excluding the low and high outliers, between 10% and 25% of methods they examined in each system contained one or more of the traits they examined, and these would primarily be variable typing. However, most instances found did combine string with another type, noting that</p>
<blockquote>
<p>It is often the case that the value of a variable
is parsed from the user inputs and its type is determined by the
source of the inputs (e.g., XML files, database or command line).</p>
</blockquote>
<p>They do present examples from real-world systems that show other replacements of values with different types, however, including strings. An example is given from IPython where a variable holding a dictionary is assigned one of the values from that dictionary. The reporting does not have enough detail to distinguish all of the cases you want to rule out.</p>
<p>Furr et al. <a href="https://doi.org/10.1145/1640089.1640110" rel="noreferrer">studied Ruby programs</a> using a profile-guided tool to infer static types for unannotated code. To produce typecheckable programs, the tool required refactoring of the benchmark programs to remove precisely this issue: they performed 11 refactorings to break multi-typed variables into multiple uni-typed variables, out of 226 total refactorings across their suite (a number of these related to specific limitations of this version of the tool, like support for dynamic type tests, so the &quot;true&quot; proportion would be higher). They also note 12 instances of fundamentally untypeable code, notably within the optparse module that parses command-line options: while these issues <em>are</em> string-&gt;other conversions, the problem is that the repeated control flow gives variables multiple values for different options, so you might count these as well. However, both classes are relatively rare and do not occur in the majority of their benchmark programs.</p>
<p>Pradel et al. <a href="https://doi.org/10.5555/2818754.2818795" rel="noreferrer">produced a tool for finding type inconsistencies in JavaScript code</a>, and benchmarked it against a suite of published code. This system was focused on finding potential bugs, rather than observing idioms, but it did encounter several cases of mixed types within functions that seem intentional; most of these involve the &quot;undefined&quot; type and another, which is meaningful within JavaScript's type model but could be analysed as a single nullable type as well. Other combinations also existed, but were less common.</p>
<p>I believe one of the Vitek analyses of R also touches on this question, but I haven't been able to find which one, if it does exist. I have <em>seen</em> a presentation on the incidence of this pattern in PHP code (quite common), but can't find any archival publication of the result; it's an explicit motivator for much of the Hack work, so I expect it has been measured to matter on the Facebook codebase too.</p>
<hr />
<p>One limitation that all of these face is that they are benchmarking against <em>published</em> code, which may tend not to use some of these features as much. It is likely that this overwriting is much more common in interactive use, which is inherently ephemeral and so not included in benchmarks. For example, a significant amount of R usage is entirely interactive, and maintaining a single variable for the in-progress results of where the user is up to is not uncommon, notwithstanding that the variable may hold different types internally as further analysis steps are run (and these different types may or may not be significant or known to the user). Some of this sort of interactive use may persist into non-published scripts calcified from interactive sessions.</p>
<p>It's also the case, though, that code where a variable has type X up to a point, and type Y thereafter, isn't necessarily resting on dynamic typing at all: without loss of generality, this can be taken as two separate variables that have the same name, one shadowing the other. It's only cases where the variable is accessed from a loop or through lexical capture, or the type changes conditionally, where the ability to mix types together really matters. This is what the refactoring from the PRuby work above rested on. The reverse can also be true: idiomatic JavaScript will declare uninitialised variables before a loop to be set inside, such as in a search — but this is strictly a change of type within JavaScript's type model, because &quot;undefined&quot; is its own type! Similarly, Python <code>None</code> is used in the same role, and is not a bottom type either. It's necessary to drill down very specifically into what is meant by type changes in order to quantify them.</p>
<p>I haven't touched here on another sort of &quot;type&quot; change: meta-mutable object values may be seen to have a different type each time one of their properties is added or removed. This could happen either as a value is built up originally (consider idiomatic JavaScript <code>let x = {}; x.a = 1; x.b = 2;</code>), either inline or by passing it to other code to populate; it can also happen long afterwards while the variable is still in scope somewhere. A change could also arise from modifications made to inheritance parents. Richards et al. <a href="https://doi.org/10.1145/1806596.1806598" rel="noreferrer">showed that all of these sorts of change are very common</a> in JavaScript code, and many are also possible and idiomatic in other languages on the more dynamic end of the spectrum. In Ruby, both monkeypatching existing types and eigenclass modifications are normal parts of using the language. These would be changes of a variable's type from some perspectives, and not others, and I'm not sure whether they're in scope of this question or not.</p>
<hr />
<p>Zhifei Chen, Yanhui Li, Bihuan Chen, Wanwangying Ma, Lin Chen, and Baowen Xu. 2020. An Empirical Study on Dynamic Typing Related Practices in Python Systems. In Proceedings of the 28th International Conference on Program Comprehension (ICPC '20). Association for Computing Machinery, New York, NY, USA, 83–93. <a href="https://doi.org/10.1145/3387904.3389253" rel="noreferrer">https://doi.org/10.1145/3387904.3389253</a></p>
<p>Michael Furr, Jong-hoon (David) An, and Jeffrey S. Foster. 2009. Profile-guided static typing for dynamic scripting languages. In Proceedings of the 24th ACM SIGPLAN conference on Object oriented programming systems languages and applications (OOPSLA '09). Association for Computing Machinery, New York, NY, USA, 283–300. <a href="https://doi.org/10.1145/1640089.1640110" rel="noreferrer">https://doi.org/10.1145/1640089.1640110</a></p>
<p>Michael Pradel, Parker Schuh, and Koushik Sen. 2015. TypeDevil: dynamic type inconsistency analysis for JavaScript. In Proceedings of the 37th International Conference on Software Engineering - Volume 1 (ICSE '15). IEEE Press, 314–324. <a href="https://doi.org/10.5555/2818754.2818795" rel="noreferrer">https://doi.org/10.5555/2818754.2818795</a></p>
<p>Gregor Richards, Sylvain Lebresne, Brian Burg, and Jan Vitek. 2010. An analysis of the dynamic behavior of JavaScript programs. In Proceedings of the 31st ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '10). Association for Computing Machinery, New York, NY, USA, 1–12. <a href="https://doi.org/10.1145/1806596.1806598" rel="noreferrer">https://doi.org/10.1145/1806596.1806598</a></p>
<p>Xia, X., He, X., Yan, Y., Xu, L., Xu, B. (2018). An Empirical Study of Dynamic Types for Python Projects. In: Bu, L., Xiong, Y. (eds) Software Analysis, Testing, and Evolution. SATE 2018. Lecture Notes in Computer Science(), vol 11293. Springer, Cham. <a href="https://doi.org/10.1007/978-3-030-04272-1_6" rel="noreferrer">https://doi.org/10.1007/978-3-030-04272-1_6</a></p>

CC BY-SA 4.0
2023-08-14T23:19:16.880Z
2023-08-14T23:50:48.157Z
2023-08-14T23:50:48.157Z
Michael Homer
CC BY-SA 4.0
2023-08-14T23:39:06.717Z
Very nice answer, TY! I'll look up these references and be back later ...
davidbak
CC BY-SA 4.0
2023-08-15T14:08:29.220Z
Nice! It's been a long time since I've seen Diamondback Ruby referenced.
Jörg W Mittag
# Are there metrics on how often variables in dynamically-typed languages change their type (not "parametrically")
Posted by: username_0 on 2023-08-14
One aspect of a dynamically typed language is that it is possible for a variable to change its type (the "type" of the value it holds) in the course of "straight line code".
This would be code like:
var a := readline(); // a is some string
a := length(a) > 10; // a is now a boolean
if (a) {
   a := 5;            // a is now an integer
} else {
   a := "foobar";     // a is now a string again
}
print a;

I'm specifically excluding the common case where a function formal argument (or a local in a function) gets a different type on separate calls to the function because on these separate calls the actual parameter is of a different type.
I'd also like to exclude the other common case where an ordinary expected conversion from string to some numeric type is done (or vice versa), e.g.,
var a := readline(); // a is some string that represents a number, e.g., the string "25"
a := 3 * a;          // a is now represented internally as an integer

My question is: Are there any numbers (e.g., studies performed) on how often programmers of dynamic languages use variables this way?  Perhaps it is language specific (e.g., cultural)?  Or maybe there are particular algorithms where it is used while in others it is never used?  Maybe it just doesn't happen?
**Tags:** dynamic-typing software-engineering
> **Comments:**
> **username_1**: I'm having some trouble understanding the last criterion. If we have `var a := <some string>; a := <some integer expression>;`, it will depend on whether or not `<some integer expression>` involves `a`? How do you determine whether or not to exclude this case?  
> **username_0**: @DavidYoung - the example I gave the reassignment _does_ involve `a`.  BTW, to avoid a red herring due to the examples I gave: I'm not restricting this to _self_ assignment.  I just did that to make the examples small.  Any case where at some point in a function `a` is assigned an integer and then somewhere later in that function `a` is assigned something else (a struct, an array, a boolean, whatever) would count.  The point being that the _programmer_ deliberately used the _same variable_ to hold _different types_ during the same function (those types not due to an implicit conversion).  
> **username_2**: Is there a particular reason you want to exclude the most common cases?  
> **username_0**: @kaya3 - the parameter case - that's one of the frequently cited benefits of dynamic languages, that you get some form of polymorphism built-in, encouraging code reuse, etc.  the implicit coercion case - that (IMO) has wide variance between languages, how many different things get freely exchanged with the other (e.g., consider AWK and APL as two examples here), plus it is a common idiom in scripting languages.  What's left is _allowed_ by dynamic languages and it is sometimes touted as a benefit but I personally haven't seen any body of code that does it _as a rule_ and wondered about ...  
> **username_0**: ... how often is it used by practicing programmers.  Plus, the answer, if known, may inform implementations and/or tools (e.g., IDEs, static analyzers).  
> **username_3**: @kaya3: If a language allows function overloading based upon the type of an argument, then each individual overload would always receive the same type.  In most cases where the lack of overloading in a dynamic language would make it necessary to check the type at runtime, therun-time type check would have been avoided if overloading were available.  
> **username_4**: I strongly suspect that the answer to this question is currently “no”, but it is impossible to prove a negative. Still, there’s no harm in having the question around in case someone does such a study at some point in the future. It seems difficult to measure, though.  
> **username_5**: I think you're asking the wrong question. You should ask how often this happens *after SSA renaming*. Any poly-type-ism that can be eliminated by renaming is "trivial" and won't affect the analysis of a compiler or IDE that's sophisticated enough to do partial type inference in the first place. All of your examples are eliminated by renaming except for `print a;` where `a` may be `5` or `"foobar"`.  
> **username_6**: Do you count `null`/`undefined` as values of a separate type? Do structs with different fields have different types? How about class instances that share the same interface but not the same implementation?  
> **username_0**: @benrg - I'm not really asking about static analysis.  I totally get how that's done.  I'm asking about what we know about _programmers who code this way_.  Like I said, I haven't seen in in any code base.  (Though I quite agree it's unexceptional in REPLs.) I'm wondering what the _programmers_ think when they do this.  To put it in context: I'm a strong-typing kind of guy.  Starting with Pascal, on to Ada, various other paths, finally to ML/Haskell and rich type systems.  But how does the _other_ half live?  
> **username_0**: @Bergi - moving from null to some type and back - I get that.  That's standard in many languages.  E.g., C#/Java/anything with Optional.  So no, not that.  Structs with different fields/different types: That depends on the language surely - is a "struct" a bag of fields or is it something with ordered fields or fixed fields.  Interfaces are obviously not it, those are polymorphic by defn, and aren't really a feature of dynamic languages.  Seriously, I thought the question (and examples) were pretty clear.  These these are details of particular "type systems" but look at the big picture instead  
> **username_7**: its talked about in the TCL community as https://wiki.tcl-lang.org/page/shimmering not sure thaere are any stats ive seen on it though  
> **username_8**: I would expect there is one factor which would significantly influence the result: whether the language makes rebinding/shadowing convenient (eg lisp) or not (eg python).  In the latter case, many cases of reassignment are logically intended to rebind, but in fact do not because that's inconvenient.  Another issue is subtyping.  If B <: A, C <: A, and a variable changes type from B to C, but the code only cares about its A-ness, does that count?  
> **username_9**: I don't think the problem is well-defined. There are type systems and inference algorithms that will tell you that `a` has the consistent union type `string | boolean | integer` throughout the program, thus "no change" occurs. There are also systems that will say `a = 0; a = 1;` has moved `a` from one type to another.  
---
## 1 answers
### Answer by username_10 on 2023-08-14. Score: 9 | Accepted answer
There have been many studies that touch on these questions, but none that I know of that follow the particular constraints you set out. A lot of work on type *inference* for dynamically-typed languages faces this issue, and often enough in practice that it comes up as something to be dealt with, while rarely enough that it's sometimes explicitly excluded from support. Some work has looked specifically at the use of dynamically-typed features on their own.

In most cases the relevant results are on the side of something else, either an inference engine or analysis of more complex dynamic features. It doesn't seem like anyone has looked specifically at reassignment, which I do find a little surprising. I can point at some previous work, but I think to match the specific goals you have in mind you'll need to run the study yourself.

Further down I'll note some limitations, and other cases that may or may not be in scope here. Exactly what it means for a variable to hold a new type is potentially a bit tricky to nail down. For example, what constitutes a type in these languages? is it necessary that the variable be reassigned?

---

Xia et al. performed [an empirical study on dynamic-typing behaviours in Python programs](https://doi.org/10.1007/978-3-030-04272-1_6) on a substantial corpus of popular real Python systems, finding that at least 6.9% of identifiers had multiple types, and another 13.4% were undetermined by their methodology, while at least 79.7% of identifiers had only a single type. They show that even assigning *two different types of literal* to a variable sequentially has real incidence, while still being uncommon. They present a heat map of this matrix in Figure 5, but unfortunately an "expression" category squashes together what could be many different kinds of conversion into one (and I think the table over-eagerly aligns changes of type with changes of expression kind).

Chen et al. performed [another Python study](https://doi.org/10.1145/3387904.3389253) and found an average of 311 instances of variables being given different types across their benchmark. I don't think this average metric they reported is particularly useful, but all but one of the systems under study had more than 50, and these were the most common dynamic-typing behaviours they measured by a large margin. Excluding the low and high outliers, between 10% and 25% of methods they examined in each system contained one or more of the traits they examined, and these would primarily be variable typing. However, most instances found did combine string with another type, noting that

> It is often the case that the value of a variable
> is parsed from the user inputs and its type is determined by the
> source of the inputs (e.g., XML files, database or command line).

They do present examples from real-world systems that show other replacements of values with different types, however, including strings. An example is given from IPython where a variable holding a dictionary is assigned one of the values from that dictionary. The reporting does not have enough detail to distinguish all of the cases you want to rule out.

Furr et al. [studied Ruby programs](https://doi.org/10.1145/1640089.1640110) using a profile-guided tool to infer static types for unannotated code. To produce typecheckable programs, the tool required refactoring of the benchmark programs to remove precisely this issue: they performed 11 refactorings to break multi-typed variables into multiple uni-typed variables, out of 226 total refactorings across their suite (a number of these related to specific limitations of this version of the tool, like support for dynamic type tests, so the "true" proportion would be higher). They also note 12 instances of fundamentally untypeable code, notably within the optparse module that parses command-line options: while these issues *are* string->other conversions, the problem is that the repeated control flow gives variables multiple values for different options, so you might count these as well. However, both classes are relatively rare and do not occur in the majority of their benchmark programs.

Pradel et al. [produced a tool for finding type inconsistencies in JavaScript code](https://doi.org/10.5555/2818754.2818795), and benchmarked it against a suite of published code. This system was focused on finding potential bugs, rather than observing idioms, but it did encounter several cases of mixed types within functions that seem intentional; most of these involve the "undefined" type and another, which is meaningful within JavaScript's type model but could be analysed as a single nullable type as well. Other combinations also existed, but were less common.

I believe one of the Vitek analyses of R also touches on this question, but I haven't been able to find which one, if it does exist. I have *seen* a presentation on the incidence of this pattern in PHP code (quite common), but can't find any archival publication of the result; it's an explicit motivator for much of the Hack work, so I expect it has been measured to matter on the Facebook codebase too.

---

One limitation that all of these face is that they are benchmarking against *published* code, which may tend not to use some of these features as much. It is likely that this overwriting is much more common in interactive use, which is inherently ephemeral and so not included in benchmarks. For example, a significant amount of R usage is entirely interactive, and maintaining a single variable for the in-progress results of where the user is up to is not uncommon, notwithstanding that the variable may hold different types internally as further analysis steps are run (and these different types may or may not be significant or known to the user). Some of this sort of interactive use may persist into non-published scripts calcified from interactive sessions.

It's also the case, though, that code where a variable has type X up to a point, and type Y thereafter, isn't necessarily resting on dynamic typing at all: without loss of generality, this can be taken as two separate variables that have the same name, one shadowing the other. It's only cases where the variable is accessed from a loop or through lexical capture, or the type changes conditionally, where the ability to mix types together really matters. This is what the refactoring from the PRuby work above rested on. The reverse can also be true: idiomatic JavaScript will declare uninitialised variables before a loop to be set inside, such as in a search — but this is strictly a change of type within JavaScript's type model, because "undefined" is its own type! Similarly, Python `None` is used in the same role, and is not a bottom type either. It's necessary to drill down very specifically into what is meant by type changes in order to quantify them.

I haven't touched here on another sort of "type" change: meta-mutable object values may be seen to have a different type each time one of their properties is added or removed. This could happen either as a value is built up originally (consider idiomatic JavaScript `let x = {}; x.a = 1; x.b = 2;`), either inline or by passing it to other code to populate; it can also happen long afterwards while the variable is still in scope somewhere. A change could also arise from modifications made to inheritance parents. Richards et al. [showed that all of these sorts of change are very common](https://doi.org/10.1145/1806596.1806598) in JavaScript code, and many are also possible and idiomatic in other languages on the more dynamic end of the spectrum. In Ruby, both monkeypatching existing types and eigenclass modifications are normal parts of using the language. These would be changes of a variable's type from some perspectives, and not others, and I'm not sure whether they're in scope of this question or not.

---

Zhifei Chen, Yanhui Li, Bihuan Chen, Wanwangying Ma, Lin Chen, and Baowen Xu. 2020. An Empirical Study on Dynamic Typing Related Practices in Python Systems. In Proceedings of the 28th International Conference on Program Comprehension (ICPC '20). Association for Computing Machinery, New York, NY, USA, 83–93. <https://doi.org/10.1145/3387904.3389253>

Michael Furr, Jong-hoon (David) An, and Jeffrey S. Foster. 2009. Profile-guided static typing for dynamic scripting languages. In Proceedings of the 24th ACM SIGPLAN conference on Object oriented programming systems languages and applications (OOPSLA '09). Association for Computing Machinery, New York, NY, USA, 283–300. <https://doi.org/10.1145/1640089.1640110>

Michael Pradel, Parker Schuh, and Koushik Sen. 2015. TypeDevil: dynamic type inconsistency analysis for JavaScript. In Proceedings of the 37th International Conference on Software Engineering - Volume 1 (ICSE '15). IEEE Press, 314–324. <https://doi.org/10.5555/2818754.2818795>

Gregor Richards, Sylvain Lebresne, Brian Burg, and Jan Vitek. 2010. An analysis of the dynamic behavior of JavaScript programs. In Proceedings of the 31st ACM SIGPLAN Conference on Programming Language Design and Implementation (PLDI '10). Association for Computing Machinery, New York, NY, USA, 1–12. <https://doi.org/10.1145/1806596.1806598>

Xia, X., He, X., Yan, Y., Xu, L., Xu, B. (2018). An Empirical Study of Dynamic Types for Python Projects. In: Bu, L., Xiong, Y. (eds) Software Analysis, Testing, and Evolution. SATE 2018. Lecture Notes in Computer Science(), vol 11293. Springer, Cham. <https://doi.org/10.1007/978-3-030-04272-1_6>
> **Comments:**
> **username_0** (2023-08-14): Very nice answer, TY! I'll look up these references and be back later ...  
> **username_11** (2023-08-15): Nice! It's been a long time since I've seen Diamondback Ruby referenced.  
---
