Skip to content

Commit bba62a5

Browse files
author
Hongbo Zhang
committed
[docs][skip ci] clean up docs about FFI
1 parent 06743cb commit bba62a5

File tree

6 files changed

+104
-116
lines changed

6 files changed

+104
-116
lines changed
Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,62 @@
1-
JavaScript functions are all [uncurried](https://en.wikipedia.org/wiki/Currying), while OCaml functions are curried by default.
1+
Note that OCaml's calling convention is curried by default, while JS
2+
does not have native support. Curried and uncurried functions can be
3+
told from type signatures.
4+
5+
For example
6+
7+
```ocaml
8+
val f : int -> string -> int
9+
val f_uncurry : int * string -> int [@uncurry]
10+
```
211

3-
A naive approach would be to Curry every OCaml functions but this has a non trivial cost and makes the generated code harder to read. Therefore BuckleScript will try its best to uncurry its function in both definition and call site.
412

5-
It is also possible to help BuckleScript perform the uncurrying by using using the runtime provided `Fn` module:
613

7-
```OCaml
8-
let iter_f = Fn.mk1 my_function in
9-
List.iter iter_f l
14+
- How BuckleScript compiles function application
15+
16+
To apply a function, you can do this
17+
18+
```ocaml
19+
f 3 "x"
20+
f_uncurry #@ (3,"x")
1021
```
22+
For uncurried function applicaton, BuckleScript is guaranteed to
23+
compile it in the same way as JS code
24+
25+
```js
26+
f_uncurry(3,"x")
27+
```
28+
29+
However, for curried function application, it depends on how compiler
30+
optimizations goes, for most cases, when the compiler see the
31+
definition of `f`, it will compile it in the most efficient way, i.e,
32+
JS full aplication, if the compiler can not see the definition of `f`,
33+
it will do a runtime dispath, so there are two possible outputs:
34+
35+
```js
36+
Curry._2(f, 3, "x") // compiler fails to optimize
37+
f(3, "x") // compiler optimized correctly
38+
```
39+
Both are correct code, but the second one is more efficient.
40+
41+
- How BuckleScript handles function definition
42+
43+
```ocaml
44+
let f = fun a b -> a + string_of_int b
45+
let f_uncurry = fun %uncurry a b -> a + string_of_int b
46+
```
47+
48+
- When is uncurried function recommended
49+
50+
1. For FFI to JS functions, all object methods are *strongly recommended*
51+
to type it as uncurried function
52+
53+
54+
55+
2. When function is passed as a callback
56+
57+
This is mostly for performance issues, it is hard to optimize in
58+
such scenario
59+
60+
1161

1262

docs/OCaml-call-JS.md

Lines changed: 44 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -75,67 +75,6 @@ improve the generated code.
7575
}
7676
```
7777

78-
## Native uncurried calling convention support
79-
80-
Note that OCaml's calling convention is curried by default, while JS
81-
does not have native support. Curried and uncurried functions can be
82-
told from type signatures.
83-
84-
For example
85-
86-
```ocaml
87-
val f : int -> string -> int
88-
val f_uncurry : int * string -> int [@uncurry]
89-
```
90-
91-
92-
93-
- How BuckleScript compiles function application
94-
95-
To apply a function, you can do this
96-
97-
```ocaml
98-
f 3 "x"
99-
f_uncurry #@ (3,"x")
100-
```
101-
For uncurried function applicaton, BuckleScript is guaranteed to
102-
compile it in the same way as JS code
103-
104-
```js
105-
f_uncurry(3,"x")
106-
```
107-
108-
However, for curried function application, it depends on how compiler
109-
optimizations goes, for most cases, when the compiler see the
110-
definition of `f`, it will compile it in the most efficient way, i.e,
111-
JS full aplication, if the compiler can not see the definition of `f`,
112-
it will do a runtime dispath, so there are two possible outputs:
113-
114-
```js
115-
Curry._2(f, 3, "x") // compiler fails to optimize
116-
f(3, "x") // compiler optimized correctly
117-
```
118-
Both are correct code, but the second one is more efficient.
119-
120-
- How BuckleScript handles function definition
121-
122-
```ocaml
123-
let f = fun a b -> a + string_of_int b
124-
let f_uncurry = fun %uncurry a b -> a + string_of_int b
125-
```
126-
127-
- When is uncurried function recommended
128-
129-
1. For FFI to JS functions, all object methods are *strongly recommended*
130-
to type it as uncurried function
131-
132-
133-
134-
2. When function is passed as a callback
135-
136-
This is mostly for performance issues, it is hard to optimize in
137-
such scenario
138-
13978

14079

14180

@@ -230,33 +169,6 @@ gives it a type and customized attributes
230169
end
231170
```
232171

233-
* `bs.obj`
234-
235-
This attribute helps create JavaScript object literal
236-
237-
A simple example:
238-
239-
```OCaml
240-
external make_config : hi:int -> lo:int -> unit -> t [@@bs.obj]
241-
let v = make_config ~hi:2 ~lo:3
242-
```
243-
will be compiled as
244-
245-
```js
246-
let v = { hi:2, lo:3}
247-
```
248-
You can use optional as well
249-
250-
```ocaml
251-
external make_config : hi:int -> ?lo:int -> unit -> t = "" [@@bs.obj]
252-
let u = make_config ~hi:3 ()
253-
let v = make_config ~hi:3 ~lo:2 ()
254-
```
255-
Will generate
256-
```js
257-
let u = {hi : 3}
258-
let v = {hi : 3 , lo: 2}
259-
```
260172

261173
* `bs.module`
262174

@@ -354,32 +266,60 @@ is inferred as type
354266
val f : < hi : ('a * 'b -> 'c [@uncurry] ; .. > Js.t -> 'a -> 'b -> 'c
355267
```
356268

357-
- Create JS object
269+
- `bs.obj`
270+
271+
This attribute helps create JavaScript object literal
358272

359273
```ocaml
360-
let a = f ({ hi = fun %uncurry (x,y) -> x + y}[@bs.obj]) 1 2
361-
let b = f ({ hi = fun %uncurry (x,y) -> x +. y}[@bs.obj]) 1. 2.
362-
```
274+
let a = f ({ hi = fun %uncurry (x,y) -> x + y}[@bs.obj]) 1 2
275+
let b = f ({ hi = fun %uncurry (x,y) -> x +. y}[@bs.obj]) 1. 2.
276+
```
363277

364-
Generated code is like below
278+
Generated code is like below
365279

366280

367-
```js
368-
function f(x, a, b) {
369-
return x.hi(a, b);
370-
}
281+
```js
282+
function f(x, a, b) {
283+
return x.hi(a, b);
284+
}
371285

372-
var a = f({
286+
var a = f({
373287
"hi": function (x, y) {
374-
return x + y | 0;
288+
return x + y | 0;
375289
}
376290
}, 1, 2);
377291

378-
var b = f({
379-
"hi": function (x, y) {
380-
return x + y;
381-
}
292+
var b = f({
293+
"hi": function (x, y) {
294+
return x + y;
295+
}
382296
}, 1, 2);
383-
```
297+
```
298+
299+
`bs.obj` can also be used in external declarations, like as below:
300+
301+
```OCaml
302+
external make_config : hi:int -> lo:int -> unit -> t [@@bs.obj]
303+
let v = make_config ~hi:2 ~lo:3
304+
```
305+
will be compiled as
306+
307+
```js
308+
let v = { hi:2, lo:3}
309+
```
310+
You can use optional as well
311+
312+
```ocaml
313+
external make_config : hi:int -> ?lo:int -> unit -> t = "" [@@bs.obj]
314+
let u = make_config ~hi:3 ()
315+
let v = make_config ~hi:3 ~lo:2 ()
316+
```
317+
Will generate
318+
```js
319+
let u = {hi : 3}
320+
let v = {hi : 3 , lo: 2}
321+
```
322+
323+
384324

385325

docs/README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99

1010
* [How to adapt your build system](./How-to-adapt-your-build-system.md)
1111

12-
* [Extensions to OCaml Language](./Extensions-to-OCaml-Language.md)
13-
1412
* [Semantic differences from other backends](./Semantic-differences-from-other-backends.md)
1513

1614

docs/SUMMARY.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
* [About OCaml](https://ocaml.org/)
1313
* [Compiler options](./Compiler-options.md)
1414
* [How to adapt your build system](./How-to-adapt-your-build-system.md)
15-
* [Extensions to OCaml Language](./Extensions-to-OCaml-Language.md)
1615
* [Semantic differences from other backends](./Semantic-differences-from-other-backends.md)
1716
* [JavaScript target versions](./JavaScript-target-versions.md)
1817

@@ -21,10 +20,11 @@
2120
* [Compiler overview](./Compiler-overview.md)
2221

2322
* BuckleScript FFI
24-
* [Runtime representation](./Runtime-representation.md)
23+
2524
* [Curry and Uncurry functions](./Curry-and-Uncurry-functions.md)
2625
* [JS call OCaml](./JS-call-OCaml.md)
2726
* [OCaml call JS](./OCaml-call-JS.md)
27+
* [Runtime representation](./Runtime-representation.md)
2828
* [Experimental support of typescript](./Experimental-support-of-typescript.md)
2929
* [Unsupported IO primitives](./Unsupported-IO-primitives.md)
3030

docs/build-doc.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
set -e
33
# node process.js
44
# gitbook build
5-
cp -r _book/* $BUCKLESCRIPT_DOC
5+
# cp -r _book/* $BUCKLESCRIPT_DOC

docs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"scripts": {
3-
"build": "gitbook install && gitbook build",
3+
"build": "gitbook install && gitbook build && cp -r _book/* $BUCKLESCRIPT_DOC",
44
"watch": "gitbook install && gitbook serve"
55
},
66
"devDependencies": {

0 commit comments

Comments
 (0)