Deleting variables in Ocaml - ocaml

I have not been able to find anyone previously asking this :
How do you let go of a variable in OCaml ? Python has del and I assume OCaml has a similar function, but I cannot find it. Is it even possible to delete a variable ?
If not, then how does one manage variables in OCaml ?

I it not possible to let go of a variable in OCaml with a keyword. However you may use the variable scope in such a way :
let a = b in
print_endline a ;
...
Is different from :
( let a = b in
print_endline a ) ;
...
In the first one, you may access a inside ..., but not in the second.
You can also shadow a variable :
let a = b in
print_endline a ;
let a = () in
...
Inside ..., it will be impossible to access the original a: there is a new variable named a, the old one is "deleted" (the correct term being shadowed).
OCaml also allows you to declare variables anywhere, not matter how "small" the expression :
print_endline (let a = b in a) ;
...
is perfectly valid, and a is only defined inside the ( ). The printed value will be the same than in the first example.

The closest counterpart of a Python variable in OCaml is a reference (which is a mutable field of a record). In Python, you commonly delete a variable to let the GC do it work and collect the variable contents as soon as possible. You could do this in OCaml as well by assigning a new value to the reference. Commonly, you would use the option type or some other container to store values in references, e.g.,
let foo = ref None
let () =
foo := Some big_data_structure; (* assigning *)
foo := None (* deleting *)
or
let foo = ref []
let () =
foo := [some; huge; list];
foo := []
If we will speak about immutable variables, then you can also speed up their collection by making sure that their lifetime is as small as possible. Therefore it is a common practice to bind a result of a transformation of an immutable value to the same variable as it was before (aka shadowing, rebinding, hiding), e.g.,
let names = ["ahura"; "bahman"; "dana"; "ervin"]
let names = List.map String.capitalize names
(* previous names are no longer accessible here, so GC can collect them *)
Here we made sure that the old names are not accessible so that the GC can collect them in the nearest minor collection.

Related

OCaml: accessing a type in the Stdlib

I want to use the Stack module from the Stdlib of OCaml, but I also need a membership function, which the Stack module lacks. So, following https://dev.realworldocaml.org/files-modules-and-programs.html, I created a file stack1.ml reading:
include Stack
let mem a t = List.mem a t.c
since c is the name of the record used in stack.ml (that file contains the line: type 'a t = { mutable c : 'a list; mutable len : int; }). But I get:
Error: Unbound record field c
What can I do ?
(And also: do I need a file with a different name Stack1 ? This is a bit annoying for the files calling it.)
The fact that the type 'a Stack.t is implemented using a mutable list or any other data type is an implementation detail that is abstracted away by the interface of the Stack module.
In other words, outside of the Stack module, you can only use the functions provided by the stack module that works on the abstract type 'a Stack.t independently of this implementation.
Fortunately, those functions are more than enough to implement a mem function. For instance, with a fold:
let mem x s = Stack.fold (fun acc y -> acc || x = y) false s

can't define a new variable to hold my rlist

I'm learning about imperative programming in Ocaml and I have the following situation where I'm trying to reverse a linked list:
these are my two defined types:
type cell = { data : int; next : rlist; }
and rlist = cell option ref
and here is my function reverse:
let reverse (head:rlist) =
let rec helper ((head: rlist),(tmp: rlist)) =
match !head with
| None -> tmp
| Some c when !(c.next) = None ->
c.next := !tmp ; tmp := Some c ; tmp
| Some c ->
let a = ref Some !(c.next) ;
c.next := !tmp ;
tmp := Some c ;
helper (a,tmp)
in
helper (head, ref None)
this version will give me Syntax error but if I replace: let a = ref Some !(c.next) with head := !(c.next) it will work. Therefore, there is something wrong with the declaration of my let.
This expression:
ref Some !(c.next)
is parsed like this:
(ref Some) !(c.next)
essentially because function application in OCaml has very high precedence.
You should parenthesize like this:
ref (Some !(c.next))
After fixing this problem you have another syntax problem. This expression:
let a = ref (Some !(c.next));
is not valid. You need to have in after let. The short description is that inside a function let is used to introduce a local variable, and the expression that uses the local variable appears after in. The in is required. You can fix this by changing the ; at the end to in.
After fixing these two syntax problems you have at least one type error. But I hope this helps you make progress.

When should extensible variant types be used in OCaml?

