
How to Name Clojure Functions - henrik_w
http://stuartsierra.com/2016/01/09/how-to-name-clojure-functions
======
hellofunk
I 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
Haskell for example has exactly that with e.g. the IO monad.

~~~
hellofunk
I 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
It 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.

~~~
kornish
You should revisit it, then! Stack, a new build tool, far surpasses the Cabal
hell that drove people away in the past.

~~~
hellofunk
I have read many times that you need a solid understanding of the Haskell
implementation as well as various extension to make the code as performant as
it is elegant. True?

~~~
kornish
Right now, that's truer than many would like. However, when GHC 8 (the new
version of the compiler) drops in the next couple months, most of the
performance tuning will involve putting a single line of code at the top of
each performance-critical file. That line will make all evaluation within the
file strict instead of lazy.

A lot of the performance and predictability problems in Haskell come from its
laziness, so the ability to toggle that on and off on a per-module (read: per-
file) basis will be a game changer.

~~~
hellofunk
That _does_ sound significant. I will be curious to hear more about that. Can
you recommend a good go-to resource for all the latest news and discussions on
Haskell?

~~~
kornish
Mostly I just read various people's blog posts and follow links (for example,
I think I first found Stack on [1]). I also spend occasional time in the IRC,
which can be useful but isn't a comprehensive news source by any means.

I hear some of the mailings lists are informative - iirc there's a haskell-
beginners one which will probably cover major updates in tooling, feature
releases, and so on. Good luck!

[1]: [https://www.fpcomplete.com/blog/2015/08/new-in-depth-
guide-s...](https://www.fpcomplete.com/blog/2015/08/new-in-depth-guide-stack)

------
escherize
I 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)

------
m0skit0
I'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
Blogs 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.

------
j-pb
I think it would be more valuable to actually define the ! convention, than
propose yet another one for side effects.

~~~
Heliosmaster
Not 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
I 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.

------
junke
> 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
Changing 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.

------
Grue3
>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.

~~~
astine
When 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
Locally 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.

------
pearjuice
I am always baffled at how individuals present their opinions and methods as
the industry standard.

~~~
natrius
I'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/)

