I'm trying to get rid of parentheses that surround an integer so that I can pass it to int_of_string
For example, I'd like to pass (-1) to int_of_string and but I don't know how to get rid of the parentheses first so that -1 can be returned.
I'm a beginner at OCaml so any help would be appreciated
Here is a function that returns the substring between the rightmost '(' and the leftmost ')':
let inside_parens s =
let lpar =
try String.rindex s '('
with Not_found -> -1
in
let rpar =
try String.index s ')'
with Not_found -> String.length s
in
String.sub s (lpar + 1) (rpar - lpar - 1)
It works for the example you give:
# int_of_string (inside_parens "(-1)");;
- : int = -1
You might need to adjust the code if you want to handle some cases that you haven't shown.
You can use Scanf.sscanf to parse the string and extract the integer component:
(* inside_parens "(-1)" returns -1 *)
let inside_parens s = Scanf.sscanf s "(%d)" Fun.id
Related
Im trying to run an interpreter I made in ocaml and when i to push in a negative value i.e. let e1 = run [PushI -2; PushI 2; LessThan] []. I am getting a syntax error for my parse_int function. I'm trying to write the part of the function that allows for the input of a negative number
type stackVal =
I of int
type command = PushI of int
let rec run (commands : command list) (stack: stackVal list) : stackVal list =
match (commands , stack) with
| (PushI i :: rest, _ ) -> run rest (I i :: stack)
let to_string (s : stackVal) : string =
match s with
| I i -> string_of_int i
let parse_command (s:string) : command =
match take_while is_alpha (String.trim s) with
| ("PushI" , p) -> let Some i = parse_int (String.trim p) in PushI i
let parse_int (s : string) : int option =
match int_of_string s with
| String.get n 0 = '-' -> Some -String.sub n 1 len
| n -> Some n
| exception _ -> None
There is a problem with the pattern-matching of your parse_int function.
match int_of_string s with
| String.get n 0 = '-' -> Some -String.sub n 1 len
| n -> Some n
| exception _ -> None
The first clause here is invalid as "String.get n 0 = '-'" is not an integer constructor. You could write 1 which matches only the integer 1 or _ whitch matches any integer or n which matches any integer and binds it to the name n for the rest of the clause. You can have a look at the manual for more informations.
If you wanted to check if the first char of the string is - pattern matching is not the right tool to do it, simply use an if then else.
However, note that int_of_string works just fine on negative integers, so there is no need to do that part by yourself.
Unrelated, but i noticed that you call the parse_int in the parse_command function. In that case you should define parse_int before parse_command.
I'm not sure about the best way to approach this, so I figured I'd ask. I have a line like this :
NAME="/dev/sda" TYPE="disk" MODEL="KINGSTON SV300S3"
(gotten from lsblk with a few options) and I'd like to extract each field as simply as possible. Yes, I know lsblk has a very nice --json, but that's unfortunately a recent addition I can't use, we have some pretty old servers still in production.
Maybe using Str with some regex ? Google seems to say menhir a lot, I've never used it, but I'm afraid that might be a bit heavy just for a few variables like that ?
I've tried using String.split_on_char and String.slice, but it starts getting complicated when model contains spaces, String.split_on_char doesn't ignore spaces between double quotes of course.
For simple format like this, the Scanf module might be a viable alternative:
let extract s = Scanf.sscanf s "NAME=%S TYPE=%S MODEL=%S" (fun x y z -> x, y ,z);;
;; extract {|NAME="/dev/sda" TYPE="disk" MODEL="KINGSTON SV300S3"|}
yields
("/dev/sda", "disk", "KINGSTON SV300S3")
as expected.
While Str could probably do the trick, the lesser-known Genlex module from the standard library can come quite handy for not-too-heavy string manipulation, at least for formats that more or less obey OCaml's lexical convention. Basically, it will transform your char stream into a stream of tokens that you can parse much more easily. I imagine that the full output format of lsblk might require some refinements, but for your example, the following is sufficient:
let lexer = Genlex.make_lexer [ "=" ]
let test = "NAME=\"/dev/sda\" TYPE=\"disk\" MODEL=\"KINGSTON SV300S3\""
let test_stream = Stream.of_string test
let test_stream_token = lexer test_stream
let info =
let l = ref [] in
try
while true do
let kw = Stream.next test_stream_token in
let eq = Stream.next test_stream_token in
let v = Stream.next test_stream_token in
let kw =
match kw with Ident s -> s | _ -> failwith "Unrecognized pattern"
in
let () = match eq with Kwd "=" -> () | _ -> failwith "Expected '='" in
let v = match v with String s -> s | _ -> failwith "Expected string" in
l:=(kw,v)::!l
done;
assert false
with Stream.Failure -> List.rev !l
Basically, the main loop considers that the information contained in the input is a sequence of items of the form <key>="<value>", decomposed in three tokens by the Genlex-generated lexer.
It results in: [("NAME", "/dev/sda"); ("TYPE", "disk"); ("MODEL", "KINGSTON SV300S3")]
Got it :
let re = Str.regexp "NAME=\"\\(.*\\)\" TYPE=\"\\(.*\\)\" MODEL=\"\\(.*\\)\"" in
match Str.string_match re line 0 with
| false -> [`Null]
| true ->
let name = Str.matched_group 1 line in
let typ = Str.matched_group 2 line in
let model = Str.matched_group 3 line in
Printf.printf "%s, %s, %s\n" name typ model
I am trying to write a code such that, given a list of parenthesis, I will check if the order is valid or not.
For simpleness, the follwoing datatype is defined.
datatype par = LPAR | RPAR
type pList = par list
What I have until now is:
fun valid(nil:plist): bool = true
| valid([Lpar]) = false
| valid([Rpar]) = false
| valid([Lrap,Rpar) = true
| valid(L::L1) =
For instance, "(()()"--> [Lpar,Lpar,Rpar,Lpar,Rpar] will return false
You can see that the parenthesis is in string format. I am confused since I will have to check to two things: that the left ( are equal to the left ) and that each ( matches a ). If so then I will need to make some helper functions.
Can you please provide me with information about what my helper functions should be or a better implementation of this?
ty
I have found out a way to solve my problem by counting the parenthesis. The logic goes like this:
I start from 0, if i find a left p I add 1, other wise I minus 1. Once I enter -1 i return false right away since I cannot have a right p come first. Then I recurse. If the final output is 0, the its true since this means that every left p matches a right p.
Q.E.D
I didn't try this in the repl but it should look something like this
fun valid_paren xs : bool =
fun aux (xs, ctr) = case xs of
[] => ctr = 0
| (x:xs') => case x of
'(' => aux (xs', ctr+1)
')' => aux (xs', ctr-1)
_ => aux (xs', ctr)
in
aux (xs, 0)
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.
I am absolute OCaml beginner and have an assignment about more code. I have got the following code, but I don't know how it works. If someone can help me out, I appreciate it.
# let explode str = (*defines function that explodes argument str witch is type
string into list of chars*)
let rec exp = function (*defines recursive function exp*)
| a, b when a < 0 -> b (*this part i dont know.is this pattern
matching ?is it function with arguments a and b
and they go into expression? when is a guard and
then we have if a is smaller than 0 then b *)
(*if a is not smaller than 0 then this function ? *)
| a, b -> exp (a-1, str.[a]::b) (*this i dont know, a and b are arguments
that go into recursive function in the way
that a is decreesed by one and b goes into
string a?? *)
in
exp ((String.length str)-1, []);; (*defined function exp on string lenght of
str decresed by one (why?) [ ]these
brackets mean or tell some kind of type ? *)
# let split lst ch =
let rec split = function (* defines recursive fun split *)
| [], ch, cacc', aacc' -> cacc'::aacc'(* if empty ...this is about what i got
so far :) *)
| c::lst, ch, cacc', aacc' when c = ch -> split (lst, ch, [], cacc'::aacc')
| c::lst, ch, cacc', aacc' -> split (lst, ch, c::cacc', aacc')
in
split (lst, ch, [], []);;
val split : 'a list -> 'a -> 'a list list = <fun>
This code is ugly. Whoever has been giving that to you is making you a disservice. If a student of mine wrote that, I would ask them to rewrite them without using when conditionals, because they tend to be confusing, encourage to write pattern-matching-heavy code at places where they are not warranted.
As a rule of the thumb, beginners should never use when. A simple if..then..else test provides an increase in readability.
Here are equivalent versions of those two functions, rewritten for readability:
let explode str =
let rec exp a b =
if a < 0 then b
else exp (a - 1) (str.[a] :: b)
in
exp (String.length str - 1) []
let split input delim_char =
let rec split input curr_word past_words =
match input with
| [] -> curr_word :: past_words
| c :: rest ->
if c = delim_char
then split rest [] (curr_word :: past_words)
else split rest (c :: curr_word) past_words
in
split input [] []
My advice to understand them is to run them yourself, on a given example, on paper. Just write down the function call (eg. explode "foo" and split 'b' ['a';'b';'c';'d']), expand the definition, evaluate the code to get another expression, etc., until you get to the result. Here is an example:
explode "fo"
=>
exp (String.length "fo" - 1) []
=>
exp 1 []
=>
if 1 < 0 then [] else exp 0 ("fo".[1] :: [])
=>
exp 0 ("fo".[1] :: [])
=>
exp 0 ('o' :: [])
=>
exp 0 ['o']
=>
if 0 < 0 then ['o'] else exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ("fo".[0] :: ['o'])
=>
exp (-1) ('f' :: ['o'])
=>
exp (-1) ['f'; 'o']
=>
if -1 < 0 then ['f'; 'o'] else exp (-2) ("fo".[-1] :: ['o'])
=>
['f'; 'o']
Take the care to do that, for each function, and any function you will have problem understanding. On a small example. That's the best way to get a global view of what's going on.
(Later when you grow more used to recursion, you'll find out that you don't actually need to do that, you can reason inductively on the function: make an assumption on what they do, and assuming that recursive calls actually do that, check that it indeed does it. In more advanced cases, trying to hold all the execution in one's head is just too hard, and this induction technique works better, but it is more high-level and requires more practices. First begin by simply running the code.)
If you're using the Core library you can just use
String.to_list "BKMGTPEZY"
Which will return a list of chars if you want strings just map it:
String.to_list "BKMGTPEZY" |> List.map ~f:Char.to_string
Outputs:
- : bytes list = ["B"; "K"; "M"; "G"; "T"; "P"; "E"; "Z"; "Y"]
As a function
let explode s = String.to_list s |> List.map ~f:Char.to_string
You can also implement in this way.
let rec strexp s =
if length(s)==0 then
[]
else
(strexp (sub s 0 (length(s)-1)))#(s.[length(s)-1]::[])
;;