Ocaml Conversion String to int to char - ocaml

I need to implement this function somewhere
String.get: string -> int -> char
I have tried this one but it does not seem to work
let String.get = fun x -> char_of_int(int_of_string x) ;;
The error I get is:
let String.get = fun x -> char_of_int(int_of_string x) ;;
^^^
Error: Syntax error

String.get is a syntax to denote the function get in module String. The syntax can not be used to (re)define a function as you wrote.
The function is documented here:
val get : string -> int -> char
String.get s n returns the character at index n in string s. You can also write s.[n] instead of String.get s n.
Raise Invalid_argument if n not a valid index in s.
What you are trying to implement is different, you are trying to read, from the string, an integer, and then convert it to a digit char (?)
Depending on what your actual requirements are, you might be asked to reimplement String.get on your own, so for example you would pick a different name in your current module (for now, this is sufficient, you don't need to bother about modules):
let char_at s n = ...
Or maybe you do actually need to convert from an integer. Please clarify your question.

Related

Alert deprecated: Stdlib.String.set

The following code returns an error and says that the syntax is deprecated. What is the correct way to change a character in a string?
let hello = "Hello!" ;;
hello.[1] <- 'a' ;;
Alert deprecated: Stdlib.String.set
Use Bytes.set instead.
Error: This expression has type string but an expression was expected of type
bytes
Strings are immutable (or at least soon they will be), so you can't change their contents. You can, of course, create a copy of a string with the one character different, e.g.,
let with_nth_char m c =
String.mapi (fun i b -> if i = m then c else b)
and
# with_nth_char 1 'E' "hello";;
- : string = "hEllo"
But if you need to change characters in an array then you shouldn't use the string data type but instead rely on bytes which is a type for mutable strings. You can use Bytes.of_strings and Bytes.to_string to translate strings to bytes and vice verse.

Printing user defined types in Ocaml

I am defining a new type which is basically a string. How to print the value ?
# type mytp = Mytp of string;;
type mytp = Mytp of string
# let x = Mytp "Hello Ocaml";;
val x : mytp = Mytp "Hello Ocaml"
# print_endline x;;
Error: This expression has type mytp but an expression was expected of type
string
#
This question already has answer here.
There is another question similar to this, which I had went through before asking the question, however I was not clear (maybe because I am a complete newbie. Other newbies might face similar confusion.) how to solve the problem from the accepted answer.
The type of print_endline is string -> unit. So you can't pass a value of type mytp.
You can write a function to print a value of type mytp:
let print_mytp (Mytp s) = print_endline s
You can write a function to convert mytp to string:
let string_of_mytp (Mytp s) = s
Then you can print like so:
print_endline (string_of_mytp x)
OCaml will not allow you to use mytp where string is expected, or vice versa. This is a feature, not a bug.

OCaml function name as string

I sometimes write functions that make the assumption that some arguments cannot occur. If they do, this is a bug and I fail:
let foo = function
| 0 -> ()
| _ -> failwith "foo: bad argument"
If I rename the function later on, I have to remember to also change the string. Is there a way to do this in a more systematic manner? My mind wanders around solutions like
| _ -> failwith (FUNCTION_NAME ^ ": bad argument")
where FUNCTION_NAME is a string variable that the compiler or interpreter will instantiate. But I have no idea whether something like this even works in OCaml. If not, is there a best practice?
There is a set of values available for debugging and error reporting.
OCaml 4.12 introduced __FUNCTION__:
val __FUNCTION__ : string
__FUNCTION__ returns the name of the current function or method, including any enclosing modules or classes.
They might be useful if you don't want to use assert false as suggested by #SteveVinoski.
__LOC__ : string
__FILE__ : string
__LINE__ : int
__MODULE__ : string
__POS__ : string * int * int * int
There are also fancier forms that you can use to wrap an expression to determine its extent in the source.
These are documented in the Stdlib module.
I think you should try as much as possible to use more specific types so that the compiler can prevent you from calling your functions with invalid input.
If you really don't find a way to tell the type system what you want, try harder, and if you really can't, then use assert which as Steve told you will give you some precious debugging information (file and line number are much more useful than function name since chances are high your function doesn't have a name).
Since 4.12.0, __FUNCTION__ will return the function name.
There are also a number of other debugging variables defined in Stdlib:
val __LOC__ : string
val __FILE__ : string
val __LINE__ : int
val __MODULE__ : string
val __POS__ : string * int * int * int
val __FUNCTION__ : string
val __LOC_OF__ : 'a -> string * 'a
val __LINE_OF__ : 'a -> int * 'a
val __POS_OF__ : 'a -> (string * int * int * int) * 'a

Why can't the compiler match this function type?

I have an issue with the OCaml compiler I can't explain myself. The following code won't compile:
open Postgresql
let get_nodes conn =
ignore (conn#exec "SELECT * FROM node_full")
let () =
let c = new connection () in
ignore (get_nodes c)
It gives the following error:
File "test.ml", line 8, characters 20-21:
Error: This expression has type Postgresql.connection
but an expression was expected of type < exec : string -> 'a; .. >
Types for method exec are incompatible
(Line 8 is the last line)
But the following piece of code compiles without error (and works as expected, in the full version of the code):
open Postgresql
let get_nodes (conn:connection) =
ignore (conn#exec "SELECT * FROM node_full")
let () =
let c = new connection () in
ignore (get_nodes c)
The only difference is that I specified the type of the conn parameter in the get_nodes function.
Does someone understand what is going on here ? This is the first time I have to specify a type myself in order to make the code work, and I am a daily OCaml user ...
Additionnaly, I don't see, in the error message, why the types involved are not compatible, here is the type of the exec function:
method exec :
?expect:Postgresql.result_status list ->
?params:string array ->
?binary_params:bool array ->
string -> Postgresql.result
and the type of the get_all function from Postgresql.result:
method get_all : string array array
Happy new year !
Well, nlucaroni has pointed out that this has been answered in a simpler form at Optional argument in a method with ocaml, but here's a short description of what I got by reading that page.
Your call to exec gives it the inferred type string -> 'a. This isn't at all like the type of the exec method of a Postgresql connection, which has three optional parameters. One way to fix it is to do what you did: declare the type of the conn parameter. You could also just declare the optional parameters of the exec method, maybe something like this:
ignore (
(conn#exec :
?expect: 'a ->
?params: 'b ->
?binary_params: 'c ->
string -> 'd) "SELECT * FROM node_full"
)

Idea working in types

Please see details in My previous question
1) cpf0.ml:
type string = char list
type name = string
type symbol =
| Symbol_name of name
2) problem.ml:
type symbol =
| Ident of Cpf0.string
In this problem.ml it has two definitions for type string, and surely it's giving me an error, but is it posible that I can make them have a same type? I need an idea.
module Str = struct type t = string end;;
module StrOrd = Ord.Make (Str);;
module StrSet = Set.Make (StrOrd);;
module StrMap = Map.Make (StrOrd);;
module SymbSet = Set.Make (SymbOrd);;
let rec ident_of_symbol = function
| Ident s -> s
let idents_of_symbols s =
SymbSet.fold (fun f s -> StrSet.add (ident_of_symbol f) s) s StrSet.empty;;
This expression has type Cpf0.string = char list but an expression was expected of type Util.StrSet.elt = string
You can use the name "string" for different types in different modules if you like, though (as Basile Starynkevitch points out) it's confusing. It would be better to pick a different name. If you really need to reuse the name, you can specify the module every time. If you don't specify a module, you'll get the predefined meaning (or the meaning from the innermost opened module).
It seems to me the problem in your quoted code is that this line:
module Str = struct type t = string end;;
doesn't specify a module name for string, so it refers to the predefined string. It seems possible you wanted to say:
module Str = struct type t = Cpf0.string end;;
It's hard to tell, however. There's not enough context for me to really understand what you're trying to do.
string is a predefined type in Ocaml (ie in the Pervasives module); it is e.g. the type of string literal constants like "this string". Use some other name (otherwise you, and any one reading your code, will be very confused)