364 search results for "function"
-
Memory Representation of Values
Tuples, Records, and Arrays
The Obj.repr function retrieves the runtime representation of any OCaml value. Obj.is_block checks the bottom bit to determine if the value is a block header or an unboxed integer. You can check the difference be
Runtime & Compiler -
Memory Representation of Values
Floating-Point Numbers and Arrays
hich are not optimized in the same way and have the normal tuple tag value (0). This tells us that float arrays have a tag value of 254. Now let's test some sample values using the Obj.tag function to check that the allocated block has the expected runtime tag, and also use Obj.double_field to retrieve a float from within the block: First, let's check that float arrays do in fact have
Runtime & Compiler -
Memory Representation of Values
Custom Heap Blocks
ted. This finalizer has nothing to do with ordinary OCaml finalizers (as created by Gc.finalize and explained in Understanding The Garbage Collector ). They are instead used to call C cleanup functions such as free . The first word of the data within the custom block is a C pointer to a struct of custom operations. The custom block cannot have pointers to OCaml blocks and is opaque to the
Runtime & Compiler -
Objects
Objects and Classes
ogramming is the stack class. This is a pretty terrible example in many ways, but let's use it here to show the basics of writing object-oriented OCaml. OCaml is an object-oriented, imperative, functional programming language . It mixes all these paradigms and lets you use the most appropriate (or most familiar) programming paradigm for the task at hand. In this chapter, we're going to look at
Advanced Topics -
Objects
Polymorphic Classes
te class which happened to contain pop and size methods with suitable type signatures, then we might accidentally call drain_stack on objects of that other type. We can define polymorphic functions which can operate on any type of stack. Our first attempt is this one: This stack is now a float stack , and only floating point numbers may be pushed and popped from this stack. Let's demon
Advanced Topics -
Objects
A Note About self
The reference to self names the object, allowing you to call methods in the same class or pass the object to functions outside the class. In other words, it's exactly the same as this in C++/Java. You may completely omit the (self) part if you don't need to refer to yourself. Indeed, in all the examples abov
Advanced Topics -
Objects
The Oo Module and Comparing Objects
IDs. Oo.copy makes a shallow copy of an object. Oo.id object returns a unique identifying number for each object (a unique number across all classes). The Oo module contains a few useful functions for OO programming.
Advanced Topics -
Objects
Immediate Objects and Object Types
eir common methods are visible (see next section). type definitions : there is no need to define an object type in advance, so it lightens the dependency constraints between modules. In terms of functionality, both the object and the record are similar, but each solution has its own advantages: The implementation of a record working like our object would be: Compare with an equivalent record
Advanced Topics -
Functors
Functors From the Standard Library
e functors Set.Make , Map.Make , and Hashtbl.Make return modules satisfying the interfaces Set.S , Map.S , and Hashtbl.S (respectively), which all contain an abstract type t and associated functions. Refer to the documentation for the details about what they provide: Here is the module's signature that the functor Hashtbl.Make expects: Here is the module's signature that the functors S
Module System -
Functors
Naming and Scoping
he same type as Dep.t ( List.t in this case). However, since Make is invoked to create module IterPrint in funkt.ml , the project fails to compile with the following error message: If the function f isn't used, the project compiles without error. Naively, we might have defined Iter.Make as follows: The with type constraint unifies types within a functor's parameter and result modules
Module System -
Functors
Write a Functor to Extend Modules
inside the toplevel, enter the following commands. scanLeft.ml dune dune-project Create a fresh directory with the following files: In this example, we extend List and Array modules with a function scan_left . It does almost the same as fold_left , except it returns all the intermediate values, not the last one as fold_left does. In this section, we define a functor to extend several modul
Module System -
Functors
Conclusion
Functor application essentially works the same way as function application: passing parameters and getting results. The difference is that we are passing modules instead of values. Beyond comfort, it enables a design approach where concerns are not only separate
Module System -
The Compiler Frontend: Parsing and Type Checking
Generating Documentation from Interfaces
some source code that's been annotated with docstring comments: OCaml uses specially formatted comments in the source code to generate documentation bundles. These comments are combined with the function definitions and signatures, and output as structured documentation in a variety of formats. Tools such as odoc and ocamldoc can generate HTML pages, LaTeX and PDF documents, UNIX manual p
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Adding Type Annotations to Find Errors
her verbose and with a line number that doesn't point to the exact location of the incorrect variant name. The best the compiler can do is to point you in the general direction of the algebra function application. There's a single character typo in the code so that it uses Nu instead of Num . The resulting type error is impressive: For instance, consider this broken example that expresse
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Enforcing Principal Typing
pal will show you a new warning: Here's an example of principality warnings when used with record disambiguation. Polymorphic methods for objects Permuting the order of labeled arguments in a function from their type definition Discarding optional labeled arguments Generalized algebraic data types (GADTs) present from OCaml 4.0 onward Automatic disambiguation of record field and constructor n
Runtime & Compiler -
The Compiler Frontend: Parsing and Type Checking
Shorter Module Paths in Type Errors
rovide a complete replacement standard library. It collects these modules into a single Std module, which provides a single module that needs to be opened to import the replacement modules and functions.
Runtime & Compiler -
Sequences
Iterating Over Sequences
ers forever,” and you have to press Ctrl-C to interrupt the execution. The following code is the same infinite loop without any output: The OCaml Standard Library also contains a Seq.iter function, which has the same behavior as List.iter . Writing this:
Data Structures -
Sequences
Reading a File with Seq.Unfold
ition. Note : To make the code in the next section work, create a file named "README.md" and add dummy content. We use a file generated by the following command: Before doing so, let's define a function that reads a file's line from a provided channel, with the type signature needed by Seq.unfold . For the next example, we will demonstrate the versatility of Seq.unfold by using it to read a
Data Structures -
Sequences
Consumer Example: Seq.iter
In print_seq , Seq.iter takes the function print_int and applies it to each element as they are generated. If List.iter was used, the whole integer list would be needed before displaying them starts.
Data Structures -
Understanding the Garbage Collector
Generational Garbage Collection
different memory layouts and garbage-collection algorithms for the major and minor heaps to account for this generational difference. We'll explain how they differ in more detail next. A typical functional programming style means that young blocks tend to die young and old blocks tend to stay around for longer than young ones. This is often referred to as the generational hypothesis . A small
Runtime & Compiler -
Understanding the Garbage Collector
The Gc Module and OCAMLRUNPARAM
ttings. The format of OCAMLRUNPARAM is documented in the OCaml manual . OCaml provides several mechanisms to query and alter the behavior of the runtime system. The Gc module provides this functionality from within OCaml code, and we'll frequently refer to it in the rest of the chapter. As with several other standard library modules, Core alters the Gc interface from the standard OCaml
Runtime & Compiler -
Understanding the Garbage Collector
Understanding Allocation
<div class="note"> These poll points check ptr against limit and developers should expect them to be placed at the start of every function and the back edge of loops. The compiler includes a dataflow pass that removes all but the minimum set of points necessary to ensure these checks happen in a bounded amount of time. It is possib
Runtime & Compiler -
Understanding the Garbage Collector
Setting the Size of the Minor Heap
t at the cost of a bigger memory profile). This setting can be overridden via the s=<words> argument to OCAMLRUNPARAM . You can change it after the program has started by calling the Gc.set function:
Runtime & Compiler -
Understanding the Garbage Collector
The Mutable Write Barrier
install the Core benchmarking suite via opam install core_bench before you compile this code: The OCaml compiler keeps track of any mutable types and adds a call to the runtime caml_modify function before making the change. This checks the location of the target write and the value it's being changed to, and ensures that the remembered set is consistent. Although the write barrier is reas
Runtime & Compiler -
Mutability and Imperative Control Flow
Mutable Record Fields
Remark : the left arrow symbol <- for mutating mutable record field values is not an operator function, like the assignment operator ( := ) is for refs . It is rather a construct of the language, it has no type. In contrast to references, there is no special syntax to dereference a mutable recor
Introduction -
Mutability and Imperative Control Flow
For Loop
Note: Here is how to do the same thing using an iterator function: for loops are convenient to iterate over and modify arrays: When you use the downto keyword (instead of the to keyword), the counter decreases on every iteration of the loop. The body of
Introduction -
Mutability and Imperative Control Flow
Recommendations for Mutable State and Side Effects
Functional and imperative programming styles are often used together. However, not all ways of combining them give good results. We show some patterns and anti-patterns relating to mutable states and
Introduction -
Mutability and Imperative Control Flow
Good: Memoization
und in the cache (it's a miss), and the result is computed, stored in the cache, and returned. However, instead of precomputing everything, memoization uses a cache that is populated when calling the function. Either, the provided arguments The memoization technique relies on the same idea as the previous section's example: lookup results from a table of previously computed values.
Introduction -
Monads
Example: The Lwt Monad
that we saw before involves creating references, but those references are completely hidden behind the monadic interface. Moreover, we know that bind involves registering callbacks, but that functionality (which as you might imagine involves maintaining collections of callbacks) is entirely encapsulated. And Lwt.Infix.( >>= ) is a synonym for Lwt.bind , so the library does provide an infi
Data Structures -
Operators
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. This provides a default pronunciation to the operator and clearly indicates that the operator is syntactic sugar : a means to ease
Advanced Topics -
Operators
Allowed Operators
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 done in two ways: By surrounding the candidate symbol with parentheses in UTo
Advanced Topics -
Sets
Creating a Set
There's another relevant function StringSet.of_seq: string Seq.t -> StringSet.t that creates a set from a sequence . Converting a list into a set using StringSet.of_list : A set with a single element is created using Strin
Data Structures -
Sets
Working With Sets
Let's look at a few functions for working with sets using these two sets.
Data Structures -
Sets
Adding an Element to a Set
The function StringSet.add with type string -> StringSet.t -> StringSet.t takes both a string and a string set. It returns a new string set. Sets created with the Set.Make functor in OCaml are immutable, so
Data Structures -
Sets
Removing an Element from a Set
The function StringSet.remove with type string -> StringSet.t -> StringSet.t takes both a string and a string set. It returns a new string set without the given string.
Data Structures -
Sets
Union of Two Sets
With the function StringSet.union , we can compute the union of two sets.
Data Structures -
Sets
Intersection of Two Sets
With the function StringSet.inter , we can compute the intersection of two sets.
Data Structures -
Sets
Subtracting a Set from Another
With the function StringSet.diff , we can remove the elements of the second set from the first set.
Data Structures -
Sets
Filtering a Set
The function StringSet.filter of type (string -> bool) -> StringSet.t -> StringSet.t creates a new set by keeping the elements that satisfy a predicate from an existing set.
Data Structures -
Sets
Checking if an Element is Contained in a Set
To check if an element is contained in a set, use the StringSet.mem function.
Data Structures -
Sets
Conclusion
We gave an overview of OCaml's Set module by creating a StringSet module using the Set.Make functor. Further, we looked at how to create sets based on a custom comparison function. For more information, refer to Set in the Standard Library documentation.
Data Structures -
Arrays
The Standard Library Array Module
OCaml provides several useful functions for working with arrays. Here are some of the most common ones:
Data Structures -
Arrays
Length of an Array
The Array.length function returns the size of an array:
Data Structures -
Maps
Adding Entries to a Map
Note that the initial map lucky_numbers remains unchanged. If the passed key is already associated with a value, the passed value replaces it. To add an entry to a map, use the add function that takes a key, a value, and the map to which it will be added. It returns a new map with that key-value pair added:
Data Structures -
Maps
Removing Entries From a Map
Note that the initial map lucky_numbers remains unchanged. Removing a key that isn't present in the map has no effect. To remove an entry from a map, use the remove function, which takes a key and a map. It returns a new map with that key's entry removed.
Data Structures -
Maps
Checking if a Key is Contained in a Map
To check if a key is a member of a map, use the mem function:
Data Structures -
Maps
Filtering a Map
To filter a map, use the filter function. It takes a predicate to filter entries and a map. It returns a new map containing the entries satisfying the predicate.
Data Structures -
Maps
Map a Map
sing string_of_int . Using StringMap.map , we create a map associating keys with string values: The lucky_numbers map associates string keys with integer values: Map modules have a map function:
Data Structures -
Options
The Standard Library Option Module
Most of the functions in this section, as well as other useful ones, are provided by the OCaml standard library in the Stdlib.Option module.
Data Structures -
Labelled and Optional Arguments
Passing Labelled Arguments
Note : Passing labelled arguments through the pipe operator ( |> ) throws a syntax error: Labelled arguments are passed using a tilde ~ and can be placed at any position and in any order. The function Option.value from the standard library has a parameter labelled default .
Introduction