String manipulation in Erlang - string

I have a string like this:
"productName=\"NAME\"\n"
I want to change it to this:
"productName=NAME"
What is the best way to do this in Erlang?

I like also this one, easy to read, very close to Ning proposition:
1> A="productName=\"NAME\"\n".
"productName=\"NAME\"\n"
2> lists:filter(fun ($\") -> false; ($\n) -> false; (_) -> true end,A).
"productName=NAME"

One of probably many ways:
A = "productName=\"NAME\"\n".
re:replace(A, ["[\"\n]*"], "", [global, {return, list}]).

(Another) one of probably many ways:
S0 = "productName=\"NAME\"\n".
[Char || Char <- S0, not lists:member(Char, [$\", $\n])].

Another variant, for example if you want to do this just for that particular key but leave all others alone:
A = "productName=\"NAME\"\n".
case A of
"productName=" ++ S ->
"productName=" ++ string:strip(S, both, $");
_ ->
A
end.

Related

OCaml : need help for List.map function

I need to create a function that basically works like this :
insert_char("string" 'x') outputs "sxtxrxixnxg".
So here is my reasoning :
Create a list with every single character in the string :
let inserer_car(s, c) =
let l = ref [] in
for i = 0 to string.length(s) - 1 do
l := s.[i] :: !l
done;
Then, I want to use List.map to turn it into a list like ['s', 'x', 't', 'x' etc.].
However, I don't really know how to create my function to use with map. Any help would be appreciated!
I'm a beginner in programming and especially in ocaml! so feel free to assume I'm absolutely ignorant.
If you were using Core, you could write it like this:
open Core.Std
let insert_char s c =
String.to_list s
|> (fun l -> List.intersperse l c)
|> String.of_char_list
Or, equivalently:
let insert_char s c =
let chars = String.to_list s in
let interspersed_chars = List.intersperse chars c in
String.of_char_list interspersed_chars
This is just straightforward use of existing librariies. If you want the implementation of List.intersperse, you can find it here. It's quite simple.
A map function creates a copy of a structure with different contents. For lists, this means that List.map f list has the same length as list. So, this won't work for you. Your problem requires the full power of a fold.
(You could also solve the problem imperatively, but in my opinion the reason to study OCaml is to learn about functional programming.)
Let's say you're going to use List.fold_left. Then the call looks like this:
let result = List.fold_left myfun [] !l
Your function myfun has the type char list -> char -> char list. In essence, its first parameter is the result you've built so far and its second parameter is the next character of the input list !l. The result should be what you get when you add the new character to the list you have so far.
At the end you'll need to convert a list of characters back to a string.

Function definition with guards

Classic way to define Haskell functions is
f1 :: String -> Int
f1 ('-' : cs) -> f1 cs + 1
f1 _ = 0
I'm kinda unsatisfied writing function name at every line. Now I usually write in the following way, using pattern guards extension and consider it more readable and modification friendly:
f2 :: String -> Int
f2 s
| '-' : cs <- s = f2 cs + 1
| otherwise = 0
Do you think that second example is more readable, modifiable and elegant? What about generated code? (Haven't time to see desugared output yet, sorry!). What are cons? The only I see is extension usage.
Well, you could always write it like this:
f3 :: String -> Int
f3 s = case s of
('-' : cs) -> f3 cs + 1
_ -> 0
Which means the same thing as the f1 version. If the function has a lengthy or otherwise hard-to-read name, and you want to match against lots of patterns, this probably would be an improvement. For your example here I'd use the conventional syntax.
There's nothing wrong with your f2 version, as such, but it seems a slightly frivolous use of a syntactic GHC extension that's not common enough to assume everyone will be familiar with it. For personal code it's not a big deal, but I'd stick with the case expression for anything you expect other people to be reading.
I prefer writing function name when I am pattern matching on something as is shown in your case. I find it more readable.
I prefer using guards when I have some conditions on the function arguments, which helps avoiding if else, which I would have to use if I was to follow the first pattern.
So to answer your questions
Do you think that second example is more readable, modifiable and elegant?
No, I prefer the first one which is simple and readable. But more or less it depends on your personal taste.
What about generated code?
I dont think there will be any difference in the generated code. Both are just patternmatching.
What are cons?
Well patternguards are useful to patternmatch instead of using let or something more cleanly.
addLookup env var1 var2
| Just val1 <- lookup env var1
, Just val2 <- lookup env var2
= val1 + val2
Well the con is ofcourse you need to use an extension and also it is not Haskell98 (which you might not consider much of a con)
On the other hand for trivial pattern matching on function arguments I will just use the first method, which is simple and readable.

Multiplying a string in F#

I have a question I am rather unsure about.
My questions is as follows
let myFunc (text:string) (times:int) = ....
What I want this function to do is put the string together as many times as specified by the times parameter.
if input = "check " 3 I want the output string = "check check check"
I have tried with a loop, but couldn't seem to make it work.
Anyone?
Actually the function is already in String module:
let multiply text times = String.replicate times text
To write your own function, an efficient way is using StringBuilder:
open System.Text
let multiply (text: string) times =
let sb = new StringBuilder()
for i in 1..times do
sb.Append(text) |> ignore
sb.ToString()
If you want to remove trailing whitespaces as in your example, you can use Trim() member in String class to do so.
A variation on pad's solution, given that it's just a fold:
let multiply n (text: string) =
(StringBuilder(), {1..n})
||> Seq.fold(fun b _ -> b.Append(text))
|> sprintf "%O"
If you want a pure functional "do-it-yourself" version for F# learning purposes, then something like the following snippet will do:
let myFunc times text =
let rec grow result doMore =
if doMore > 0 then
grow (result + text) (doMore- 1)
else
result
grow "" times
Here is the test:
> myFunc 3 "test";;
val it : string = "testtesttest"
Otherwise you should follow the pointer about the standard F# library function replicate given in pad's answer.
String.replicate already provides the functionality you're looking for.
If for some reason you want the arguments reversed, you can do it as follows:
(* A general function you should add to your utilities *)
let flip f a b = f b a
let myFunc = flip String.replicate
In a simple recursive fashion:
let rec dupn = function
|s,1 -> s
|s,n -> s ^ dupn(s, n-1)

Case Insensitive Pattern Matching over String Lists

I'm trying to parse command line arguments in an F# application. I'm using pattern matching over parameters list to accomplish it. Something like:
let rec parseCmdLnArgs =
function
| [] -> { OutputFile = None ; OtherParam = None }
| "/out" :: fileName :: rest -> let parsedRest = parseCmdLnArgs rest
{ OutputFile = Some(fileName) with parsedRest }
The problem is I want to make "/out" match case insensitive while preserving the case of other stuff. That means I can't alter the input and match the lowercase version of the input against it (this will lose the fileName case information).
I have thought about several solutions:
Resort to when clauses which is less than ideal.
Match a tuple each time, the first would be the actual parameter (which I'll just save for further processing and will wildcard match it) and the second would be the lowercased version used in such matchings. This looks worse than the first.
Use active patterns but that looks too verbose. I'll have to repeat things like ToLower "/out" before every item.
Is there a better option/pattern for doing these kind of stuff? I think this is a common problem and there should be a good way to handle it.
I quite like your idea of using F# active patterns to solve this. It is a bit more verbose than using pre-processing, but I think it's quite elegant. Also, according to some BCL guidelines, you shouldn't be using ToLower when comparing strings (ignoring the case). The right approach is to use OrdinalIgnoreCase flag. You can still define a nice active pattern to do this for you:
open System
let (|InvariantEqual|_|) (str:string) arg =
if String.Compare(str, arg, StringComparison.OrdinalIgnoreCase) = 0
then Some() else None
match "HellO" with
| InvariantEqual "hello" -> printfn "yep!"
| _ -> printfn "Nop!"
You're right that it's more verbose, but it nicely hides the logic and it gives you enough power to use the recommended coding style (I'm not sure how this could be done using pre-processing).
I might do some pre-processing to allow for either "-" or "/" at the beginning of keywords, and to normalize the case:
let normalize (arg:string) =
if arg.[0] = '/' || arg.[0] = '-' then
("-" + arg.[1..].ToLower())
else arg
let normalized = args |> List.map normalize
It's perhaps not ideal, but it's not like any user is going to have enough patience to type so many command-line parameters that looping through them twice is noticeably slow.
You can use guards to match your deal:
let rec parseCmdLnArgs =
function
| [] -> { OutputFile = None ; OtherParam = None }
| root :: fileName :: rest when root.ToUpper() = "/OUT" -> let parsedRest = parseCmdLnArgs rest
{ OutputFile = Some(fileName) with parsedRest }
Ran into this looking for a solution to a similar issue, and while Tomas' solution works for individual strings, it doesn't help with the original issue of pattern matching against lists of strings. A modified version of his active pattern allows matching lists:
let (|InvariantEqual|_|) : string list -> string list -> unit option =
fun x y ->
let f : unit option -> string * string -> unit option =
fun state (x, y) ->
match state with
| None -> None
| Some() ->
if x.Equals(y, System.StringComparison.OrdinalIgnoreCase)
then Some()
else None
if x.Length <> y.Length then None
else List.zip x y |> List.fold f (Some())
match ["HeLlO wOrLd"] with
| InvariantEqual ["hello World";"Part Two!"] -> printfn "Bad input"
| InvariantEqual ["hello WORLD"] -> printfn "World says hello"
| _ -> printfn "No match found"
I haven't been able to figure out how to make it match with placeholders properly to do | InvariantEqual "/out" :: fileName :: rest -> ... yet, but if you know the entire contents of the list, it's an improvement.

F#: Remove the first N characters from a string?

I'm trying to write some code to remove the first N characters in a string. I could have done this in an imperative manner already, but I would like to see it done in the spirit of functional programming. Being new to F# and functional programming, I'm having some trouble...
"Hello world".[n..];;
As #Jeff has shown, you can do this in six characters, so this is not necessarily the best question to ask to see how to "do it in the spirit of functional programming".
I show another way, which is not particularly "functional" (as it uses arrays, but at least it doesn't mutate any), but at least shows a set of steps.
let s = "Hello, world!"
// get array of chars
let a = s.ToCharArray()
// get sub array (start char 7, 5 long)
let a2 = Array.sub a 7 5
// make new string
let s2 = new string(a2)
printfn "-%s-" s2 // -world-
"Hello world".Substring 3
let rec remove_first_n (str:string) (n:int) =
match str, n with
| _, n when n <= 0 -> str
| "", _ -> ""
| _ -> remove_first_n (str.Remove(0,1)) (n-1)
Another way to do it (not particularly functional either). In fact it uses features of both world: mutation and lambda:
let remove_first_n (s:string) (n:int) =
let arr = Array.create (s.Length-n) '0'
String.iteri (fun i c -> if i>=n then arr.[i-n] <- c else ()) s
new string(arr)
That being said, I think the best way is Jeff's solution.
One more thing to keep in mind is that Strings are immutable in .NET (a string value cannot be modified once built) and that F# strings are actually .NET Strings.

Resources