If statements questions in OCaml - ocaml

I am trying to write the following code in OCaml:
let a = 0
let b = 1
if a > b then
{
print_endline "a";
print_endline "a";
}
print_endline "b"
And then I encountered the following error:
File "[21]", line 4, characters 0-2:
4 | if a > b then
^^
Error: Syntax error
I have tried using the begin and end keywords.

If you're writing a program (rather than mucking about in a REPL), then there are only certain constructs which can exist at the top level of your program.
One of those is a binding. So the following is fine:
let a = 0
let b = 1
But a conditional expression (if/else) is not permitted. We can get around this by binding that expression to a pattern. Since print_endline will just return (), we can write:
let () =
...
Your use of { and } is incorrect in this situation, but you can grouped multiple expressions with ; and ( and ). Remember that ; is not a "statement terminator" but rather a separator.
let () =
if a > b then (
print_endline "a";
print_endline "a"
);
print_endline "b"
Note that if can only exist without a matching else if the entire expression returns unit. This meets that criteria.

Related

Pretty-printing with a comment string prefixing a box

I am trying to generate a text file for use in another program. This program only has line-style comments. I want to pretty-print a comment that, whenever the line is broken, it is prefixed by //.
Here is what I have so far:
type elaborate_type = A | B
let elaborate_to_string = function
| A -> "OK, this is type A, but long"
| B -> "B"
let pp_elaborate chan v = Format.pp_print_string chan (elaborate_to_string v)
Format.printf "#[<hv2>{#,#[<hov>// Here is a long comment I want to break# // \
here, but also indent. It should also be the case that anything# // \
I put here (such as some complex printable term \"%a\") should# // \
only break if it has //, too).#]#,\
#[...#]\
#]#,}#."
pp_elaborate A
which gives the output
{
// Here is a long comment I want to break
// here, but also indent. It should also be the case that anything
// I put here (such as some complex printable term "OK, this is type A, but long") should
// only break if it has //, too).
...
}
Is there a way to do this without adding the //# to the end of each line I want to break?
A option to solving this issue is to update the newline function of the formatter to make it prints // right after the newline:
let add_double_slash_after_linebreak_and_before_indents fmt =
let fns = Format.pp_get_formatter_out_functions fmt () in
let out_newline () =
fns.out_newline ();
fns.out_string "//" 0 2
in
Format.pp_set_formatter_out_functions fmt { fns with out_newline}
let () =
let () =
add_double_slash_after_linebreak_and_before_indents Format.std_formatter
in
Format.printf "#[<v 2>This tests the formatting#,One line#,two line #]"
This tests the formatting
// One line
// two line val add_double_slash_after_linebreak_and_before_indents :
However, the double slashes // will appear at the start of the line independently of the indentation, if you prefer them to appear after the indentation, you can update the indentation function of the formatter instead:
let add_double_slash_after_linebreak_and_indents fmt =
let fns = Format.pp_get_formatter_out_functions fmt () in
let out_indent n =
fns.out_indent n;
fns.out_string "//" 0 2
in
Format.pp_set_formatter_out_functions fmt { fns with out_indent}
let () =
let () =
add_double_slash_after_linebreak_and_indents Format.std_formatter
in
Format.printf "#[<v 2>This tests the formatting#,One line#,two line #]"
This tests the formatting
//One line
//two line
Concerning your follow-up question, any \n in a string will mess up the formatting if there are printed with %s. You can avoid this issue by using pp_print_text which replaces and \n in the string by calls to pp_print_space and pp_force_line.

What is this OCaml function returning?

As I understand it, OCaml doesn't require explicit return statements to yield a value from a function. The last line of the function is what returns something.
In that case, could someone please let me know what the following function foo is returning? It seems that it's returning a stream of data. Is it returning the lexer?
and foo ?(input = false) =
lexer
| 'x' _
-> let y = get_func lexbuf
get_text y
| ',' -> get_func lexbuf
| _ -> get_text lexbuf
I'm trying to edit the following function, bar, to return a data stream, as well, so that I can replace foo with bar in another function. However, it seems that bar has multiple lexers which is preventing this return. How can I rewrite bar to return a data stream in a similar way that foo appears to?
let bar cmd lexbuf =
let buff = Buffer.create 0 in
let quot plus =
lexer
| "<" -> if plus then Buffer.add_string b "<" quot plus lexbuf
and unquot plus =
lexer
| ">" -> if plus then Buffer.add_string b ">" unquot plus lexbuf
in
match unquot true lexbuf with
| e -> force_text cmd e
First, your code is probably using one of the old camlp4 syntax extension, you should precise that.
Second, foo is returning the same type of value as either get_text or get_funct. Without the code for those functions, it is not really possible to say more than that.
Third,
Buffer.add_string b ">" unquot plus lexbuf
is ill-typed. Are you missing parentheses:
Buffer.add_string b ">" (unquot plus lexbuf)
?

How can I convert the captured pattern in a regex replace to uppercase?

