What do you think about my solution for the "accumulate" exercise?

TLDR: The test passed by using for.

I want to know if there is any wrong in using for? I made use of the higher order function functionality by passing the operation as first class citizens when computing the result.

I’m so impressed on what this lang can do.

Did you read the restriction? This problem should be solved using basic tools. So no map, reduce, for. The final result should be constructed manually by adding one element at a time.

Got it! Thanks for the clarification. I’ll try a different approach.

(I do not know Clojure.)

Your second iteration uses loop, if, seq, recur, rest, conj, and first. Can you solve this problem using fewer built-in/predefined functions?

I know of a Haskell solution that uses only 2 built-ins. Clojure and Haskell are fairly similar.

I didn’t realise that minimising the number of built-in functions was the goal. :sweat_smile: I’ll figure out a better approach. I’m thinking about using recursion and destructuring.

As my third iteration, I tried to keep the built-in functions to a minimum. It took me a while to reason about it, but I think this is the best I can do. I don’t know how a solution with 2 built-ins is even possible in Clojure :smile:, maybe a more experienced Clojure programmer can figure it out. Anyway, can you share the Haskell solution with me? I don’t know Haskell, but I’ll try to understand it.

The purpose of the exercise is written in the instructions. Avoid built-ins like map, reduce, for. Now, how you choose to solve it is up to you. The second iteration is perfectly fine since it’s the most frequent and typical approach being used in manual looping. No way you can do it with just two basic functions as per @MatthijsBlom suggestion. Clojure is way more verbose.

As for the 3rd iteration, the inner function will return the output if head is equal to nil and that’s probably not what we want here because a nil head does not necessarily indicate the end of the sequence, unless you know that the sequence does not contain nil values.

Another approach is using lazy-seq to construct a lazy sequence, but this approach still uses many built-ins.

It isn’t necessarily. It just seems like a natural extrapolation of the instructions to me.

Me too :slight_smile:

As far as I know Clojure does not feature a pattern matching construct, so I guess 3 would be the theoretical minimum. I do not know enough about Clojure to be more specific.

Here are two versions, one using special list syntax and one using more ‘normal’ Haskell syntax:

-- typical but special syntax
accumulate :: (a -> b) -> [a] -> [b]
accumulate f input =
  case input of
    []     -> []
    x : xs -> f x : accumulate f xs

-- atypical but normal syntax  (more beginner friendly?)
accumulate :: (a -> b) -> List a -> List b
accumulate f input =
  case input of
    Nil       -> Nil
    Cons x xs -> Cons (f x) (accumulate f xs)

case, of, and -> are keywords that always come together as parts of the case expression syntactical construct. The only ‘built-ins’ / predefined values used are (:)/Cons and []/Nil.

It is possible to avoid explicitly pattern matching by using the standard function foldr:

accumulate f input = foldr (\x ys -> f x : ys) [] input

Should a solution in Clojure that uses only 3 built-ins exist, I expect an equivalent of this foldr to be the third one.

(The thingy between parentheses is a lambda expression.)

Thanks to all for the help. It was a cool experience solving this exercise.