From 870289faa8083b496ad539d531529a64b66bf434 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 10 Sep 2014 20:17:03 +0700 Subject: Add OCaml tutorial. --- ocaml.html.markdown | 309 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 309 insertions(+) create mode 100644 ocaml.html.markdown (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown new file mode 100644 index 00000000..ae862f08 --- /dev/null +++ b/ocaml.html.markdown @@ -0,0 +1,309 @@ +--- +language: "OCaml" +contributors: + - ["Daniil Baturin", "http://baturin.org/"] +--- + +OCaml is a strictly evaluated functional language with some imperative +features. + +Along with StandardML and its dialects it belongs to ML language family. +Just like StandardML, there are both a compiler and an interpreter +for OCaml. The interpreter binary is normally called "ocaml" and +the compiler is "ocamlc.opt". There is also a bytecode compiler, "ocamlc", +but there are few reasons to use it. + +It is strongly and statically typed, but instead of using manually written +type annotations it infers types of expressions using Hindley-Milner algorithm. +It makes type annotations unnecessary in most cases, but can be a major +source of confusion for beginners. + +When you are in the top level loop, OCaml will print the inferred type +after you enter an expression. +``` +# let inc x = x + 1 ;; +val inc : int -> int = +# let a = 99 ;; +val a : int = 99 +``` + +For a source file you can use "ocamlc -i /path/to/file.ml" command +to print all names and signatures. + +``` +$ cat sigtest.ml +let inc x = x + 1 +let add x y = x + y + +let a = 1 + +$ ocamlc -i ./sigtest.ml +val inc : int -> int +val add : int -> int -> int +val a : int +``` +Note that type signatures of functions of multiple arguments are +written in curried form. + +```ocaml +(* Comments are enclosed in (* and *). It's fine to nest comments. *) + +(* There are no single-line comments *) + + +(** Variables and functions *) + +(* Statements can be separated by double + semicolon symbol, ";;". + In many cases it's redundant, but in this tutorial we use it after + every expression for easy pasting into the interpreter shell. *) + +(* Variable and function declarations use "let" keyword. *) +let x = 10 ;; + +(* Since OCaml uses type inference, you normally don't need to + specify argument types explicitly. However, you can do it + if you want or need to. *) +let inc_int (x: int) = x + 1 ;; + +(* You need to mark recursive function definitions as such with "rec" keyword. *) +let rec factorial n = + if n = 0 then 1 + else factorial n * factorial (n-1) +;; + +(* Function application usually doesn't need parantheses around arguments *) +let fact_5 = factorial 5 ;; + +(* ...unless the argument is an expression *) +let fact_4 = factorial (5-1) ;; +let sqr2 = sqr (-2) ;; + +(* You can use multiple statements separated by semicolon in function body, + but the last expression becomes its return value. This is useful when + writing in imperative style. The simplest form of it is inserting a + debug print. *) +let print_and_return x = + print_endline (string_of_int x); + x +;; + +(* Every function must have at least one argument. + Since some funcions naturally don't take any arguments, there's + "unit" type for it that has the only one value written as "()" *) +let print_hello () = print_endline "hello world" ;; + +(* Note that you must specify "()" as argument when calling it. *) +print_hello () ;; + +(* Calling a function with insufficient number of arguments + does not cause an error, it produces a new function. *) +let make_inc x y = x + y ;; (* make_inc is int -> int -> int *) +let inc_2 = make_inc 2 ;; (* inc_2 is int -> int *) +inc_2 3 ;; (* Evaluates to 5 *) + + +(* Since OCaml is a functional language, it lacks "procedures". + Every function must return something. So functions that + do not really return anything and are called solely for their + side effects, like print_endline, return value of "unit" type. *) + + +(* Definitions can be chained with "let ... in" construct. + This is roughly the same to assigning values to multiple + variables before using them in expressions in imperative + languages. *) +let x = 10 in +let y = 20 in +x + y ;; + +(* Alternatively you can use "let ... in and ..." construct. + This is especially useful for mutually recursive functions, + with ordinary "let .. in" the compiler will complain about + unbound values. + It's hard to come up with a meaningful but self-contained + example of mutually recursive functions, but that syntax + works for non-recursive definitions too. *) +let a = 3 and b = 4 in a * b ;; + + +(** Operators **) + +(* There is little distintion between operators and functions. + Every operator can be called as a function. *) + +(+) 3 4 (* Same as 3 + 4 *) + +(* There's a number of built-in operators. One of unusual features is + that OCaml doesn't just refrain from any implicit conversions + between integers and floats, it also uses different operators + for floats. *) +12 + 3 ;; (* Integer addition *) +12.0 +. 3.0 ;; (* Floating point addition *) + +12 / 3 ;; (* Integer division *) +12.0 /. 3.0 ;; (* Floating point division *) +5 mod 2 ;; (* Remainder *) + +(* Unary minus is a notable exception, it's polymorphic. + However, it also has "pure" integer and float forms. *) +- 3 ;; (* Polymorphic, integer *) +- 4.5 ;; (* Polymorphicm float *) +~- 3 (* Integer only *) +~- 3.4 (* Type error *) +~-. 3.4 (* Float only *) + +(* You can define your own operators or redefine existing ones. + Unlike SML or Haskell, only selected symbols can be used + for operator names and first symbol defines associativity + and precedence rules. *) +let (+) a b = a - b ;; (* Surprise maintenance programmers *) + +(* More useful: a reciprocal operator for floats. + Unary operators must start with "~" *) +let (~/) x = 1.0 /. x ;; +~/4.0 (* = 0.25 *) + + +(** Built-in datastructures *) + +(* Lists are enclosed in square brackets, items are separated by + semicolons. *) +let my_list = [1; 2; 3] ;; + +(* Tuples are (optionally) enclosed in parantheses, items are separated + by commas *) +let first_tuple = 3, 4 ;; +let second_tuple = (4, 5) ;; + +(* Corollary: if you try to separate list items by commas, you get a list + with a tuple inside, probably not what you want. *) +let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *) + +(* You can access individual list items with List.nth function *) +List.nth my_list 1 ;; + +(* You can add an item to the beginning of a list with "::" constructor + often referred to as "cons". *) +1 :: [2; 3] ;; (* Gives [1; 2; 3] *) + +(* Arrays are enclosed in [| |] *) +let my_array = [| 1; 2; 3 |] ;; + +(* You can access array items like this: *) +my_array.(0) ;; + + + +(** Data types *) + +(* You can define types with "type some_type =" construct. Like in this + useless type alias: *) +type my_int = int ;; + +(* More interesting types include so called type constructors. + Constructors must start with a capital letter. *) +type ml = OCaml | StandardML ;; +let lang = OCaml ;; (* Has type "ml" *) + +(* Type constructors don't need to be empty. *) +type my_number = PlusInfinity | MinusInfinity | Real of float ;; +let r0 = Real -3.4 ;; (* Has type "my_number" *) + +(* Can be used to implement polymorphic arithmetics. *) +type number = Int of int | Float of float ;; + +(* Point on a plane, essentially a type-constrained tuple *) +type point2d = Point of float * float ;; +let my_point = Point (2.0, 3.0) ;; + +(* Types can be parametrized, like in this type for "list of lists + of anything". 'a can be substituted with any type. *) +type 'a list_of_lists = 'a list list ;; +type int_list_list = int list_of_lists ;; + +(* Types also can be recursive. Like in this type analogous to + built-in list of integers. *) +type my_int_list = EmptyList | IntList of int * my_int_list ;; +let l = Cons (1, EmptyList) ;; + + +(** Pattern matching *) + +(* Pattern matching is somewhat similar to switch statement in imperative + languages, but offers a lot more expressive power. + + Even though it may look complicated, it really boils down to matching + an argument against an exact value, a predicate, or a type constructor. The type system + is what makes it so powerful. *) + +(* Matching exact values. "_" means "anything" *) +let is_zero x = + match x with + | 0 -> true + | _ -> false +;; + +(* Alternatively, you can use "function" keyword *) +let is_one x = function +| 1 -> true +| _ -> false +;; + +(* Matching predicates, aka "guarded pattern matching" *) +let abs x = + match x with + | x when x < 0 -> -x + | _ -> x +;; + +abs 5 ;; (* 5 *) +abs (-5) (* 5 again *) + +(* Matching type constructors *) + +type animal = Dog of string | Cat of string ;; + +let say x = + match x with + | Dog x -> x ^ " says woof" + | Cat x -> x ^ " says meow" +;; + +say (Cat "Fluffy") ;; (* "Fluffy says meow" *) + +(* Traversing data structures *) + +(* Recursive types can be traversed with pattern matching easily. + The cons thing ("::") that is used with built-in lists is actually a + type constructor, except it can be used in infix form, unlike + user-defined constructors. So you can use it like this: *) + +let rec sum_list l = + match l with + | [] -> 0 + | head :: tail -> head + (sum_list tail) +;; + +sum_list [1; 2; 3] ;; + +(* Built-int syntax for cons obscures the structure a bit, so we'll make + our own list for demonstration. *) + +type int_list = Nil | Cons of int * int_list ;; +let rec sum_int_list l = + match l with + | Nil -> 0 + | Cons (head, tail) -> head + (sum_int_list tail) +;; + +let t = Cons (1, Cons (2, Cons (3, Nil))) ;; +sum_int_list t ;; + +``` + +## Further reading + +* Visit the official website to get the compiler and read the docs: http://ocaml.org/ +* Try interactive tutorials and a web-based interpreter by OCaml Pro: http://try.ocamlpro.com/ +* Read "OCaml for the skeptical" course: http://www2.lib.uchicago.edu/keith/ocaml-class/home.html -- cgit v1.2.3 From 9f3bff9ce85ea95073f8a90397195c841d9fce23 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 10 Sep 2014 21:33:41 +0700 Subject: Fix some typos/errors in the OCaml tutorial. --- ocaml.html.markdown | 112 ++++++++++++++++++++++++++-------------------------- 1 file changed, 56 insertions(+), 56 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index ae862f08..3c9593d4 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -14,7 +14,7 @@ the compiler is "ocamlc.opt". There is also a bytecode compiler, "ocamlc", but there are few reasons to use it. It is strongly and statically typed, but instead of using manually written -type annotations it infers types of expressions using Hindley-Milner algorithm. +type annotations, it infers types of expressions using Hindley-Milner algorithm. It makes type annotations unnecessary in most cases, but can be a major source of confusion for beginners. @@ -46,24 +46,24 @@ Note that type signatures of functions of multiple arguments are written in curried form. ```ocaml +(*** Comments ***) + (* Comments are enclosed in (* and *). It's fine to nest comments. *) -(* There are no single-line comments *) +(* There are no single-line comments. *) -(** Variables and functions *) +(*** Variables and functions ***) -(* Statements can be separated by double - semicolon symbol, ";;". +(* Expressions can be separated by a double semicolon symbol, ";;". In many cases it's redundant, but in this tutorial we use it after every expression for easy pasting into the interpreter shell. *) (* Variable and function declarations use "let" keyword. *) let x = 10 ;; -(* Since OCaml uses type inference, you normally don't need to - specify argument types explicitly. However, you can do it - if you want or need to. *) +(* Since OCaml compiler infers types automatically, you normally don't need to + specify argument types explicitly. However, you can do it if you want or need to. *) let inc_int (x: int) = x + 1 ;; (* You need to mark recursive function definitions as such with "rec" keyword. *) @@ -72,22 +72,13 @@ let rec factorial n = else factorial n * factorial (n-1) ;; -(* Function application usually doesn't need parantheses around arguments *) +(* Function application usually doesn't need parentheses around arguments *) let fact_5 = factorial 5 ;; -(* ...unless the argument is an expression *) +(* ...unless the argument is an expression. *) let fact_4 = factorial (5-1) ;; let sqr2 = sqr (-2) ;; -(* You can use multiple statements separated by semicolon in function body, - but the last expression becomes its return value. This is useful when - writing in imperative style. The simplest form of it is inserting a - debug print. *) -let print_and_return x = - print_endline (string_of_int x); - x -;; - (* Every function must have at least one argument. Since some funcions naturally don't take any arguments, there's "unit" type for it that has the only one value written as "()" *) @@ -102,6 +93,15 @@ let make_inc x y = x + y ;; (* make_inc is int -> int -> int *) let inc_2 = make_inc 2 ;; (* inc_2 is int -> int *) inc_2 3 ;; (* Evaluates to 5 *) +(* You can use multiple expressions in function body. + The last expression becomes the return value. All other + expressions must be of the "unit" type. + This is useful when writing in imperative style, the simplest + form of it is inserting a debug print. *) +let print_and_return x = + print_endline (string_of_int x); + x +;; (* Since OCaml is a functional language, it lacks "procedures". Every function must return something. So functions that @@ -117,7 +117,7 @@ let x = 10 in let y = 20 in x + y ;; -(* Alternatively you can use "let ... in and ..." construct. +(* Alternatively you can use "let ... and ... in" construct. This is especially useful for mutually recursive functions, with ordinary "let .. in" the compiler will complain about unbound values. @@ -127,28 +127,28 @@ x + y ;; let a = 3 and b = 4 in a * b ;; -(** Operators **) +(*** Operators ***) (* There is little distintion between operators and functions. Every operator can be called as a function. *) (+) 3 4 (* Same as 3 + 4 *) -(* There's a number of built-in operators. One of unusual features is +(* There's a number of built-in operators. One unusual feature is that OCaml doesn't just refrain from any implicit conversions between integers and floats, it also uses different operators for floats. *) -12 + 3 ;; (* Integer addition *) -12.0 +. 3.0 ;; (* Floating point addition *) +12 + 3 ;; (* Integer addition. *) +12.0 +. 3.0 ;; (* Floating point addition. *) -12 / 3 ;; (* Integer division *) -12.0 /. 3.0 ;; (* Floating point division *) -5 mod 2 ;; (* Remainder *) +12 / 3 ;; (* Integer division. *) +12.0 /. 3.0 ;; (* Floating point division. *) +5 mod 2 ;; (* Remainder. *) (* Unary minus is a notable exception, it's polymorphic. However, it also has "pure" integer and float forms. *) - 3 ;; (* Polymorphic, integer *) -- 4.5 ;; (* Polymorphicm float *) +- 4.5 ;; (* Polymorphic, float *) ~- 3 (* Integer only *) ~- 3.4 (* Type error *) ~-. 3.4 (* Float only *) @@ -156,34 +156,34 @@ let a = 3 and b = 4 in a * b ;; (* You can define your own operators or redefine existing ones. Unlike SML or Haskell, only selected symbols can be used for operator names and first symbol defines associativity - and precedence rules. *) -let (+) a b = a - b ;; (* Surprise maintenance programmers *) + and precedence rules. *) +let (+) a b = a - b ;; (* Surprise maintenance programmers. *) (* More useful: a reciprocal operator for floats. - Unary operators must start with "~" *) + Unary operators must start with "~". *) let (~/) x = 1.0 /. x ;; ~/4.0 (* = 0.25 *) -(** Built-in datastructures *) +(*** Built-in datastructures ***) (* Lists are enclosed in square brackets, items are separated by semicolons. *) let my_list = [1; 2; 3] ;; -(* Tuples are (optionally) enclosed in parantheses, items are separated - by commas *) -let first_tuple = 3, 4 ;; +(* Tuples are (optionally) enclosed in parentheses, items are separated + by commas. *) +let first_tuple = 3, 4 ;; (* Has type "int * int". *) let second_tuple = (4, 5) ;; (* Corollary: if you try to separate list items by commas, you get a list with a tuple inside, probably not what you want. *) let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *) -(* You can access individual list items with List.nth function *) +(* You can access individual list items with the List.nth function. *) List.nth my_list 1 ;; -(* You can add an item to the beginning of a list with "::" constructor +(* You can add an item to the beginning of a list with the "::" constructor often referred to as "cons". *) 1 :: [2; 3] ;; (* Gives [1; 2; 3] *) @@ -195,20 +195,20 @@ my_array.(0) ;; -(** Data types *) +(*** User-defined data types ***) -(* You can define types with "type some_type =" construct. Like in this +(* You can define types with the "type some_type =" construct. Like in this useless type alias: *) type my_int = int ;; (* More interesting types include so called type constructors. Constructors must start with a capital letter. *) type ml = OCaml | StandardML ;; -let lang = OCaml ;; (* Has type "ml" *) +let lang = OCaml ;; (* Has type "ml". *) (* Type constructors don't need to be empty. *) type my_number = PlusInfinity | MinusInfinity | Real of float ;; -let r0 = Real -3.4 ;; (* Has type "my_number" *) +let r0 = Real (-3.4) ;; (* Has type "my_number". *) (* Can be used to implement polymorphic arithmetics. *) type number = Int of int | Float of float ;; @@ -222,13 +222,13 @@ let my_point = Point (2.0, 3.0) ;; type 'a list_of_lists = 'a list list ;; type int_list_list = int list_of_lists ;; -(* Types also can be recursive. Like in this type analogous to +(* Types can also be recursive. Like in this type analogous to built-in list of integers. *) type my_int_list = EmptyList | IntList of int * my_int_list ;; let l = Cons (1, EmptyList) ;; -(** Pattern matching *) +(*** Pattern matching ***) (* Pattern matching is somewhat similar to switch statement in imperative languages, but offers a lot more expressive power. @@ -237,20 +237,21 @@ let l = Cons (1, EmptyList) ;; an argument against an exact value, a predicate, or a type constructor. The type system is what makes it so powerful. *) -(* Matching exact values. "_" means "anything" *) +(** Matching exact values. **) + let is_zero x = match x with | 0 -> true - | _ -> false + | _ -> false (* The "_" pattern means "anything else". *) ;; -(* Alternatively, you can use "function" keyword *) +(* Alternatively, you can use the "function" keyword. *) let is_one x = function | 1 -> true | _ -> false ;; -(* Matching predicates, aka "guarded pattern matching" *) +(* Matching predicates, aka "guarded pattern matching". *) let abs x = match x with | x when x < 0 -> -x @@ -260,7 +261,7 @@ let abs x = abs 5 ;; (* 5 *) abs (-5) (* 5 again *) -(* Matching type constructors *) +(** Matching type constructors **) type animal = Dog of string | Cat of string ;; @@ -270,24 +271,23 @@ let say x = | Cat x -> x ^ " says meow" ;; -say (Cat "Fluffy") ;; (* "Fluffy says meow" *) +say (Cat "Fluffy") ;; (* "Fluffy says meow". *) -(* Traversing data structures *) +(** Traversing datastructures with pattern matching **) (* Recursive types can be traversed with pattern matching easily. - The cons thing ("::") that is used with built-in lists is actually a - type constructor, except it can be used in infix form, unlike - user-defined constructors. So you can use it like this: *) - + Let's see how we can traverse a datastructure of the built-in list type. + Even though the built-in cons ("::") looks like an infix operator, it's actually + a type constructor and can be matched like any other. *) let rec sum_list l = match l with | [] -> 0 | head :: tail -> head + (sum_list tail) ;; -sum_list [1; 2; 3] ;; +sum_list [1; 2; 3] ;; (* Evaluates to 6 *) -(* Built-int syntax for cons obscures the structure a bit, so we'll make +(* Built-in syntax for cons obscures the structure a bit, so we'll make our own list for demonstration. *) type int_list = Nil | Cons of int * int_list ;; -- cgit v1.2.3 From b2cf2228b3843a2015b3badbb550faf47fcb0404 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Wed, 10 Sep 2014 21:40:47 +0700 Subject: One more fix in the OCaml tutorial. --- ocaml.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 3c9593d4..fd7ca36e 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -217,7 +217,7 @@ type number = Int of int | Float of float ;; type point2d = Point of float * float ;; let my_point = Point (2.0, 3.0) ;; -(* Types can be parametrized, like in this type for "list of lists +(* Types can be parameterized, like in this type for "list of lists of anything". 'a can be substituted with any type. *) type 'a list_of_lists = 'a list list ;; type int_list_list = int list_of_lists ;; -- cgit v1.2.3 From 146e6a4ac13f0ff6353879e7b42dfaa2a6725011 Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Wed, 10 Sep 2014 17:35:30 +0200 Subject: Update ocaml.html.markdown --- ocaml.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index fd7ca36e..3dbf5a10 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -1,5 +1,5 @@ --- -language: "OCaml" +language: OCaml contributors: - ["Daniil Baturin", "http://baturin.org/"] --- @@ -20,6 +20,7 @@ source of confusion for beginners. When you are in the top level loop, OCaml will print the inferred type after you enter an expression. + ``` # let inc x = x + 1 ;; val inc : int -> int = @@ -42,6 +43,7 @@ val inc : int -> int val add : int -> int -> int val a : int ``` + Note that type signatures of functions of multiple arguments are written in curried form. -- cgit v1.2.3 From 1d5533f45b4b123920e633064b23332039335f7e Mon Sep 17 00:00:00 2001 From: Adam Bard Date: Wed, 10 Sep 2014 17:37:17 +0200 Subject: Fix up links. --- ocaml.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 3dbf5a10..c104823a 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -306,6 +306,6 @@ sum_int_list t ;; ## Further reading -* Visit the official website to get the compiler and read the docs: http://ocaml.org/ -* Try interactive tutorials and a web-based interpreter by OCaml Pro: http://try.ocamlpro.com/ -* Read "OCaml for the skeptical" course: http://www2.lib.uchicago.edu/keith/ocaml-class/home.html +* Visit the official website to get the compiler and read the docs: +* Try interactive tutorials and a web-based interpreter by OCaml Pro: +* Read "OCaml for the skeptical" course: -- cgit v1.2.3 From 6eea532330ac11ce261dd9b3e765099b1288fb17 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Thu, 11 Sep 2014 20:59:21 +0700 Subject: The native compiler is ocamlopt, not ocamlc.opt. Artifacts of late-night writing. --- ocaml.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index c104823a..747a52f5 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -10,7 +10,7 @@ features. Along with StandardML and its dialects it belongs to ML language family. Just like StandardML, there are both a compiler and an interpreter for OCaml. The interpreter binary is normally called "ocaml" and -the compiler is "ocamlc.opt". There is also a bytecode compiler, "ocamlc", +the compiler is "ocamlopt". There is also a bytecode compiler, "ocamlc", but there are few reasons to use it. It is strongly and statically typed, but instead of using manually written -- cgit v1.2.3 From 791c123ba55d726df3da03115a56657b02a02e6f Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Thu, 11 Sep 2014 21:22:02 +0700 Subject: Add a section about strings and characters to the OCaml tutorial. --- ocaml.html.markdown | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 747a52f5..5c236b1a 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -196,6 +196,39 @@ let my_array = [| 1; 2; 3 |] ;; my_array.(0) ;; +(*** Strings and characters ***) + +(* Use double quotes for string literals. *) +let my_str = "Hello world" ;; + +(* Use single quotes for character literals. *) +let my_char = 'a' ;; + +(* Single and double quotes are not interchangeable. *) +let bad_str = 'syntax error' ;; (* Syntax error. *) + +(* This will give you a single character string, not a character. *) +let single_char_str = "w" ;; + +(* Strings can be concatenated with the "^" operator. *) +let some_str = "hello" ^ "world" ;; + +(* Strings are not arrays of characters. + You can't mix characters and strings in expressions. + You can convert a character to a string with "String.make 1 my_char". + There are more convenient functions for this purpose in additional + libraries such as Core.Std that may not be installed and/or loaded + by default. *) +let ocaml = (String.make 1 'O') ^ "Caml" ;; + +(* There is a printf function. *) +Printf.printf "%d %s" 99 "bottles of beer" ;; + +(* Unformatted read and write functions are there too. *) +print_string "hello world\n" ;; +print_endline "hello world" ;; +let line = read_line () ;; + (*** User-defined data types ***) -- cgit v1.2.3 From 15fd51c9984fcadcfa83658ae0f01e4b3402c07f Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Thu, 11 Sep 2014 21:40:15 +0700 Subject: Minor style notes in the OCaml tutorial. --- ocaml.html.markdown | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 5c236b1a..7f4e0a9d 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -59,11 +59,19 @@ written in curried form. (* Expressions can be separated by a double semicolon symbol, ";;". In many cases it's redundant, but in this tutorial we use it after - every expression for easy pasting into the interpreter shell. *) + every expression for easy pasting into the interpreter shell. + Unnecessary use of expression separators in source code files + is often considered to be a bad style. *) (* Variable and function declarations use "let" keyword. *) let x = 10 ;; +(* OCaml allows single quote characters in identifiers. + Single quote doesn't have a special meaning in this case, it's often used + in cases when in other languages one would use names like "foo_tmp". *) +let foo = 1 ;; +let foo' = foo * 2 ;; + (* Since OCaml compiler infers types automatically, you normally don't need to specify argument types explicitly. However, you can do it if you want or need to. *) let inc_int (x: int) = x + 1 ;; -- cgit v1.2.3 From 55c269cc3c6a5678bbff3effc587edb7a1cd6e8a Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Fri, 12 Sep 2014 18:39:15 +0700 Subject: F# is also related to the ML family. --- ocaml.html.markdown | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 7f4e0a9d..8638a291 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -8,8 +8,10 @@ OCaml is a strictly evaluated functional language with some imperative features. Along with StandardML and its dialects it belongs to ML language family. -Just like StandardML, there are both a compiler and an interpreter -for OCaml. The interpreter binary is normally called "ocaml" and +F# is also heavily influenced by OCaml. + +Just like StandardML, OCaml features both an interpreter that can be +used interactively and a compiler. The interpreter binary is normally called "ocaml" and the compiler is "ocamlopt". There is also a bytecode compiler, "ocamlc", but there are few reasons to use it. -- cgit v1.2.3 From d9110cf7bc8a3dcf84207ea509340dbae868a44a Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Fri, 12 Sep 2014 19:34:50 +0700 Subject: An overly simplified explanation of currying in OCaml tutorial. --- ocaml.html.markdown | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 8638a291..fd5b9b2e 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -31,7 +31,7 @@ val a : int = 99 ``` For a source file you can use "ocamlc -i /path/to/file.ml" command -to print all names and signatures. +to print all names and type signatures. ``` $ cat sigtest.ml @@ -47,7 +47,13 @@ val a : int ``` Note that type signatures of functions of multiple arguments are -written in curried form. +written in curried form. A function that takes multiple arguments can be +represented as a composition of functions that take only one argument. +The "f(x,y) = x + y" function from the example above applied to +arguments 2 and 3 is equivalent to the "f0(y) = 2 + y" function applied to 3. +Hence the "int -> int -> int" signature, which can be read as +"(int -> int) -> int". + ```ocaml (*** Comments ***) -- cgit v1.2.3 From 962d58d013fa245c6b61863d2d14420c4c563743 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Fri, 12 Sep 2014 19:35:56 +0700 Subject: Remove stray argument from the alternative matching syntax in OCaml tutorial. It wouldn't cause a syntax error, but wouldn't give intended result either. --- ocaml.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index fd5b9b2e..1732f7be 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -297,7 +297,7 @@ let is_zero x = ;; (* Alternatively, you can use the "function" keyword. *) -let is_one x = function +let is_one = function | 1 -> true | _ -> false ;; -- cgit v1.2.3 From 3995be4f4bf518e2c3436632ec100c14bb47bda1 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Fri, 12 Sep 2014 19:42:50 +0700 Subject: Break some long lines in OCaml tutorial to avoid horizontal scrolling. --- ocaml.html.markdown | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 1732f7be..41bc4ff2 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -81,7 +81,8 @@ let foo = 1 ;; let foo' = foo * 2 ;; (* Since OCaml compiler infers types automatically, you normally don't need to - specify argument types explicitly. However, you can do it if you want or need to. *) + specify argument types explicitly. However, you can do it if + you want or need to. *) let inc_int (x: int) = x + 1 ;; (* You need to mark recursive function definitions as such with "rec" keyword. *) @@ -285,8 +286,8 @@ let l = Cons (1, EmptyList) ;; languages, but offers a lot more expressive power. Even though it may look complicated, it really boils down to matching - an argument against an exact value, a predicate, or a type constructor. The type system - is what makes it so powerful. *) + an argument against an exact value, a predicate, or a type constructor. + The type system is what makes it so powerful. *) (** Matching exact values. **) @@ -328,8 +329,8 @@ say (Cat "Fluffy") ;; (* "Fluffy says meow". *) (* Recursive types can be traversed with pattern matching easily. Let's see how we can traverse a datastructure of the built-in list type. - Even though the built-in cons ("::") looks like an infix operator, it's actually - a type constructor and can be matched like any other. *) + Even though the built-in cons ("::") looks like an infix operator, + it's actually a type constructor and can be matched like any other. *) let rec sum_list l = match l with | [] -> 0 -- cgit v1.2.3 From 2d01fb3c0597cfc692e3edfebcfc81bf2e3e3ee9 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Fri, 12 Sep 2014 19:46:41 +0700 Subject: Minor formatting and punctuation fix in the OCaml tutorial. --- ocaml.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 41bc4ff2..0107fd35 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -10,10 +10,10 @@ features. Along with StandardML and its dialects it belongs to ML language family. F# is also heavily influenced by OCaml. -Just like StandardML, OCaml features both an interpreter that can be -used interactively and a compiler. The interpreter binary is normally called "ocaml" and -the compiler is "ocamlopt". There is also a bytecode compiler, "ocamlc", -but there are few reasons to use it. +Just like StandardML, OCaml features both an interpreter, that can be +used interactively, and a compiler. +The interpreter binary is normally called "ocaml" and the compiler is "ocamlopt". +There is also a bytecode compiler, "ocamlc", but there are few reasons to use it. It is strongly and statically typed, but instead of using manually written type annotations, it infers types of expressions using Hindley-Milner algorithm. -- cgit v1.2.3 From 166fb997a0793067b7aa09091a1c9f76229ea6de Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Sat, 13 Sep 2014 00:36:15 +0700 Subject: Remove the signature explanation by grouping to avoid confusion with signature syntax for function types. --- ocaml.html.markdown | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 0107fd35..5be9510b 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -51,8 +51,7 @@ written in curried form. A function that takes multiple arguments can be represented as a composition of functions that take only one argument. The "f(x,y) = x + y" function from the example above applied to arguments 2 and 3 is equivalent to the "f0(y) = 2 + y" function applied to 3. -Hence the "int -> int -> int" signature, which can be read as -"(int -> int) -> int". +Hence the "int -> int -> int" signature. ```ocaml -- cgit v1.2.3 From 807a958c78c44a83172724766d446eadb24f8cc5 Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Sat, 13 Sep 2014 00:46:46 +0700 Subject: Some information about the need for type annotations in OCaml tutorial. --- ocaml.html.markdown | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index 5be9510b..bb9a1a75 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -82,7 +82,13 @@ let foo' = foo * 2 ;; (* Since OCaml compiler infers types automatically, you normally don't need to specify argument types explicitly. However, you can do it if you want or need to. *) -let inc_int (x: int) = x + 1 ;; +let inc_int (x: int) : int = x + 1 ;; + +(* One of the cases when explicit type annotations may be needed is + resolving ambiguity between two record types that have fields with + the same name. The alternative is to encapsulate those types in + modules, but both topics are a bit out of scope of this + tutorial. *) (* You need to mark recursive function definitions as such with "rec" keyword. *) let rec factorial n = -- cgit v1.2.3 From 5cf408a7a9f0d72f40dadd95d81430f35dee3a1e Mon Sep 17 00:00:00 2001 From: Daniil Baturin Date: Sat, 13 Sep 2014 00:54:23 +0700 Subject: Add anonymous functions and list map/filter sections to the OCaml tutorial. --- ocaml.html.markdown | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index bb9a1a75..b9505f13 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -150,6 +150,8 @@ x + y ;; works for non-recursive definitions too. *) let a = 3 and b = 4 in a * b ;; +(* Anonymous functions use the following syntax: *) +let my_lambda = fun x -> x * x ;; (*** Operators ***) @@ -207,6 +209,10 @@ let bad_list = [1, 2] ;; (* Becomes [(1, 2)] *) (* You can access individual list items with the List.nth function. *) List.nth my_list 1 ;; +(* There are higher-order functions for lists such as map and filter. *) +List.map (fun x -> x * 2) [1; 2; 3] ;; +List.filter (fun x -> if x mod 2 = 0 then true else false) [1; 2; 3; 4] ;; + (* You can add an item to the beginning of a list with the "::" constructor often referred to as "cons". *) 1 :: [2; 3] ;; (* Gives [1; 2; 3] *) -- cgit v1.2.3 From b2cb538a5a758ce03a219545a77b274cd8609cc4 Mon Sep 17 00:00:00 2001 From: Oscar Date: Sat, 18 Oct 2014 11:44:44 +0800 Subject: Recursive function a little bit to recursive Infinitely recursive --- ocaml.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index b9505f13..f9db7080 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -93,7 +93,7 @@ let inc_int (x: int) : int = x + 1 ;; (* You need to mark recursive function definitions as such with "rec" keyword. *) let rec factorial n = if n = 0 then 1 - else factorial n * factorial (n-1) + else n * factorial (n-1) ;; (* Function application usually doesn't need parentheses around arguments *) -- cgit v1.2.3 From 8c70acc9fb102e5884fb9e05c79e07015c3e4188 Mon Sep 17 00:00:00 2001 From: Chenggang Duan Date: Thu, 12 Feb 2015 16:54:26 +0800 Subject: [ocaml/en] Change the example of mutually recursive functions Change the example to a meaningful and self-contained example of mutually recursive functions. --- ocaml.html.markdown | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index f9db7080..b30d920b 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -144,11 +144,16 @@ x + y ;; (* Alternatively you can use "let ... and ... in" construct. This is especially useful for mutually recursive functions, with ordinary "let .. in" the compiler will complain about - unbound values. - It's hard to come up with a meaningful but self-contained - example of mutually recursive functions, but that syntax - works for non-recursive definitions too. *) -let a = 3 and b = 4 in a * b ;; + unbound values. *) +let rec + is_even = function + | 0 -> true + | n -> is_odd (n-1) +and + is_odd = function + | 0 -> false + | n -> is_even (n-1) +;; (* Anonymous functions use the following syntax: *) let my_lambda = fun x -> x * x ;; -- cgit v1.2.3 From ea5c3c1f3efd4da9d47a7e108e0c1b92ee6dfeb6 Mon Sep 17 00:00:00 2001 From: Chenggang Duan Date: Thu, 12 Feb 2015 17:02:16 +0800 Subject: [ocaml/en] Fix typo --- ocaml.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index b30d920b..b0027fea 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -293,7 +293,7 @@ type int_list_list = int list_of_lists ;; (* Types can also be recursive. Like in this type analogous to built-in list of integers. *) type my_int_list = EmptyList | IntList of int * my_int_list ;; -let l = Cons (1, EmptyList) ;; +let l = IntList (1, EmptyList) ;; (*** Pattern matching ***) -- cgit v1.2.3 From 960ee4a1856db8eadb96277bb2422edfa8f2a81c Mon Sep 17 00:00:00 2001 From: Gabriel Halley Date: Wed, 7 Oct 2015 23:11:24 -0400 Subject: removing whitespace all over --- ocaml.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'ocaml.html.markdown') diff --git a/ocaml.html.markdown b/ocaml.html.markdown index b0027fea..02435e4d 100644 --- a/ocaml.html.markdown +++ b/ocaml.html.markdown @@ -34,13 +34,13 @@ For a source file you can use "ocamlc -i /path/to/file.ml" command to print all names and type signatures. ``` -$ cat sigtest.ml +$ cat sigtest.ml let inc x = x + 1 let add x y = x + y -let a = 1 +let a = 1 -$ ocamlc -i ./sigtest.ml +$ ocamlc -i ./sigtest.ml val inc : int -> int val add : int -> int -> int val a : int @@ -104,7 +104,7 @@ let fact_4 = factorial (5-1) ;; let sqr2 = sqr (-2) ;; (* Every function must have at least one argument. - Since some funcions naturally don't take any arguments, there's + Since some funcions naturally don't take any arguments, there's "unit" type for it that has the only one value written as "()" *) let print_hello () = print_endline "hello world" ;; @@ -301,7 +301,7 @@ let l = IntList (1, EmptyList) ;; (* Pattern matching is somewhat similar to switch statement in imperative languages, but offers a lot more expressive power. - Even though it may look complicated, it really boils down to matching + Even though it may look complicated, it really boils down to matching an argument against an exact value, a predicate, or a type constructor. The type system is what makes it so powerful. *) @@ -320,7 +320,7 @@ let is_one = function ;; (* Matching predicates, aka "guarded pattern matching". *) -let abs x = +let abs x = match x with | x when x < 0 -> -x | _ -> x -- cgit v1.2.3