I want to replace /test/test1 with TEST1:. This is what I started with:
extern crate regex; // 1.0.1
use regex::Regex;
fn main() {
let regex_path_without_dot = Regex::new(r#"/test/(\w+)/"#).unwrap();
let input = "/test/test1/test2/";
// Results in "test1:test2/"
let result = regex_path_without_dot.replace_all(input, "$1:");
}
I have tried using
let result = regex_path_without_dot.replace_all(&input, "$1:".to_uppercase());
but I get this error:
error[E0277]: the trait bound `for<'r, 's> std::string::String: std::ops::FnMut<(&'r regex::Captures<'s>,)>` is not satisfied
--> src/main.rs:10:41
|
10 | let result = regex_path_without_dot.replace_all(&input, "$1:".to_uppercase());
| ^^^^^^^^^^^ the trait `for<'r, 's> std::ops::FnMut<(&'r regex::Captures<'s>,)>` is not implemented for `std::string::String`
|
= note: required because of the requirements on the impl of `regex::Replacer` for `std::string::String`
How do I implement this required trait? Is there a simple way to do this?
Regex::replace has the signature
pub fn replace<'t, R: Replacer>(&self, text: &'t str, rep: R) -> Cow<'t, str>
Replacer is implemented by:
&'a str
ReplacerRef<'a, R> where R: Replacer
F where F: FnMut(&Captures) -> T, T: AsRef<str>
NoExpand<'t>
There is no implementation for String, which is the direct cause of your error message. You could "fix" the error by converting your String into a string slice:
replace_all(&input, &*"$1:".to_uppercase()
Since the uppercase version is the same as the lowercase version, nothing will usefully change.
However, the implementation of Replacer by a closure is useful:
let result = regex_path_without_dot.replace_all(&input, |captures: &regex::Captures| {
captures[1].to_uppercase() + ":"
});
replace_all(&input, "$1:".to_uppercase())
This shows a fundamental error in understanding how this functionality works or in function precedence. This is the same as saying:
let x = "$1:".to_uppercase();
replace_all(&input, x)
Or, equivalently, since 1 is the uppercase 1 and $ is the uppercase $:
let x = String::from("$1:");
replace_all(&input, x)
Calling a function like to_uppercase isn't magically deferred until "some later point".

writing main() to call a function

I have an OCaml function that converts a string to an array. What is the canonical way of writing a "main" function to call this and print the array.
let createArray pattern patArray =
(* some unimportant way of setting all the elements in the array patArray
based on the string pattern *)
let main () =
let pattern = "Pattern" in
let patArray = Array.create (String.length pattern) 0 in
let res = createArray pattern patArray in
Array.iter ~f:(printf "%d ") patArray;; <------------------
main ()
1) In the above, if I leave out the ';;' , it does not work. What is the significance of that?
2) Instead of using a dummy binding "res" , can I somehow just write two statements to be executed sequentially , like so:
createArray pattern patArray
Array.iter ~f:(printf "%d ") patArray
Without the ;;, the parser cannot know that the main () call following that line is supposed to be a stand-alone expression (whitespace is not significant here).
You can use the following idiom instead:
let main () = ...
let () = main ()
The let () = expr idiom will evaluate an expression of type unit at that point. The initial let informs the parser that a new top-level let construct begins. Using ;; is an alternative way to tell the parser about the end of a top-level construct, but is primarily intended for interactive use.
In order to evaluate two expressions sequentially, separate them with a semicolon (use parentheses or begin ... end if you're unsure about precedence rules). For example:
let patArray = Array.create (String.length pattern) 0 in
createArray pattern patArray;
Array.iter ~f:(printf "%d ") patArray
Or, using begin and end to make precedence clearer:
let patArray = Array.create (String.length pattern) 0 in begin
createArray pattern patArray;
Array.iter ~f:(printf "%d ") patArray
end
Without the ;, the parser would not know whether Array.iter on the next line is supposed to an additional argument to the createArray call.

How does regex capturing work in scala?

Here is an example:
object RegexTest {
def main (args: Array[String]): Unit = {
val input = "Enjoy this apple 3.14 times"
val pattern = """.* apple ([\d.]+) times""".r
val pattern(amountText) = input
val amount = amountText.toDouble
println(amount)
}
}
I understand what this does, but how does val pattern(amountText) = input actually work? It looks very weird to me.
What that line is doing is calling Regex.unapplySeq (which is also called an extractor) to deconstruct input into a list of captured groups, and then bind each group to a new variable. In this particular scenario, only one group is expected to be captured and bound to the value amountText.
Validation aside, this is kinda what's going on behind the scenes:
val capturedGroups = pattern.unapplySeq(input)
val amountText = capturedGroups(0)
// And this:
val pattern(a, b, c) = input
// Would be equivalent to this:
val capturedGroups = pattern.unapplySeq(input)
val a = capturedGroups(0)
val b = capturedGroups(1)
val c = capturedGroups(2)
It is very similar in essence to extracting tuples:
val (a, b) = (2, 3)
Or even pattern matching:
(2,3) match {
case (a, b) =>
}
In both of these cases, Tuple.unapply is being called.
I suggest you have a look at this page : http://docs.scala-lang.org/tutorials/tour/extractor-objects.html. It is the official tutorial regarding extractors which this the pattern you are looking for.
I find that looking at the source makes it clear how it works : https://github.com/scala/scala/blob/2.11.x/src/library/scala/util/matching/Regex.scala#L243
Then, note that your code val pattern(amountText) = input is perfectly working, but, you must be sure about the input and be sure that there is a match with the regex.
Otherwise, I recommend you to write it this way :
input match {
case pattern(amountText) => ...
case _ => ...
}