I took a course on OCaml before extensible variant types were introduced, and I don't know much about them. I have several questions:
(This question was deleted because it attracted a "not answerable objectively" close vote.)
What are the low-level consequences of using EVTs, such as performance, memory representation, and (un-)marshaling?
Note that my question is about extensible variant type specifically, unlike the question suggested as identical to this one (that question was asked prior to the introduction of EVTs!).
Extensible variants are quite different from standard variants in term of
runtime behavior.
In particular, extension constructors are runtime values that lives inside
the module where they were defined. For instance, in
type t = ..
module M = struct
type t +=A
end
open M
the second line define a new extension constructor value A and add it to the
existing extension constructors of M at runtime.
Contrarily, classical variants do not really exist at runtime.
It is possible to observe this difference by noticing that I can use
a mli-only compilation unit for classical variants:
(* classical.mli *)
type t = A
(* main.ml *)
let x = Classical.A
and then compile main.ml with
ocamlopt classical.mli main.ml
without troubles because there are no value involved in the Classical module.
Contrarily with extensible variants, this is not possible. If I have
(* ext.mli *)
type t = ..
type t+=A
(* main.ml *)
let x = Ext.A
then the command
ocamlopt ext.mli main.ml
fails with
Error: Required module `Ext' is unavailable
because the runtime value for the extension constructor Ext.A is missing.
You can also peek at both the name and the id of the extension constructor
using the Obj module to see those values
let a = [%extension_constructor A]
Obj.extension_name a;;
: string = "M.A"
Obj.extension_id a;;
: int = 144
(This id is quite brittle and its value it not particurlarly meaningful.)
An important point is that extension constructor are distinguished using their
memory location. Consequently, constructors with n arguments are implemented
as block with n+1 arguments where the first hidden argument is the extension
constructor:
type t += B of int
let x = B 0;;
Here, x contains two fields, and not one:
Obj.size (Obj.repr x);;
: int = 2
And the first field is the extension constructor B:
Obj.field (Obj.repr x) 0 == Obj.repr [%extension_constructor B];;
: bool = true
The previous statement also works for n=0: extensible variants are never
represented as a tagged integer, contrarily to classical variants.
Since marshalling does not preserve physical equality, it means that extensible
sum type cannot be marshalled without losing their identity. For instance, doing
a round trip with
let round_trip (x:'a):'a = Marshall.from_string (Marshall.to_string x []) 0
then testing the result with
type t += C
let is_c = function
| C -> true
| _ -> false
leads to a failure:
is_c (round_trip C)
: bool = false
because the round-trip allocated a new block when reading the marshalled value
This is the same problem which already existed with exceptions, since exceptions
are extensible variants.
This also means that pattern-matching on extensible type is quite different
at runtime. For instance, if I define a simple variant
type s = A of int | B of int
and define a function f as
let f = function
| A n | B n -> n
the compiler is smart enough to optimize this function to simply accessing the
the first field of the argument.
You can check with ocamlc -dlambda that the function above is represented in
the Lambda intermediary representation as:
(function param/1008 (field 0 param/1008)))
However, with extensible variants, not only we need a default pattern
type e = ..
type e += A of n | B of n
let g = function
| A n | B n -> n
| _ -> 0
but we also need to compare the argument with each extension constructor in the
match leading to a more complex lambda IR for the match
(function param/1009
(catch
(if (== (field 0 param/1009) A/1003) (exit 1 (field 1 param/1009))
(if (== (field 0 param/1009) B/1004) (exit 1 (field 1 param/1009))
0))
with (1 n/1007) n/1007)))
Finally, to conclude with an actual example of extensible variants,
in OCaml 4.08, the Format module replaced its string-based user-defined tags
with extensible variants.
This means that defining new tags looks like this:
First, we start with the actual definition of the new tags
type t = Format.stag = ..
type Format.stag += Warning | Error
Then the translation functions for those new tags are
let mark_open_stag tag =
match tag with
| Error -> "\x1b[31m" (* aka print the content of the tag in red *)
| Warning -> "\x1b[35m" (* ... in purple *)
| _ -> ""
let mark_close_stag _tag =
"\x1b[0m" (*reset *)
Installing the new tag is then done with
let enable ppf =
Format.pp_set_tags ppf true;
Format.pp_set_mark_tags ppf true;
Format.pp_set_formatter_stag_functions ppf
{ (Format.pp_get_formatter_stag_functions ppf ()) with
mark_open_stag; mark_close_stag }
With some helper function, printing with those new tags can be done with
Format.printf "This message is %a.#." error "important"
Format.printf "This one %a.#." warning "not so much"
Compared with string tags, there are few advantages:
less room for a spelling mistake
no need to serialize/deserialize potentially complex data
no mix up between different extension constructor with the same name.
chaining multiple user-defined mark_open_stag function is thus safe:
each function can only recognise their own extension constructors.

What is <cycle> in data?

(I use OCaml version 4.02.3)
I defined a type self
# type self = Self of self;;
type self = Self of self
and its instance s
# let rec s = Self s;;
val s : self = Self <cycle>
Since OCaml is a strict language, I expected defining s will fall into infinite recursion. But the interpreter said s has a value and it is Self <cycle>.
I also applied a function to s.
# let f (s: self) = 1;;
val f : self -> int = <fun>
# f s;;
- : int = 1
It seems s is not evaluated before the function application (like in non-strict language).
How OCaml deal with cyclic data like s? Self <cycle> is a normal form?
OCaml is indeed an eager language, however s is a perfectly valid and fully evaluated term that happens to contain a cycle. For instance, this code yields the expected result:
let f (Self Self x) = x
f s == s;;
More precisely, the memory representation of constructors with at n arguments are boxed and read like this:
⋅—————————————————————————————————————————————⋅
| header | field[0] | field[1] | ⋯ | fiekd[n] |
⋅—————————————————————————————————————————————⋅
The header contains metadata whereas field[k] is an OCaml value, i.e. either an integer or a pointer. In the case of s, Self has only one argument, and thus only one field field[0]. The value of field[0] is then simply a pointer towards the start of the block. The term s is thus perfectly representable in OCaml.
Moreover, the toplevel printer is able to detect this kind of cycles and print an <cycle> to avoid falling into an infinite recursion when printing the value of s. Here, <cycle>, like <abstr> or <fun>, represents just a kind of value that the toplevel printer cannot print.
Note, however, that cyclical value will trigger infinite recursion in many situations, for instance f s = s where (=) is the structural equality
and not the physical one (i.e. (==)) triggers such recursion, another example would be
let rec ones = 1 :: ones;; (* prints [1;<cycle>] *)
let twos = List.map ((+) 1) ones;; (* falls in an infinite recursion *)

F# list of key value pairs to variable assignments

Given a list of key/value pairs:
do
[("A", 1);("B",2)]
|> (fun list ->
for item in list do
match item with
| ("A", x) -> //expression assigning x to variable "A"
| ("B", x) -> //expression assigning x to variable "B"
| _ -> //default expression
)
Are there some expressions I can write that will accomplish the same thing as
let A = 1
let B = 2
I know in advance that the list has no more than 10 items, and that the items are tuples of <string, int> but don't know in advance whether "A" or "B" or other keys may be present or if the list is be empty.
Basically, decompose the list into a set of typed variables.
UPDATE: Notes on Context
In my app I receive a list of key/value pairs just like this from an upstream program maintained by a different team. I expect certain keys to be in the list, which i want to assign to typed variables for later processing. I'll throw an exception if ones I need are missing. However I don't want to be locked in to any given set of variable names, except for the expected ones. For all of them, I want to be able to assign them at run time.
If you want to do something with the variables later on in the code, then they will need to be in scope - so you will inevitably have to declare the variables in some way. The easiest option is to make them mutable and mutate them according to the values in the list:
let mutable A = 0
let mutable B = 0
To make the mutation a bit easier, you can create a lookup table with setters:
let setters =
dict [ ("A", fun x -> A <- x); ("B", fun x -> B <- x) ]
This now lets you iterate over the inputs, use dictionary lookup to get the appropriate setter and invoke it to set the variable value:
for var, value in [("A", 1);("B",2)] do
setters.[var] value
With the limited context of your question, it is a bit hard to say whether this is a good way of achieving what actually motivated your question - as F# code, it does look like a bit ugly and it is likely that if you add more context, someone can suggest a better way.
It sounds like you have some dynamic data that can be represented well as a map:
let data = Map [ ("A", 1); ("B", 2) ]
let a = Map.find "A" data
// throws an exception if "A" is not present
let b = Map.find "B" data
// throws an exception if "B" is not present
let c = Map.tryFind "C" data
// "C" is not present so c = None
Note: In F# the convention is for binding names (variable names) to start with a lower case letter.