Hacker News new | ask | show | jobs
by megapoliss 1637 days ago
> The part of functional programming I hate the most is passing some new data through 10 levels of callstack to use it in a function that didn't needed it previously. It should be automated.

Probably, you may restructure your code, use curried functions, and you won't need to go through all 10 levels. Transition from imperative to functional programming may looks like untangling a ball of function calls, in order to get simple and clean design.

1 comments

I can structure the code cleanly, that's why I love functional programming. Althought I mostly use clojure not SML-like languages so I don't go overboard with currying. From my limited experience currying makes order of arguments matter A LOT, and then you have to refactor that often.

My problem is that I'm mostly writing games in my free time (the only time when I'm allowed to use functional languages), and writing games is mostly about quick iteration and testing many small changes. So previously I had the code to handle collisions only take potentially colliding objects as inputs and outputs. Now I want to add particle effects when things collide. Pass that particle system and return particles from the function.

Then I think - what if collisions cause the screen to "shake"? Again pass new data to the function. Then I decide it looks stupid and revert it.

Then I think - what if police reacted to collisions if they are near the police station? Again - pass some new data there.

I can do this, but it's a lot of refactoring. I'd prefer if I could just use a global variable and hit a button in IDE to refactor it to a nice functional code.

Curring is a way to do "dependency injection" in FP, so it let you to "capture" some arguments and don't pass them each time. Sure, arguments order matter, but you don't need to refactor that often.

I'm not familiar enough with clojure, buy in F# you sample with collision/shake/police may looks like

  someGameState
  |> handleCollisions
  |> handleShake
  |> handlePolice
  ...
  |> renderGameState

where each function accept gameState, run some login against it, and return modified state, so you don't need to pass dozen arguments through call-stack.
In clojure:

    (-> someGameState
      handleCollisions 
      handleShake
      handlePolice
      ;; ...
      renderGameState)

    ;; ->> would work as well in this example cause it's both first and last argument
But this code is only pretending to be functional, because in practice every function can modify everything. So looking at this I have no idea where the particles were created - I have to look at every function anyway.