Utop and Ocamlc difference?

utop

#1

Gentlefolk,

Environment: Linux Mint 18.2, Ocaml 4.05.

I am writing a program which
Reads a file of lines of comma seperated data.
Breaks each line into seperate fields.
Applies checks (numeric, gender, first letter not a capital, etc…)
Reports any errors.

The code uses List.mapi to ‘iter’ over the data and return the results of checks on each field.

I am having troubles with test code which seemingly works in “utop” and fails to compile in ocamlc.

Utop code:
# let process_field ctr word = 
  (* Process/check each field of the record *)
  printf "%d %s\n" ctr (word "a"); process_field in
  "OK" ;; (* Test purposes.... *)
# let process_fields in_line =
  (* Check each field in 'in_line'. Report issues... *)
  begin
    (* String/Str function/s, requires 'str.cma' on ocamlc CLI *) 
    let words = Str.split (Str.regexp "[,\t]+") in_line in
      List.mapi (process_field) words;  (* Passes field index and data[index] *)   
  end;;

# process_fields "abc,def,ghi";;

Results displayed are;

# process_fields "abc,def,ghi";;
0 abc a
1 def a
2 ghi a
- : string list = ["OK"; "OK"; "OK"]

The same code compiled with ocamlc results in the following error:

Error: Unbound value process_field… Line 37

Line 37 is the code in function "process_field" 
  printf "%d %s\n" ctr (word "a"); process_field in 

I am new to Ocaml and struggling with many things. Any help appreciated.

Ian


#2

process_field should be recursive (let rec), otherwise you’re referring to a previously defined function with the same name.


#3

Please wrap your code using

```
code
```

to make it more readable.


#4

Thank you for the response but things are not as simple as they may seem.

I have struggled to get the List.mapi mechanism to work and return the results of processing a field. The code in “process_field” is for test purposes and is the result of hacking around until something worked.

I am unsure about the need for recursion. If I add “rec” to “process_field” I get an error in utop as follows:

let rec process_field ctr word = 
  (* Process/check each field of the record *)
  printf "%d %s\n" ctr (word "a"); process_field in (* <<<< process_field underlined!!! *)
  "OK" ;;

  Error: This expression has type int -> (string -> string) -> 'a
       but an expression was expected of type 'a
       The type variable 'a occurs inside int -> (string -> string) -> 'a

A similar error occurs in ocamlc with the same code.

I think my problem is more how to code List.map field return processing. Any help appreciated.

Ian.


#5

Hold on, your code actually says

let process_field ctr word = printf “%d %s\n” ctr (word “a”); process_field in

That code makes no sense to me. I can’t figure out what it would mean, and that probably means the type error from the compiler is sensible. You’re giving it a value of one type and it isn’t expecting something of that type there.

And please, please, please edit your original post to show the code as code?


#6

Perry, you are most likely correct about the code making much sense, I have been trying a lot of things.

I have studied an example of the use of Ocaml and List.mapi when applied to matrix manipulation on Stack Overflow. Used some of the code in utop and ocamlc and it compiles clean.
I applied what I learned to “my” test code, corrected some stupidities and came up with the following

let process_field ctr word = 
  (* Process/check each field of the record *)
  printf "%d %s\n" ctr (word "a") in 
  "OK" ;;
   
let process_fields in_line = 
  (* Check each field in 'in_line'. Report issues... *)
  begin
    (* String/Str function/s, requires 'str.cma' on ocamlc CLI *) 
    let words = Str.split (Str.regexp "[,\t]+") in_line in
      List.mapi (process_field i x) words  (* Passes field index and data[index] *)   
  end;;

This runs well in utop but again fails in ocamlc. The error is “Error: Unbound value process_field” on the List.mapi line.

It appears to be an issue of scope.
But a similar structure with what I think is similar structure and scope compiles clean in ocamlc!!

let myfun m = 99;;

let replnth r n l =
    List.mapi (fun i x -> if i = n then  r else myfun x);;

Ian.


#7

The in in process_field makes this function local to the following constant expression. It’s definitely not what you want to do. Besides, the begin/end pair is useless in process_fields.

EDIT: sorry, I was wrong about recursion, I should’ve read further…


#8

Gentlefolk,

I am just writing to wrap this up. I have read a lot, thought a lot and finally got things working.

I am not a programmer but over 50+ years I sometimes crawled through the bowels of giant mainframes and communication systems. I wrote things in machine code, assembler and ancient languages like WIZ, Algol, GMAP etc to fix problems and improve systems and get things working for the applications and database people.

Outside of that my basic work tool was the Borland originated Pascal language. On CPM and basic Intel systems of the 80’s (3 floppies for the compiler and IDE) I used Turbo Pascal. Outside of work I used Turbo Pascal and Lazarus to write data entry, data management and analysis systems for the sport of athletics.

So I am a procedural person. I am now semi retired and as an intellectual exercise I have taken on the task of re-implementing and extending one of my athletics data analysis programs in Ocaml using the functional approach.

It is hard work… I keep slipping back into procedural mode. The compiler produces error messages which appear to depend on the phases of the moon. Write and test small functions…

Thanks for all the help, Ian.