In OCaml, I can use Printf.printf to output formatted string, like
Printf.printf "Hello %s %d\n" world 123
However, printf is a kind of output.
What I wish for is not for output, but for a string. For example, I want
let s = something "Hello %s %d\n" "world" 123
then I can get s = "Hello World 123"
How can I do that?
You can use Printf.sprintf:
# Printf.sprintf "Hello %s %d\n" "world" 123;;
- : string = "Hello world 123\n"
You can do this:
$ ocaml
OCaml version 4.00.1
# let fmt = format_of_string "Hello %s %d";;
val fmt : (string -> int -> '_a, '_b, '_c, '_d, '_d, '_a) format6 = <abstr>
# Printf.sprintf fmt "world" 123;;
- : string = "Hello world 123"
The format_of_string function (as the name implies) transforms a string literal into a format. Note that formats must ultimately be built from string literals, because there is compiler magic involved. You can't read in a string and use it as a format, for example. (It wouldn't be typesafe.)
Related
Because String.tokens is a curried function, I know I can change
String.tokens (fn c =\> c = #" ") "hello world";
to a string that would contain all the delimiters, but I am just confused about the actual dictation of how.
One of the forms that I tried was:
fun splitter nil = nil
| splitter str =
let
val c = " ,.;?:!\t\n"
val s = String.tokens (fn (c:string,x:char) => c=Char.toString c x) str
in
s
end;
With c being the string of the delimiters, but I know something is very wrong. If anyone could point me into the right direction that would be greatly appreciated.
String.tokens takes two arguments: a predicate to determine if a character is a token; and a string to split. The first argument is the important part. We don't have to specify a character to split on, just a rule to identify that character.
If you turn a string containing the token characters into a list with String.explode, then it's easy to use List.exists to find out if a character is in that token string.
fun splitOn(str, tokens) =
let
val tokens' = String.explode tokens
fun isToken c = List.exists (fn c' => c = c') tokens'
in
String.tokens isToken str
end;
splitOn("hello world | wooble. foo? bar!", " |.?!");
(* ["hello", "world", "wooble", "foo", "bar"] *)
I am very new to OCaml and am attempting to learn and write a program at the same time. I am writing a palindrome program. I am attempting to get a string from the user such as d e v e d or Hello World! or loud all of the preceding are valid user input. I need to read these strings and display them then reverse them and check if it is a palindrome or not. I did the following code...
print_string "Enter a string: ";
let str = read_line () in
Printf.printf "%s\n" str;;
Printf.printf "%s\n" str;;
this works fine and will give the print, Enter a string: d e v e d or Enter a string: Hello World! The issue comes when I try to add another Printf.printf "%s\n" str;; into the code. it gives me an error of File "main.ml", line 5, characters 21-24:
Error: Unbound value str with line 5 being the line of the 2nd Printf.printf statement. I have tried this with no ; for both of the print statements, with 1 or with 2 and I get the same error each time. Does anyone with more OCaml knowledge know why I get this error.
Because of your use of in your code parses as:
(let str = read_line () in Printf.printf "%s\n" str);;
and then a completely separate:
Printf.printf "%s\n" str;;
So str is local to the first printf.
You want:
let str = read_line ();;
Printf.printf "%s\n" str;;
Printf.printf "%s\n" str;;
which is three separate definitions. The first defines a global variable str.
I was expecting this
val string = "hello , world"
val regex = Regex("""(\s+)[,]""")
println(string.replace(regex, ""))
to result in this:
hello, world
Instead, it prints this:
hello world
I see that the replace function cares about the whole match. Is there a way to replace only the 1st group instead of the 0th one?
Add the comma in the replacement:
val string = "hello , world"
val regex = Regex("""(\s+)[,]""")
println(string.replace(regex, ","))
Or, if kotlin supports lookahead:
val string = "hello , world"
val regex = Regex("""\s+(?=,)""")
println(string.replace(regex, ""))
You can retrieve the match range of the regular expression by using the groups property of MatchGroupCollection and then using the range as a parameter for String.removeRange method:
val string = "hello , world"
val regex = Regex("""(\s+)[,]""")
val result = string.removeRange(regex.find(string)!!.groups[1]!!.range)
The problem is that I have a string like:
public class MyFirstJavaProgram {
public static void main ( String []args ) {
System.out.println ( "Hello World" );
}
}
When I try to get a string list like:
["public";"class";"MyFirstJavaProgram";...;"(";""Hello World"";")";"...]
Im getting
["public class MyFirstJavaProgram {"; "";
" public static void main ( String []args) {";
" System.out.println("Hello World"); "; " }"; "}"]
How can i remove those white spaces.
Given the sample output in the original question, I think the closest simple solution would be:
File.ReadAllText("MyFirstJavaProgram.java").Split([|' '; '\n'|], StringSplitOptions.RemoveEmptyEntries)
|> Array.map (fun s -> s.Trim())
However, this will not treat the string "Hello World" as one entry in the array. For that, you would need to use a proper tokenization algorithm.
If you are not interested in some lines, the way to go is filter:
File.ReadAllLines(...)
|> Seq.filter (not << String.IsNullOrWhiteSpace)
Then, you can split all lines:
|> Seq.collect (fun line -> line.Split([| " " |], StringSplitOptions.RemoveEmptyEntries))
RemoveEmptyEntries will remove empty lines and leading/trailing whitespace. So filtering is not needed anymore and no trimming is neccessary.
Note that this is not a proper Java tokenizer though, e.g. main( won't be split into main and ( but "Hello World" will be split into "Hello and World".
For doing proper Java parsing, look for a library.
Note that asking for and recommending libraries is not appropriate on StackOverflow. SoftwareRecommendations might be able to help.
I'd like to do something like this
String.concat '\n' [str1; str2 ... strn]
so I can print in a file. But ocaml doesn't allow me to do that. What can I do?
String.concat "\n" [str1; str2 ... strn]
works fine. The problem is that you used '\n', which is a character literal, not a string. Example:
# String.concat '\n' ["abc"; "123"];;
Error: This expression has type char but an expression was expected of type
string
# String.concat "\n" ["abc"; "123"];;
- : string = "abc\n123"
If you're using Jane Street's base module for your standard library you'll have to do it like so:
# #require "base";;
# open! Base;;
# String.concat ~sep:"\n" ["abc"; "123"];;
- : string = "abc\n123"
Jane Street really likes to take advantage of named arguments.