Functions are constants too
Table of contents:
Once in a while, I get feedback on a code review remarking that I ought to extract a certain string literal into a constant. For example, that this:
fn get_foo() -> {
std::env::var("FOO").unwrap()
}
Should become this:
const FOO_KEY: &str = "FOO";
fn get_foo() -> {
std::env::var(FOO_KEY).unwrap()
}
This increases the scope of the relevant constant. Now you have to check to see if that constant is used anywhere else, without improving legibility otherwise. So I’m oftentimes opposed to this kind of change.
(That being said, I’m not opposed to writing a helpful constant name which is still restricted in scope to the function body.)
Functions are constant values too! It’s perfectly acceptable to leave implementation details, including magic values, inside a function definition (assuming that they’re not used anywhere else).
Or alternatively — constants are essentially zero-ary functions. This is more obvious in e.g. an ML-style language where function and constant bindings follow the same syntactic pattern:
let foo = 3 (* constant binding *)
let bar baz = 4 (* function which takes one argument *)
Related posts
The following are hand-curated posts which you might find interesting.
Date | Title | |
---|---|---|
09 Apr 2017 | How to parse contextual keywords in a programming language | |
24 Jul 2017 | Null-tracking, or the difference between union and sum types | |
23 Dec 2017 | Why LINQ syntax differs from SQL, list comprehensions, etc. | |
20 Apr 2020 | Monotonicity is a halfway point between mutability and immutability | |
14 Jun 2022 | (this post) | Functions are constants too |
17 Jun 2023 | Encoding ML-style modules in Rust | |
14 Aug 2025 | Lithe, less analysis with Datalog |
Want to see more of my posts? Follow me on Twitter or subscribe via RSS.