6 ms·
How to Name Clojure Functions
- m0skit0 11y agoI'm really confused about what is the author intent with this article. At first read, it is pointless. The first paragraph pretty much resumes it: "These are my rules, but they're not good because I break them more often than I adhere to them". If this is intended as a starting point for a discussion, as the author claims, I think a forum is more appropriate format, and at least start from some previous existing convention discussion. This just looks like trying to reinvent the wheel from scratch.
- hellofunk 11y agoBlogs tend to be the way a lot of advice, guidelines etc are disseminated in the software world, so that's the main reason. I don't know of any major forums in the Clojure world, for example, that everyone is aware of and contributing knowledge to. It seems to blogs, irc, the mailing list, stackoverflow.
- Jare 11y agoThey are not good as rules, but they are excellent ideas to have in mind when making decisions on this topic.
- sdegutis 11y agoThis is on Stuart Sierra's personal blog, so it's just him sort of thinking out loud. He's got a lot of that on his blog, and a lot of it is really valuable. I refer to it often when I want to get some new ideas on different ways to do things in Clojure.
- escherize 11y agoI suspect I overuse the x->y naming convention for functions that take an x and return a y. Esspecially when there is only one kind of thing that that function ever takes. So instead of: (-> x x->y y->z) I'd have: (-> x y z) Makes sense. Thanks for the post Stu! P.S. Another useful tome about naming functions is: https://github.com/bbatsov/clojure-style-guide https://github.com/bbatsov/clojure-style-guide
- j-pb 11y agoI think it would be more valuable to actually define the ! convention, than propose yet another one for side effects.
- Heliosmaster 11y agoNot sure why he says the ! is not for side effects, i've always encountered it used in that way (and changing the state is also a side effect)
- virmundi 11y agoI can't think off the top of my head where it's been abused. I do know that one question that often arises is "should I end with an ! if my method logs?" I've had this conversation on IRC with the author. The consensus was to only apply such a name when a global was involved. The trick is trying to telegraph to the consumer that your function logs. They need to know because it brings with it dependencies both by way of code and runtime requirements. Logging may fail for a variety of reasons. These would throw any consumer off. They have to plan for it.
- dkersten 11y agoThe clojure convention for ! is to use it for functions that are not safe to execute in a transaction - that is, functions that cannot safely be retried. That means that most side-effecting functions should end in !, but not necessarily all: it is possible to have side-effecting yet transaction-safe functions as long as the side-effects are idempotent. When will functions be called in a transaction? STM ref, agent and atom updates.
- junke 11y ago> If name-clashes become a problem, add prefixes to the function names Or, find better names for local variables, like customer-address. In the given example, there is in fact no need to add local variables: simply calling the functions would be enough.
- barrkel 11y agoChanging function names after the fact is a versioning problem. I'd much rather not have to rename functions. Changing global names because you're having a hard time with local names seems like a developer anti-pattern.
- wtetzner 11y ago> Or, find better names for local variables, like customer-address. In the given example, there is in fact no need to add local variables: simply calling the functions would be enough. Or require the function using a namespace alias.
- hellofunk 11y agoI think one issue that pops up in many languages is the distinction between functions that have side effects and those that don't. In C++ you see standard library higher-order-functions that accept lambdas or other functions, but the documentation says "the function passed should not produce side-effects." You also see this in Clojure functions, and functions you might write might also expect only side-effect-free functions. The problem is that the functions you pass may not be functions you wrote, they might come from another library and then to be most confident, you must go and look up the source or docs to feel sure. I don't think a naming convention is enough, since many may not use the convention. For languages where this is important, I wish there was a compiler or runtime check for these things so the user didn't have to take responsibility. Almost as if functions were split into two "function types", those with and those without side effects. Maybe starting at the lowest level of the core language library, some functions would be noted as causing side-effects, and then any function built that called those functions would automatically be categorized as such, and on up to the top, so that side-effects-beget-side-effects and function parameters that require non-side-effect-functions wouldn't allow those to pass. Anyway, it is a problem that is not solved by a naming convention.
- germanier 11y agoHaskell for example has exactly that with e.g. the IO monad.
- hellofunk 11y agoI don't know Haskell, but assumed it would probably tackle this problem based on all the praise I've seen it get for things like this and its general type system.
- baldfat 11y agoIt gets all the praise but the use of Haskell is still very low. For me the package system drove me into the Arms of Racket and Clojure.
- pearjuice 11y agoI am always baffled at how individuals present their opinions and methods as the industry standard.
- hellofunk 11y agoClojure is a small "industry" with a few key players offering a lot of the guidance and advice. Nothing wrong with that, but often the community does in fact adopt the guidelines of just a few people, so that is probably why the author continues to contribute in this way. This author, for example, also wrote one of the tiny but widely-used functions used for unit testing in Clojure, for example. Almost everyone uses it at some point (the "is" macro).
- dandrews 11y ago"This guide is just a starting point for thinking about how to name things." That's a novel way to introduce an "industry standard".
- natrius 11y agoI'm glad you made this comment because it's important to understand why this attitude is harmful. If people believe what you're saying, then they're less likely to attempt to steer their communities in helpful ways. Strong opinions that are widely distributed act as a frame of reference that lets people start from a common base of knowledge and explain where their opinions differ. I can now say, "I name my Clojure functions like Stuart Sierra, except for two differences..." More people need to present their opinions as the best way to do things. Some useful, widely-cited examples: - https://github.com/airbnb/javascript https://github.com/airbnb/javascript - http://12factor.net/ http://12factor.net/
- Grue3 11y ago>If I have a function to compute a user’s age based on their birthdate, it is called age, not calculate-age or get-age. Ah, but isn't Clojure Lisp-1? Then you can't have function `age` and variable `age` in the same scope despite `age` being a great variable name in many circumstances. Hence having to come up with silly variable names like "lst" instead of "list", because all the good names are taken by the functions.
- mapleoin 11y agoHe discusses that in a later pargraph "Local name clashes", basically advocating the use of namespace prefixes.
- astine 11y agoWhen I write Clojure I tend not to worry too much about this. Most of my variable names will be declared with `let` and will have a very limited scope. I can go ahead and clash some builtin function name and not worry about it unless I happen to need that builtin function within the `let` block. It usually is the case that I don't need to.
- Grue3 11y agoLocally overriding builtin/global functions seems like a bug waiting to happen. There's no way to figure out if you actually intended to use the local variable inside of scope, or the function it overshadowed. It seems to me that in Lisp-1 all local variables should be prefixed with some sort of symbol so that they can never override globals.