Difficulty naming functions would imply to me that the functions
involved do not contain a clear functionality.
The names of the functions should sort of be an 'emergent property' of
a larger process of reasoning through the programming problem.
As I see it, there are two ways to do this...
The first (systematic):
1.) break the program into reasonable steps
(a concise description of the step being the function name)
2.) make a function for each step.
3.) break each function into steps
4.) goto 2 until you are able to describe different pieces of the
program in the base language.
the second (haphazard):
1.) start writing code into a function (name of overall functionality)
2.) when the code gets to a certain size, decide that you have too
much code in the function.
3.) look for different pieces of the task that you could potentially
pull out and name, or patterns that repeat more than once.
4.) pull them out and use them as functions.
5.) loop through this process of expanding the code and rewriting it
until you are done.
I could write these as functions
(defn systematic [idea]
(let [sub-ideas (partition-idea idea)]
(map #(unless (atomic? %1) (systematic %1)) sub-ideas))
(defn haphazard [functionality]
(let [[refactored-functionality & new-functions] (extract-
functionality functionality)]
(map #(unless (atomic? %1) (haphazard %1)) new-functions)))
Ideally these functions lead to the same output.
In my use of map I am assuming a lazy programmer without a deadline.
In the case of a motivated programmer, we might use dolist.
In the case of a lazy programmer with a deadline, we might use doall
or dorun..
(defn <insert-name-here> [n base]
(loop [n n count 0]
(if (< n base)
{:val n :count count}
(recur (float (/ n base)) (inc count)))))
This can be used among other things, to determine how to format bytes.
Say I have a file that's 6,789,354 bytes, and I want to display that
in a more readable manner, I could use my unnamed function like so
(<unnamed> 6789354 1024), and get a new appropriately rounded number,
including the number of times it has been rounded, which I can use the
pick the appropriate suffix from a list ("Bytes", "KB", "MB", "GB",
"TB).
I mean, what the hell would you name this function, or would you not
create such an obscure and generalised function to start with?
I would probably split that up:
The division can just use /, so no need for a separate function.
The rest can be done like this:
(defn logn [n x]
(/ (java.lang.Math/log x) (java.lang.Math/log n)))
Then you could have a function that formats file sizes:
(defn format-file-size [num-bytes]
(let [base 1024
val (float (/ num-bytes base))
times (int (logn base num-bytes))]
...)
Not sure if that helps with your general question, though :)
> I mean, what the hell would you name this function, or would you not
> create such an obscure and generalised function to start with?
--
Michael Wood <esio...@gmail.com>
Anyway, would you have written this particular function as a method of
a class, would the problem of giving it a "short but meaningful name"
rather than "long and meaningful name" have been easier ?
2010/2/4 Wardrop <t...@tomwardrop.com>:
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
How about significand-and-exponent-in-radix? :-)
(Or for a shorter name maybe sci-notation-map or something...)
In fact, I might generalise it further to accept an optional argument
-- defaulting to 0 -- to determine how the result is to be normalised:
user> (defn significand-and-exponent-in-radix
([n radix] (significand-and-exponent-in-radix n radix 1))
([n radix o]
(let [threshold (Math/pow radix o)]
(loop [n n count 0]
(if (< n threshold)
{:significand n :exponent count}
(recur (double (/ n radix)) (inc count)))))))
#'user/significand-and-exponent-in-radix
user> (Math/pow 10 1)
10.0
user> (significand-and-exponent-in-radix 1000 10)
{:significand 1.0, :exponent 3}
user> (significand-and-exponent-in-radix 1000 10 0)
{:significand 0.1, :exponent 4}
Also, add docstrings. With the REPL at hand, the explanation of
anything unclear from your function's name is one (doc ...) call away
if you do.
All best,
Michał
e
There is no naming convention: filter, remove, take, take-nth, drop-while, ... are all examples of that.
Sincerely
Meikel
Thanks for the implementation suggestion. I left school 2 years only
so missed out on some of the more advanced mathematics, hence I was
unaware of the function and purpose of log. Since reading your post,
I've done a little bit of research on log as to educate myself. I've
now re-implemented my function using your logn implementation. It now
has a name also...
(defn recursively-divide
"Divides n by base until n is smaller than base. Returns a map
consisting of the structure {:result :times}, where :result is the
result of the recursive division, and :times is the number of times n
was divided by base."
[n base]
(let [times (int (logn base n))]
{:result (float (/ n (expt base times))) :times times}))
I've chosen "recursively-divide" as it seemed more clojuresque, as it
reads like it would in english "recursively divide n by base".
I guess if I've learnt anything from just this function alone, it's
that often names are difficult to think of when it's hard to define
exactly what it is a function is doing. If you can't easily define
what a functions purpose is, then I think that usually means it's been
poorly designed/implemented (suggesting there's a better way) or the
coder isn't exactly sure what they're trying to achieve.
> Michael Wood <esiot...@gmail.com>