I am working on the solution for this koan, which states:
Write a function which replicates each element of a sequence a variable number of times.
To do this, I want to:
- Make a method which takes a sequence and the number of times to repeat each element.
- Define a local method within this method which duplicates a value, v, n times into a sequence.
With that in mind, I wrote the following method:
(fn dupSeqX [aseq x]
(fn dupx [v x]
(if (= x 1) (list v) (concat v (dupx v (- x 1))))
)
(reverse (reduce #(concat %1 (dupx %2 x)) '() aseq)))
When running this code, I get the following error:
java.security.PrivilegedActionException: java.lang.Exception: Unable to resolve symbol: dupx in this context (NO_SOURCE_FILE:0)
How do I go about creating a local method that will allow me to finish this koan?
Is there a “clojure-esque” way of doing this that I’m not aware of?
First of all, we don’t talk about methods: we talk about functions. There is something in clojure that you could call a method but it’s different from a function. If you stop using the OO lingo you will lose the OO style of thinking too.
What you are trying to do is possible. You basiclly want to create a new function with the name
dupxin thedupseqxfunction. What you are doing right now is creating a function and then throwing it away (you don’t do anything with the return value and only the last form in a function gets returned). Since a function is just like any other value, you can use the same mecanism like with any other value: create a local “variable”. What’s the mechanism for this? It’s local binding and it works like this (The name in the fn is just so that you can call it from itself; it doesn’t need to be the same as thelet-bound name):Notice that I corrected some other things.
A shorter form of this (fixing the double name ugliness):
Ok in everything between “(let […]” and the matching “)” we now have a
dupxfunction.So now the rest of your code works:
This code can be made a little more idiomatic:
collinstead ofaseqHow did I go about writing this?
First the basic fn.
collis the standard for naming function that expect sequences.If you read this “each element of a sequence” your brain has to go MAP.
“replicates each … ” is basically a description of what you have to put into the map function. We can use
repeat(your dubx function but with some extra goodies like that it’s lazy).There is one problem left (from the koan). It wants one seq back, not a sequence in a sequence for each element. This means we have to concat the result together.
You will often see the
(apply concat (map ....))pattern. There is a better function for that in the standard library, calledmapcat, and I’ll make the inner function into the short syntax.Hope that helps!