Reputation: 2039
I would like to be able to create a string using printf like functionality, with the variables drawn from a list and inserted into a template string.
i.e.
let templateStr = "First comes %s, then comes %s, after which comes %s"
let vars = ["one","two", "three"]
and some function returns:
function returns >>> First comes one, then comes two, after which comes three
i.e. in Python I could do something like:
>>> templateStr = "First comes %s, then comes %s, after which comes %s"
>>> vars = ["one","two", "three"]
>>> outputStr = tempStr % tuple(vars)
>>> print outputStr
First comes one, then comes two, after which comes three
My Attempt
mergeList :: [a] -> [a] -> [a]
mergeList [] ys = ys
mergeList (x:xs) ys = x:mergeList ys xs
-- not actually needed * use: Prelude.concat
listConcat :: [[a]] -> [a]
listConcat [] = []
listConcat (x:xs) = x ++ listConcat xs
-- via @dfeuer list concat is not need because of Prelude.concat
printf' :: String -> [String] -> String
printf' s v = concat $ mergeList (splitOn "%s" s) v
Attempt via @Reid Barton
printf' :: String -> [String] -> String
printf' ('%':'s':rest) (v:vs) = v ++ printf' rest vs
printf' (c:rest) vs = c : printf' rest vs
printf' [] _ = []
both attempts give
>>> let templateStr = "First comes %s, then comes %s, after which comes %s"
>>> let vars = ["one","two", "three"]
>>> printf' templateStr vars
"First comes one, then comes two, after which comes three"
Upvotes: 3
Views: 353
Reputation: 14999
The outline of another, more direct approach:
printf' ('%':'s':rest) (v:vs) = ...
printf' (c:rest) vs = ...
... -- handle the remaining cases too
Upvotes: 3
Reputation: 48581
Great start! mergeList
is very clean.
mergeList :: [a] -> [a] -> [a]
mergeList [] ys = ys
mergeList (x:xs) ys = x:mergeList ys xs
listConcat :: [String] -> String
listConcat [] = []
listConcat (x:xs)
| null xs = x
| otherwise = x ++ listConcat xs
You can do better than this for listConcat
. In particular, you currently use two base cases for the recursion, but you only need one. Furthermore, you can change the type signature to listConcat :: [[a]] -> [a]
to make it more general. Once you've cleaned up your version: There's a function like that in the standard library. Can you find it?
Upvotes: 1