Basic ocaml program not compiling

一个人想着一个人 提交于 2020-01-15 10:28:08

问题


I was trying to write a piece of code that checks if a sentence is a palindrome (if we don't consider spaces and case) but my code won't compile. I get the following error :

File "main.ml", line 12, characters 0-2:
Error: Syntax error

This error corresponds to the second program, line 12 being where the ;; are at.

Entire program

let scan_word () = Scanf.scanf " %s" (fun x -> x)
in
let scan_int () = Scanf.scanf " %d" (fun x -> x)
in
let scan_float () = Scanf.scanf " %f" (fun x -> x)
in
let scan_char () = Scanf.scanf " %c" (fun x -> x)
in
let maj_to_min = function
    | c when (c >= 'a' && c <= 'z') -> c
    | c -> (char_of_int ( (int_of_char c) - (int_of_char 'A') + (int_of_char 'a')))
in

let convert_string s = 
    let n = String.length s in
    let cur = ref 0 in
    let arr = Array.make n ' ';
    for i = 0 to (n-1)
    do
        if s.[i] <> ' ' 
        then begin
            arr.(!cur) <- maj_to_min s.[i];
            incr cur;
        end;
    done;
    (Array.sub arr 0 cur)
in

let is_palindrome arr =
    let n = Array.length arr in
    let ans = ref true in

    for i = 0 to (n-1)
    do
        ans := (!ans) && (arr.(i) = arr.(n-1-i));
    done;
    !ans
in

let n = read_int () in

for i = 1 to n
do
    let s = read_line () in 
    if (is_palindrome (convert_string s)) = true  then print_endline s
done;;

Minimal program which doesn't compile :

let scan_word () = Scanf.scanf " %s" (fun x -> x)
in
let scan_int () = Scanf.scanf " %d" (fun x -> x)
in
let scan_float () = Scanf.scanf " %f" (fun x -> x)
in
let scan_char () = Scanf.scanf " %c" (fun x -> x)
in
let maj_to_min = function
    | c when (c >= 'a' && c <= 'z') -> c
    | c -> (char_of_int ( (int_of_char c) - (int_of_char 'A') + (int_of_char 'a')))
;;

The maj_to_min converts upper case letts to lower-case letters.
I'd like to understand where did I make a mistake when writing code ! Thanks in advance.


回答1:


It doesn't compile because your code is not a syntactically valid OCaml.

An OCaml program is a sequence of value, type, module, and other definitions. Your particular example is trying to define several values. A value definition in OCaml is having the following syntax

let <name> = <value> 

Note, that there is no in part. So the correct (syntactically at least) program would look like this

let scan_word () = Scanf.scanf " %s" (fun x -> x)
let scan_int () = Scanf.scanf " %d" (fun x -> x)
let scan_float () = Scanf.scanf " %f" (fun x -> x)
let scan_char () = Scanf.scanf " %c" (fun x -> x)
let maj_to_min = function
    | c when (c >= 'a' && c <= 'z') -> c
    | c -> (char_of_int ( (int_of_char c) - (int_of_char 'A') + (int_of_char 'a')))

This program will define 5 functions. Neither will be called, so you would probably like to add a definition that will call it.

The main difference between let <name> = <expr-1> in <expr-2> and let <name> = <expr> is that the latter is the value definition which occurs on the program/module top-level. It is the closest to the what is named statement in other languages. The former, I mean the let <name> = <expr-1> in <expr-2> is an expression, which can occur in any place where an expression is expected. And usually it is used to build complex expressions. e.g.,

let input_user () = 
    let name = scan_word () in
    let age = scan_int () in
    let weight = scan_float () in
    let gender = scan_char () in
    printf "%s is %d years old, weights %g pounds, and has gender %c\n"
       name age weight gender

and now to make your binary do something you can call this function, add the following value definition to the top-level of your program, e.g.,

   let () = input_user ()

This will serve as an entry point of your program.

To elaborate a little more, this is a general structure of an OCaml program:

(* this is the top-level of your file, each file defines a module 
   which has the name equal to the file name (but capitalized), 
   let's imagine that our file is named example.ml therefore it 
   defines a module named Example
 *)


(* this is a top-level constant that is visible to all code that is below 
    it. You can also access it from other files as `Example.version`.
 *)
let version = "0.0.1"


(* this is a mutable reference, the closest to the mutable and global 
   variable in C *)
let calls = ref 0

(* this is a simple function with two imperative expressions, which uses 
   values defined above *)
let make_a_call () = 
    incr calls;
    Printf.printf "we made %d calls so far in version %s\n" !calls version


(* this is a function, that defines local variables `d` and `e` and
   uses them. These variables are seen only in the body of this 
   function. More generally `let <v> = <e> in <body>` evaluates `<e>`
   binds it to `<v>` and makes `<v>` visible in the scope of `<body>` *)
let complex_function x y = 
   let d = x + y - 1 in
   let e = x * y + 2 in
   (d + e) / (x + y)


(* we can even define function inside other functions, the 
   same as with `d` and `e` above, the `inner_function` is only 
   visible inside the `complex_function_with_functions` *)
let complex_function_with_functions x = 
   let inner_function y = 
      x + y in
   inner_function 5 + inner_function 6 


(* this is the main function. The name doesn't matter at all, well at
   least to OCaml. But it is usually a good idea to have one at least
   to cherish others who will be reading your code. This function
   demonstrates how you can interleave imperative expressions with
   `let` bindings` *)
let main () = 
   make_a_call ();
   let r = complex_function_with_functions 12 in
   make_a_call ();
   let p = complex_function r 16 in 
   make_a_call ();
   Printf.printf "wow: we get %d and %d, don't know what it means\n" r p


(* finally, let's call the main function to actually run our program *)

let () = main ()

A pro tip, you don't really need to compile this file to run it, as OCaml has an interpreter, so if you put this code in the file named example.ml then it is as easy as,

$ ocaml example.ml 
we made 1 calls so far in version 0.0.1
we made 2 calls so far in version 0.0.1
we made 3 calls so far in version 0.0.1
wow: we get 35 and 12, don't know what it means


来源:https://stackoverflow.com/questions/57416477/basic-ocaml-program-not-compiling

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!