816 search results for ""
-
Sequences
Be Aware of Seq.Cons vs Seq.cons
Let's look at how confusing Seq.Cons and Seq.cons can lead to unintended behavior. Now that we have seen these two versions of "cons-ing" can construct the same sequence, it begs the questio
Data Structures -
Sequences
Fibs with Seq.cons
This produces a never-ending recursion that leads to a stack overflow. <!-- Or with an int version: ```ocaml # let rec ints_v1 n = Seq.cons n (n + 1);; val fibs : int -> int -> int Seq.t = <fun> #
Data Structures -
Sequences
Fibs with Seq.Cons
<!-- Or with an int version ``` ocaml # ints_v2 1 |> Seq.take 10 |> List.of_seq;; - : int list = [1; 2; 3; 4; 5; 6; 7; 8; 9; 10] ``` --> This implementation successfully defines a producer of laz
Data Structures -
Sequences
Understanding the Difference
If the distinction remains a mystery, take a moment to compare the inputs to the Seq.Cons constructor and Seq.cons function. They look deceptively similar, but one takes as input a value of ty
Data Structures -
Sequences
A Mental Model for Seq.Cons vs Seq.cons
It is useful to think of Seq.Cons and Seq.cons as accomplishing different tasks. Seq.Cons provides a convenient means of recursively defining a sequence generator and a clumsy means to prep
Data Structures -
Sequences
Sequences for Conversions
Similar functions are also provided for sets, maps, hash tables ( Hashtbl ), and others. When implementing a datatype module, it is advised to expose to_seq and of_seq functions. Lists Ar
Data Structures -
Sequences
Miscellaneous Considerations
<!-- Suggestion: perhaps it would be enlightening to illustrate the use of Seq.unfold by re-implementing the already seen function primes? Perhaps in an exercise rather than in the main text of the t
Data Structures -
Memoization
Memoization
Fibonacci
Although this code uses imperative constructs (specifically, array update), the side effects are not visible outside the function fibm . So from a client's perspective, fibm is functional. The
Data StructuresMemoization
Memoization Using Higher-order Functions
Now we can slightly rewrite the original fib function above using this general memoization technique: For recursive functions, however, the recursive call structure needs to be modified. T
Data StructuresMemoization
Just for Fun: Party Optimization
<!-- ***** MRC 7/22/21: the section below needs a lot more explanation. Also the value `big` was undefined in the original notes, so the code didn't compile. I added a definition of `target + 1` but
Data StructuresMonads
Monads
The Monad Signature
So the next few sections look at several different examples of code in which monads can be discovered. Because monads are a design pattern, they aren't always obvious; it can take some study to t
Data StructuresMonads
The Maybe Monad
Now that we're done playing with integer operators, we should restore their original meaning for the rest of this file: The result is we get code that (once you understand how to read the bind
Data StructuresMonads
Example: The Writer Monad
It's debatable which version of loggable is easier to read. Certainly you need to be comfortable with the monadic style of programming to appreciate the version of it that uses >>= . But if yo
Data StructuresMonads
Example: The Lwt Monad
Metaphorically, as we discussed before, the box involved here is one that starts out empty but eventually will be filled with a value of type 'a . The "something more" in these computations is t
Data StructuresMonads
Monad Laws
But the problem is that doesn't type check: f >>= g doesn't have the right type to be on the right-hand side of >>= . So we have to insert an extra anonymous function fun x -> ... to make th
Data StructuresMonads
Composition and Monad Laws
In that formulation, it becomes immediately clear that return is a left and right identity, and that composition is associative. Law 1: return >=> f behaves the same as f . Law 2: f >=> r
Data StructuresPreprocessors and PPXs
Preprocessors and PPXs
Preprocessing in OCaml
This guide presents the state of the two kinds of preprocessors in OCaml, but with an emphasis on PPXs. Although the latter is the recommended way of writing preprocessors, we start with source p
Advanced TopicsPreprocessors and PPXs
Source Preprocessors
In OCaml, preprocessing text files do not have specific support from the language. Instead it is the build system's role to drive the preprocessing. So, applying preprocessors will boil down to t
Advanced TopicsPreprocessors and PPXs
Preprocessing With ocamlc and ocamlopt
Compiling a classic "Hello, World!" program with this option would alter the compilation: OCaml's compiler ocamlc and ocamlopt offer the -pp option to preprocess a file in the compilat
Advanced TopicsPreprocessors and PPXs
Preprocessing With Dune
Putting it all together, the following dune file would rewrite the corresponding module files using our previously written preprocessor.sh : The stanza to apply preprocessing on the source fi
Advanced TopicsPreprocessors and PPXs
The Limits of Manipulating Text Files
Working with a much more structured representation of a program solves both the reading and writing issues. This is exactly what PPXs do! It is difficult to read parts of the program, such as the ty
Advanced TopicsPreprocessors and PPXs
PPXs
PPxs are a different kind of preprocessor—one that does not run on the textual source code, but rather on the parsing result: the Abstract Syntax Tree (AST), which in the OCaml compiler is call
Advanced TopicsPreprocessors and PPXs
OCaml’s Parsetree: The OCaml AST
Note that the Parsetree is an internal representation of the code that happens before typing the program, so an ill-typed program can be rewritten. The internal representation after the typing is
Advanced TopicsPreprocessors and PPXs
PPX Rewriters
Secondly, most of the PPX's code transformation do not need to be given the full AST; they can work locally in subparts of it. There are two kinds of such local restrictions to the general PPX re
Advanced TopicsPreprocessors and PPXs
Attributes and Derivers
ppx_show generates a pretty printer from a type for values of this type. Derivers that derive serializers from OCaml types to other formats, such as JSON with ppx_yojson_conv , YAML with ppx
Advanced TopicsPreprocessors and PPXs
Extension Nodes and Extenders
Extenders which allow users to write OCaml values representing another language directly in such language. For example: - ppx_yojson to generate Yojson values by writing JSON code - tyxml-
Advanced TopicsPreprocessors and PPXs
Using PPXs
And that's all you need to use PPXs! Although these instructions will work for most PPXs, note that the first source of information will be the package documentation, as some PPXs might need some
Advanced TopicsPreprocessors and PPXs
Dropping PPXs Dependency With [@@deriving_inline]
Note that, while it allows to drop a project's dependency both on ppxlib and on the used PPX, using deriving_inline comes with some drawbacks. It can increase the size (and readability) of th
Advanced TopicsPreprocessors and PPXs
Why PPXs Are Especially Useful in OCaml
Other rewriters, such as ppx_expect , show that being able to enrich the syntax via PPX rewriters is very useful, even outside of the specificity of OCaml. Secondly, one of the strong features of
Advanced TopicsPreprocessors and PPXs
The Need for Controlling the PPX Ecosystem: ppxlib
For those interested in the history of OCaml, note that before ppxlib , there were other "official" libraries to deal with PPXs. Camlp4 was a way to extend the OCaml parser with added construc
Advanced TopicsPreprocessors and PPXs
One PPX for Multiple OCaml Versions
ppxlib deals with this issue by converting Parsetree types to and from the latest version. A PPX author then only needs to maintain their transformation for OCaml's latest version and get a PPX
Advanced TopicsPreprocessors and PPXs
Restricting PPXs for Composition, Speed, and Security
Note that Dune combines all PPXs written using ppxlib in a single preprocessor binary, even if the PPXs come from different packages. Compared to this, rewriters that work on the whole AST can a
Advanced TopicsPreprocessors and PPXs
Writing a PPX
If you want to write your own PPX, the place to start is ppxlib's documentation .
Advanced TopicsOperators
Operators
Goals
Using operators as functions and reciprocally, using functions as operators Assign the right associativity and precedence to a custom operator Use and define custom let binders The learning goals o
Advanced TopicsOperators
Using Binary Operators
Finally, in the third line, all the arguments expected by List.filter are provided. The returned list contains the values satisfying the ( <= ) 10 function. The first shows the List.filter typ
Advanced TopicsOperators
Defining Binary Operators
It is a recommended practice to define operators in two steps, like shown in the example. The first definition contains the function's logic. The second definition is merely an alias of the first one
Advanced TopicsOperators
Unary Operators
This allows users to write more compact code. However, be careful not to write excessively terse code, as it is harder to maintain. Understanding operators must be obvious to most readers, otherwise
Advanced TopicsOperators
Allowed Operators
OCaml has a subtle syntax; not everything is allowed as an operator symbol. An operator symbol is an identifier with a special syntax, so it must have the following structure:
Advanced TopicsOperators
Prefix Operator
First character, either: ? ~ ! Following characters, at least one if the first character is ? or ~ , optional otherwise: $ & * + - / = > @ ^ | % <
Advanced TopicsOperators
Binary Operator
Don't define wide scope operators. Restrict their scope to module or function. Don't use many of them. Before defining a custom binary operator, check that the symbol is not already used. This can be
Advanced TopicsOperators
Operator Associativity and Precedence
The complete list of precedence is longer because it includes the predefined operators that are not allowed to be used as custom operators. The OCaml Manual has a table that sums up the operator as
Advanced TopicsOperators
Binding Operators
<!-- TODO: move this into the list tutorial In the following example, we use that mechanism to write a function which produces the list of Friday 13th dates between two years. ```ocaml # let ( let
Advanced TopicsObjects
Objects
Objects and Classes
s is an opaque object. The implementation (i.e., the list) is hidden from callers. In the OCaml toplevel, we can examine the types of objects and methods in more detail: Notice the syntax.
Advanced TopicsObjects
Polymorphic Classes
We can force OCaml to be more specific and only allow drain_stack to be called on 'a stack s by narrowing the type of the s argument, like this: Notice the type of drain_stack . Cleverly
Advanced TopicsObjects
Inheritance, Virtual Classes, Initialisers
Let's create a label which says "Press me!" and add it to the button: Here's our comparatively trivial label class: Before defining our label class, let's play with the button class in
Advanced Topics