i try the below code to do a recursive from i -> 0 and output white space
let print_tab fmt i =
match i with
| 0 -> put fmt "%s" ""
| _ -> put fmt "%s" " " ; print_tab fmt (i-1)
however it does not work, show the error like below
Error: This function is applied to too many arguments;
maybe you forgot a `;'
i have try another code
let print_tab fmt = function
| 0 -> put fmt "%s" ""
| j -> put fmt "%s" " " ; print_tab fmt (j-1)
but it get the same error, what's wrong?
The error is that you forgot rec so your function is not recursive and tries to use a previously defined version of print_tab.
Related
I found this code to evaluate expressions in OCaml on the internet and want to try to understand how it works, but when I enter it in my editor and run it I get the following error:
type t =
| Integer of int
| Binary of binary * t * t
and binary =
| Add
| Sub
| Mult
| Div
type token =
| INTEGER of int
| ADD
| SUB
| MULT
| DIV
let rec eval = function
| Integer(k) -> k
| Binary(op, a, b) ->
(match op with
| Add -> ( + )
| Sub -> ( - )
| Mult -> ( * )
| Div -> ( / )) (eval a) (eval b)
let lexer s =
let open Str in
let split s =
let rec splitchar x l =
if x< 0 then l else splitchar (x-1) ( s.[x]:: l ) in
splitchar ( String.length s -1) []
|> List.map
(function
| "+" -> ADD
| "-" -> SUB
| "*" -> MULT
| "/" -> DIV
| _ -> failwith "lexer: Invalid token: %s" );;
Characters 280-282:
| _ -> failwith "lexer: Invalid token: %s" );;
^^
Error: Syntax error
The error message doesn't help very much and I've tried a few changes that only make things worse. Can anyone help me get started by figuring out what the syntax error is?
There is a couple of issues :
split is defined but not used.
failwith expects a string, not a format.
For the first issue : you have to use split before List.map:
...in split s | List.map...
failwith expect a string, in the current case, the mistake is that it is a string that looks more a format string that waits for another string.
The fix is as below :
- first catch the string
- then use it to form the final string expected by failwith
(function
| "+" -> ADD <br>
| "-" -> SUB <br>
| "*" -> MULT <br>
| "/" -> DIV <br>
| _ as s -> failwith ("lexer: Invalid token: " ^ s) );;
But I am not sure at all the whole code will work....
in ast.ml, the structure is below:
type beantype =
| Bool
| Int
| TLr of fieldsrec
| TId of ident
and fieldsrec = { fields : field list }
and field =
| FIe of (ident * beantype)
in printer.ml, i use it like below:
let rec print_bean fmt = function
| Bool -> put fmt "%s" "bool"
| Int -> put fmt "%s" "int"
| TLr f -> put fmt "%s" "{"; print_fieldsrec fmt f ; put fmt "%s" "}"
| TId id -> put fmt "%s" id
and print_fieldsrec fmt = function
| f :: fe -> print_field fmt f; put fmt "%s" "," ; print_fieldsrec fmt fe
and print_field fmt = function
| FIe (id, beantype) -> put fmt "%s" id; put fmt "%s" ":"; print_bean fmt beantype
However it said the different pattern match in print_fieldsrec
Error: This pattern matches values of type 'a list
but a pattern was expected which matches values of type
Bean_ast.fieldsrec
how can i change the printer.ml?
You seem to be confused by the type fieldsrec = { fields : field list }. You should have followed Jeffrey's advice of using | Fields of field list instead.
fieldsrec is not a list, it is a record containing a list, so
print_fieldsrec fmt = function f :: fe -> ...
doesn't have the type its name suggests.
Also you forgot the base case for the recursive print_fieldsrec.
Taken from the chapter 18 of the Real World OCaml book, I'm trying to break down the example given.
My scope, to just make the GET call and print something of the JSON we get back.
This is my code ( it's supposed to be a subset of the example given )
(* libraries *)
open Core.Std
open Async.Std
(* Generate a DuckDuckGo search URI from a query string *)
let query_uri query =
let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in
Uri.add_query_param base_uri ("q", [query])
(* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *)
let get_definition_from_json json_string =
match Yojson.Safe.from_string json_string with
| `Assoc kv_list ->
let find key =
begin match List.Assoc.find kv_list key with
| None | Some (`String "") -> None
| Some s -> Some (Yojson.Safe.to_string s)
end
in
begin match find "Abstract" with
| Some _ as x -> x
| None -> find "Definition"
end
| _ -> None
(* Execute the DuckDuckGo search *)
let get_definition word =
print_endline ("get_definition word:" ^ word);
Cohttp_async.Client.get (query_uri word)
>>= fun (_, body) ->
Pipe.to_list (Cohttp_async.Body.to_pipe body)
>>| fun strings ->
(word, get_definition_from_json (String.concat strings))
(* run *)
let () =
get_definition "OCaml"
>>= fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
)
My issue is that I get this error when compiling:
ocaml setup.ml -build
Finished, 0 targets (0 cached) in 00:00:00.
+ /Users/antouank/.opam/system/bin/ocamlfind ocamlc -c -g -annot -bin-annot -thread -package yojson -package threads -package textwrap -package re2 -package core -package cohttp.async -I src -o src/main.cmo src/main.ml
File "src/main.ml", line 48, characters 18-41:
Error: This expression has type unit but an expression was expected of type
'a Async.Std.Deferred.t = 'a Async_kernel.Deferred0.t
Command exited with code 2.
Compilation unsuccessful after building 2 targets (0 cached) in 00:00:00.
E: Failure("Command ''/usr/local/bin/ocamlbuild' src/main.native -use-ocamlfind -tag debug' terminated with error code 10")
make: *** [build] Error 1
How can I get the string out of that Deferred, and what does that error mean exactly?
In the book, the example is run with a weird Command wrap, so I cannot see how to pull it out.
The problem in your definition of run is that the anonymous function
fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
)
is not correctly typed to be used with a monadic operator >>=. It has type string * string -> unit while the >>= would here expect a function of type string * string -> unit Deferred.t.
If you look at the example of an echo server in the very same chapter, it will suggest the following approach:
let run () =
get_definition "OCaml"
>>= fun (word, def) ->
print_endline ("- word: " ^ word);
(
match def with
| None -> print_endline "[EMPTY]"
| Some str -> print_endline str
);
Deferred.return()
let () =
ignore(run ());
never_returns (Scheduler.go ())
I'm trying to use the CIL library to parse C source code. I'm searching for a particular function using its name.
let cil_func = Caml.List.find (fun g ->
match g with
| GFun(f,_) when (equal f.svar.vname func) -> true
| _ -> false
) cil_file.globals in
let body g = match g with GFun(f,_) -> f.sbody in
dumpBlock defaultCilPrinter stdout 1 (body cil_func)
So I have a type GFun of fundec * location, and I'm trying to get the sbody attribute of fundec.
It seems redundant to do a second pattern match, not to mention, the compiler complains that it's not exhaustive. Is there a better way of doing this?
You can define your own function that returns just the fundec:
let rec find_fundec fname = function
| [] -> raise Not_found
| GFun (f, _) :: _ when equal (f.svar.vname fname) -> f (* ? *)
| _ :: t -> find_fundec fname t
Then your code looks more like this:
let cil_fundec = find_fundec func cil_file.globals in
dumpBlock defaultCilPrinter stdout 1 cil_fundec.sbody
For what it's worth, the line marked (* ? *) looks wrong to me. I don't see why f.svar.vname would be a function. I'm just copying your code there.
Update
Fixed an error (one I often make), sorry.
I have a function save that take standard input, which is used individually like this:
./try < input.txt (* save function is in try file *)
input.txt
2
3
10 29 23
22 14 9
and now i put the function into another file called path.ml which is a part of my interpreter. Now I have a problem in defining the type of Save function and this is because save function has type in_channel, but when i write
type term = Save of in_channel
ocamlc complain about the parameter in the command function.
How can i fix this error? This is the reason why in my last question posted on stackoverflow, I asked for the way to express a variable that accept any type. I understand the answers but actually it doesn't help much in make the code running.
This is my code:
(* Data types *)
open Printf
type term = Print_line_in_file of int*string
| Print of string
| Save of in_channel (* error here *)
;;
let input_line_opt ic =
try Some (input_line ic)
with End_of_file -> None
let nth_line n filename =
let ic = open_in filename in
let rec aux i =
match input_line_opt ic with
| Some line ->
if i = n then begin
close_in ic;
(line)
end else aux (succ i)
| None ->
close_in ic;
failwith "end of file reached"
in
aux 1
(* get all lines *)
let k = ref 1
let first = ref ""
let second = ref ""
let sequence = ref []
let append_item lst a = lst # [a]
let save () =
try
while true do
let line = input_line stdin in
if k = ref 1
then
begin
first := line;
incr k;
end else
if k = ref 2
then
begin
second := line;
incr k;
end else
begin
sequence := append_item !sequence line;
incr k;
end
done;
None
with
End_of_file -> None;;
let rec command term = match term with
| Print (n) -> print_endline n
| Print_line_in_file (n, f) -> print_endline (nth_line n f)
| Save () -> save ()
;;
EDIT
Error in code:
Save of in_channel:
Error: This pattern matches values of type unit
but a pattern was expected which matches values of type in_channel
Save of unit:
Error: This expression has type 'a option
but an expression was expected of type unit
There are many errors in this code, so it's hard to know where to start.
One problem is this: your save function has type unit -> 'a option. So it's not the same type as the other branches of your final match. The fix is straightforward: save should return (), not None. In OCaml these are completely different things.
The immediate problem seems to be that you have Save () in your match, but have declared Save as taking an input channel. Your current code doesn't have any way to pass the input channel to the save function, but if it did, you would want something more like this in your match:
| Save ch -> save ch
Errors like this suggest (to me) that you're not so familiar with OCaml's type system. It would probably save you a lot of trouble if you went through a tutorial of some kind before writing much more code. You can find tutorials at http://ocaml.org.