summaryrefslogtreecommitdiff
path: root/manual/src/refman/extensions/indexops.etex
blob: a4c49619e605e53afef245a4821b81e191c06e34 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
(Introduced in 4.06)

\begin{syntax}

dot-ext:
   | dot-operator-char { operator-char }
;
dot-operator-char:
  '!' || '?' || core-operator-char || '%' || ':'
;
expr:
          ...
        | expr '.' [module-path '.'] dot-ext ( '(' expr ')' || '[' expr ']' || '{' expr '}' ) [ '<-' expr ]
;
operator-name:
          ...
        | '.' dot-ext ('()' || '[]' || '{}') ['<-']
;
\end{syntax}


This extension provides syntactic sugar for getting and setting elements
for user-defined indexed types. For instance, we can define python-like
dictionaries with
\begin{caml_example*}{verbatim}
module Dict = struct
include Hashtbl
let ( .%{} ) tabl index = find tabl index
let ( .%{}<- ) tabl index value = add tabl index value
end
let dict =
  let dict = Dict.create 10 in
  let () =
    dict.Dict.%{"one"} <- 1;
    let open Dict in
    dict.%{"two"} <- 2 in
  dict
\end{caml_example*}
\begin{caml_example}{toplevel}
dict.Dict.%{"one"};;
let open Dict in dict.%{"two"};;
\end{caml_example}

\subsection{ss:multiindexing}{Multi-index notation}
\begin{syntax}
expr:
          ...
        | expr '.' [module-path '.'] dot-ext '(' expr {{ ';' expr }} ')' [ '<-' expr ]
        | expr '.' [module-path '.'] dot-ext '[' expr {{ ';' expr }} ']' [ '<-' expr ]
        | expr '.' [module-path '.'] dot-ext '{' expr {{ ';' expr }} '}' [ '<-' expr ]
;
operator-name:
          ...
        | '.' dot-ext ('(;..)' || '[;..]' || '{;..}') ['<-']
;
\end{syntax}

Multi-index are also supported through a second variant of indexing operators

\begin{caml_example*}{verbatim}
let (.%[;..]) = Bigarray.Genarray.get
let (.%{;..}) = Bigarray.Genarray.get
let (.%(;..)) = Bigarray.Genarray.get
\end{caml_example*}

which is called when an index literals contain a semicolon separated list
of expressions with two and more elements:

\begin{caml_example*}{verbatim}
let sum x y = x.%[1;2;3] + y.%[1;2]
(* is equivalent to *)
let sum x y = (.%[;..]) x [|1;2;3|] + (.%[;..]) y [|1;2|]
\end{caml_example*}

In particular this multi-index notation makes it possible to uniformly handle
indexing Genarray and other implementations of multidimensional arrays.

\begin{caml_example*}{verbatim}
module A = Bigarray.Genarray
let (.%{;..}) = A.get
let (.%{;..}<- ) = A.set
let (.%{ }) a k = A.get a [|k|]
let (.%{ }<-) a k x = A.set a [|k|] x
let syntax_compare vec mat t3 t4 =
          vec.%{0} = A.get vec [|0|]
   &&   mat.%{0;0} = A.get mat [|0;0|]
   &&   t3.%{0;0;0} = A.get t3 [|0;0;0|]
   && t4.%{0;0;0;0} = t4.{0,0,0,0}
\end{caml_example*}

Beware that the differentiation between the multi-index and single index
operators is purely syntactic: multi-index operators are restricted to
index expressions that contain one or more semicolons ";". For instance,
\begin{caml_example*}{verbatim}
  let pair vec mat = vec.%{0}, mat.%{0;0}
\end{caml_example*}
is equivalent to
\begin{caml_example*}{verbatim}
  let pair vec mat = (.%{ }) vec 0, (.%{;..}) mat [|0;0|]
\end{caml_example*}
Notice that in the "vec" case, we are calling the single index operator, "(.%{})", and
not the multi-index variant, "(.{;..})".
For this reason, it is expected that most users of multi-index operators will need
to define conjointly a single index variant
\begin{caml_example*}{verbatim}
let (.%{;..}) = A.get
let (.%{ }) a k = A.get a [|k|]
\end{caml_example*}
to handle both cases uniformly.