364 search results for "function"

Showing 251 - 300
  1. Values and Functions

    Discarding Values Using Pattern Matching

    <!-- END Version Two --> Tuples behave differently from records; contained data is anonymous, and its position is used to access it. To discard the email value from the tuple of the contact fi

    Introduction
  2. Values and Functions

    Scopes and Environments

    <!-- With respect to the environment, there are no means to: - List its contents - Clear its contents - Remove a definition - Reset it to an earlier state --> Top-level expressions are also statemen

    Introduction
  3. Values and Functions

    Inner Shadowing

    <!-- A name-value pair in a local expression *shadows* a binding with the same name in the global environment. In other words, the local binding temporarily hides the global one, making it inaccessib

    Introduction
  4. Values and Functions

    Same-Level Shadowing

    There are now two definitions of h in the environment. The first h is unchanged. When the second h is defined, the first one becomes unreachable. Another kind of shadowing takes place when t

    Introduction
  5. Higher Order Functions

    Mapping Options

    Note that both sides of the match return the same thing: if we had a None we return None , if we have a Some we return a Some . This way, the structure is preserved. Mapping an optional valu

    Introduction
  6. Higher Order Functions

    Mapping Results

    Both of these are useful in different situations, such as wanting to change the type of errors, or only perform operations once we have an Ok value. We can map the value in the Ok value constr

    Introduction
  7. Higher Order Functions

    Mapping Custom Data Types

    Note that the structure of the tree is preserved, but every time we encounter a value , we update it with (fn value) . When working with our custom data types, such as the tree we used in the

    Introduction
  8. Higher Order Functions

    Let-ops

    This has the advantage of making code a lot more readable, without changing the behavior we've come to expect from bind calls. Thankfully, OCaml lets us redefine a subset of operators called let-

    Introduction
  9. Your First OCaml Program

    Installing and Using Modules From a Package

    efer to the Sexplib documentation for more information. Next, define a string containing a valid S-expression in bin/main.ml . Parse it into a S-expression with the Sexplib.Sexp.of_string function, and then convert it back into a string with Sexplib.Sexp.to_string and print it. To illustrate this, let's update our hello project to parse a string containing an S-expression and print

    First Steps
  10. Your First OCaml Program

    Using the Preprocessor to Generate Code

    le, and edit it to look like this: Let's assume we'd like hello to display its output as if it was a list of strings in UTop: ["hello"; "using"; "an"; "opam"; "library"] . To do that, we need a function turning a string list into a string , adding brackets, spaces, and commas. Instead of defining it ourselves, let's generate it automatically with a package. We'll use ppx_deriving . Here is how t

    First Steps
  11. A Tour of OCaml

    Type Conversion and Type-Inference

    ison to other languages. Arguably, this saves more time than we lose by being more explicit. In OCaml you need to explicitly convert the integer to a floating point number using the float_of_int function: In the first example, + is intended to be used with integers, so it can't be used with the 2.5 float. In the second example, +. is intended to be used with floats, so it can't be used with th

    First Steps
  12. A Tour of OCaml

    Pattern Matching, Cont'd

    mes, just as let does. In the third pattern, x designates the data inside the double-wrapped option. Pattern matching isn't limited to lists. Any kind of data can be inspected using it, except functions. Patterns are expressions that are compared to an inspected value. It could be performed using if … then … else … , but pattern matching is more convenient. Here is an example using the opti

    First Steps
  13. A Tour of OCaml

    Records

    Here, the pattern { age = x; _ } is typed with the most recently declared record type that has an age field of type int . The type int is inferred from the expression 13 <= x && x <= 19 . The function is_teenager will only work with the found record type, here person . When defining gerard , no type needs to be declared. The type checker will search for a record which has exactly three fiel

    First Steps
  14. Configuring Your Editor

    1) Hovering for Type Information

    This is a great feature that let's you see type information of any OCaml variable or function. All you have to do is place your cursor over the code and it will be displayed in the tooltip. VSCode Hovering

    Tooling
  15. Configuring Your Editor

    Finer configuration

    OCaml-eglot can be finely configured, the project README gives several configuration paths to adapt perfectly to your workflow. You will also find there an exhaustive presentation of the different functions offered by the mode.

    Tooling
  16. Configuring Your Editor

    Getting Type Information

    OCaml-eglot README provides a comprehensive overview of all the functions available in this mode! Emacs Type information Opening an OCaml file should launch an ocaml-lsp server, and you can convince yourself that it's working by using, for example, the ocaml-eglot-ty

    Tooling
  17. 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
  18. 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
  19. 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
  20. Modules

    Interfaces and Implementations

    module implementation) The public declarations of a module (the module interface) For this, we must distinguish: By default, anything defined in a module is accessible from other modules. Values, functions, types, or submodules, everything is public. This can be restricted to avoid exposing definitions that are not relevant from the outside.

    Module System
  21. Modules

    Stateful Modules

    and third calls return the same results, showing that the internal state was reset. A module may have an internal state. This is the case for the Random module from the standard library. The functions Random.get_state and Random.set_state provide read and write access to the internal state, which is nameless and has an abstract type.

    Module System
  22. Modules

    Conclusion

    Functors, which act like functions from modules to modules Libraries, which are compiled modules bundled together Packages, which are installation and distribution units Going further, here are the other means to handle OCaml softwar

    Module System
  23. 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
  24. 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
  25. 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
  26. 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
  27. The Compiler Backend: Bytecode and Native code

    The Untyped Lambda Form

    ype information into a simpler intermediate lambda form . The lambda form discards higher-level constructs such as modules and objects and replaces them with simpler values such as records and function pointers. Pattern matches are also analyzed and compiled into highly optimized automata.

    Runtime & Compiler
  28. The Compiler Backend: Bytecode and Native code

    Generating Portable Bytecode

    <div class="note"> There are around 140 instructions in total, but most are just minor variants of commonly encountered operations (e.g., function application at a specific arity). You can find full details online . The preceding bytecode has been simplified from the lambda form into a set of simple instructions that are executed seriall

    Runtime & Compiler
  29. The Compiler Backend: Bytecode and Native code

    Compiling and Linking Bytecode

    le program. The order in which .cmo arguments are presented on the command line defines the order in which compilation units are initialized at runtime. Remember that OCaml has no single main function like C, so this link order is more important than in C programs. The individual objects in the library are linked as regular cmo files in the order specified when the library file was built. I

    Runtime & Compiler
  30. The Compiler Backend: Bytecode and Native code

    Embedding OCaml Bytecode in C

    ile. Here's an example to show how it all fits together. This mode causes ocamlc to output an object file containing the bytecode for the OCaml part of the program, as well as a caml_startup function. All of the OCaml modules are linked into this object file as bytecode, just as they would be for an executable. A consequence of using the bytecode compiler is that the final link phase must

    Runtime & Compiler
  31. The Compiler Backend: Bytecode and Native code

    Compiling Fast Native Code

    ks modules together into an executable, it uses the contents of the cmx files to perform cross-module inlining across compilation units. This can be a significant speedup for standard library functions that are frequently used outside of their module. A .o file containing native object code A .cmx file containing extra information for linking and cross-module optimization A .cmi compile

    Runtime & Compiler
  32. The Compiler Backend: Bytecode and Native code

    Benchmarking Polymorphic Comparison

    ee that this polymorphic comparison is much heavier than the simple monomorphic integer comparison from earlier. Let's confirm this hypothesis again by writing a quick Core_bench test with both functions:

    Runtime & Compiler
  33. The Compiler Backend: Bytecode and Native code

    Debugging Native Code Binaries

    assembly when the library is compiled in debug mode. These include the CFI stubs you will have noticed in the profiling output earlier ( .cfi_start_proc and .cfi_end_proc to delimit an OCaml function call, for example). The native code compiler builds executables that can be debugged using conventional system debuggers such as GNU gdb . You need to compile your libraries with the -g optio

    Runtime & Compiler
  34. The Compiler Backend: Bytecode and Native code

    Interactive Breakpoints with the GNU Debugger

    e first call to take : Now we can run this interactively within gdb : Compile and run this with debugging symbols. You should see the following output: Let's write a mutually recursive function that selects alternating values from a list. This isn't tail-recursive, so our stack size will grow as we single-step through the execution: Let's see name mangling in action with some interacti

    Runtime & Compiler
  35. The Compiler Backend: Bytecode and Native code

    Gprof

    gmon.out when the program is executed. This profile information can then be examined using gprof . gprof produces an execution profile of an OCaml program by recording a call graph of which functions call one another, and recording the time these calls take during the program execution.

    Runtime & Compiler
  36. The Compiler Backend: Bytecode and Native code

    Perf

    home page . This trace broadly reflects the results of the benchmark itself. The mutable benchmark consists of the combination of the call to test_mutable and the caml_modify write barrier function in the runtime. This adds up to slightly over half the execution time of the application. When this completes, you can interactively explore the results: Run Perf on a compiled binary to reco

    Runtime & Compiler
  37. Memory Representation of Values

    Distinguishing Integers and Pointers at Runtime

    . This representation means that integers are unboxed runtime values in OCaml so that they can be stored directly without having to allocate a wrapper block. They can be passed directly to other function calls in registers and are generally the cheapest and fastest values to use in OCaml. OCaml values don't all have to be boxed at runtime. Instead, values use a single tag bit per word to disting

    Runtime & Compiler
  38. Memory Representation of Values

    Integers, Characters, and Other Basic Types

    it are very efficient to use, since integers are never allocated on the heap. They can be passed directly in registers and not appear on the stack if you don't have too many parameters to your functions. Modern architectures such as x86_64 have a lot of spare registers to further improve the efficiency of using unboxed integers. Many basic types are efficiently stored as unboxed integers at

    Runtime & Compiler
  39. 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
  40. 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
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. 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
  50. 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