4 ms·
>for (int i =0;i<len;i++){ if(lines[i] == "a"){ i+=2; } } This algorithm can, without modification, be done in a functional language. For example, consider the
by gizmo686 10y ago
>for (int i =0;i<len;i++){ if(lines[i] == "a"){ i+=2; } }
This algorithm can, without modification, be done in a functional language. For example, consider the following Haskell:
import Control.Monad.Loops
import Control.Monad
for_ :: (Monad m) => m () -> m Bool -> m () -> m ()
for_ init guard step body =
init >>
whileM_ guard (body >> step)
loop :: [string] -> State Int ()
loop lines = for_ (put 0) (get (<(length lines))) (modify (+1)) (when (get >>= \i -> (lines!!i == "a")) (modify (+2)))
I did not use do notation to avoid accusations of cheating; and am defining for_ here because Haskell's standard library for loop only iterates through data-structures (like the for loop of many imperative languages). I will also admit that the Haskell version is ugly due to its verbosity (because, even though it is possible, it is not how you are supposed to do things in Haskell).
EDIT: Made for_ generic and added type signature for loop.
If you want multiple "variables" in this approach, you can define a datatype to store them:
data S = S { i :: Int ... }
In this case, we can access i by replacing "get" with "gets i" in the above example ( "i" being an accessor function that Haskell automatically defines when we create a datatype with a field called "i"). You can imagine the generated value "i" being a more complicated datatype that can be both a getter and setter, in which case we can define "puts i" to be the analog of "gets i" and "put".
I think I have seen this approach done in Haskell but cannot remember what it is called.
- dvfjsdhgfv 10y ago> This algorithm can, without modification, be done in a functional language. For example, consider the following Haskell: The OP clearly stated the iterative version is cleaner, and you seem to confirm his pint.
- mathetic 10y agoExcept it is not cleaner. It is just more familiar to you because most languages in use in the past 40 years have been influenced by Algol family of languages for their syntax. Now the author is being modest here: First, `for` is defined out of simpler function `while`. You can do the same for the for loop in C of course, but only as a function call and to pass arbitrary body you would need to use a function pointer, which I argue is overwhelmingly more confusing. You may have different opinions merits of of baking non-orthagonal features into the compiler, but surely you'll appreciate the clarity here. Second, `do` notation is not used which would make it look more like Algol family of languages with semicolons to delimit (if "statements" (really, monadic expressions) are on the same line otherwise line feed is enough.) and less `>>=` would appear. Third, giving type annotations which can always be inferred unless you are using advanced extensions such as Generalised Algebraic Data Types (GADTs), which are not used here. Also less characters do not mean cleaner. For example the `loop`'s type annotation produces a `State` monad with `Int` as the state. This means that `loop` will not be connecting the Internet, it will not be throwing an exception [0], etc. Even in the narrow effect of manipulating state it guarantees it will only simulate mutation of a single variable of type `Int`. All of that guaranteed from a single line is a remarkable manifestation of clarity. [0] I don't account for undefined and the problem of strictness, that's a discussion for another day.
- spion 10y agodo notation is not cheating - I would not avoid it. IMO its important to share awareness that Haskell can do procedural, imperative code just fine and even has nice sugar for it.
- codygman 10y agoDo notation isn't cheating! For instance see these tips on writing g readable Haskell: http://www.haskellforall.com/2015/09/how-to-make-your-haskell-code-more.html http://www.haskellforall.com/2015/09/how-to-make-your-haskel... One of the big ones is always using do notation.