As just one person who has written a great deal of functional code, it reads well to me. I think because I am used to reading it "inside out"? Reading lisp-likes is probably helpful.
Take 'color' for example. It opens with a 'cond', with three branches. First branch is if the idx-th position in word is the same as letter, return green. Second branch is if the word includes the latter at all, yellow. Otherwise we're grey.
That took me a few seconds to grok. Just one anecdote for you. Don't think you're broken but reading/writing this kind of code even a little bit will change the way you see code IMO.
def color(word, letter, idx):
if word[idx] == letter:
return GREEN
elif letter in word:
return YELLOW
else:
return GREY
I know which one I'd prefer to grok at 2AM with alerts going off.At that time I'd just opt for sleep. Or sex. Or drink. Reading code doesn't belong to things one should do at 2AM.
That's just a myth spread by a few workaholic programmers. Luckily, there are enough 9-5 programmers to clean up the mess created by those 2AM committers.
Don't confuse familiarity with readability.
This is a tangent, but I've been thinking about how I feel when the conditions of an if-else ladder rely on the order they're listed in.
This is an example; if you swapped the order of those branches around, the coloration would become incorrect.
I'm a little happier when the conditions are described completely, such that swapping the order of the checks doesn't change which of them evaluate false or true, but it's also true that that can add quite a bit of complexity over an order-sensitive set of conditions.
Thoughts?
I hate meaningless statements like this. This means nothing, other maybe that you know Python. 20 years ago people might have said that about Python - I even know many people today who would say that about Python.
I had been programming in C for a while, learning from K&R, to build ray tracing input files and that sort of thing so I was kind of disappointed but whatever, I was a mature student who had rediscovered computers a couple of years before (had a C64 in the 80s) and was just happy to be there.
Anyway, this guy in the back yells out "I could do that in 2 lines of Q-BASIC" or something to that effect (Q-BASIC was definitely part of his pithy one-liner). Little did I know he was representing so many of the people I would encounter over the next decades.
(defn color [word letter idx]
(cond
(= (nth word idx) letter) :green
(str/includes? word letter) :yellow
:else :gray))
Interesting that even with the `str` callouts removed, the function still appears to work on other datatypes such as: (def s (seq ("test1"))
A lazy sequence, but one Clojure still allows to be indexed over in O(1) time. That's probably what the `str` conversion was trying to speed up.Python, meanwhile, fails on lazy input as it isn't indexable.
word = (c for c in "test1")
I guess I'll be checking out Clojure this weekend. def color(word, letter, idx):
cond:
word[idx] == letter: return GREEN
letter in word: return YELLOW
True: return GREY (first (filter identity
[(and (condition-three) (action-three))
(and (condition-one) (action-one))
(and (condition-four) (action-four))
(and (condition-two) (action-two))]))
And you could write a macro to do it with nice syntax. A bit more work and you could parallelize it.You probably wouldn't want to most of the time, but if the conditions are slow to test but otherwise inexpensive, it might be a useful optimization.
Or possibly the code even uses non-symbols for some of the arguments. Suppose that letter is sometimes the integer 1.
fun color(word: String, letter: Char, idx: Int) =
when (letter) {
word[idx] -> GREEN
in word -> YELLOW
else -> GRAY
}