Skip to content

Commit 2d8439c

Browse files
committed
Update docs
1 parent 9208c55 commit 2d8439c

2 files changed

Lines changed: 18 additions & 45 deletions

File tree

_docs_src/src/recursive.md

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,17 @@ class Bar:
1616

1717
`Foo` has a method that returns a `Bar` object, and `Bar` has a method that returns a `Foo` object.
1818

19-
While this works fine in Python, we have to be more explicit in OCaml to use recursive modules. Technically, `pyml_bindgen` doesn't handle recursive modules. But it is simple enough to edit the output by hand. Let's see.
19+
While this works fine in Python, we have to be more explicit in OCaml in these kinds of situations.
2020

21+
## Auto-generate bindings
2122

22-
## Value specs
23+
As of version `0.4.0-SNAPSHOT`, `pyml_bindgen` ships two helper scripts for dealing with this type of thing automatically: `gen_multi` and `combine_rec_modules`. Check out the [Recursive Modules](https://github.com/mooreryan/ocaml_python_bindgen/tree/main/examples/recursive_modules) example on GitHub for how to use them.
24+
25+
## Semi-manually generate bindings
26+
27+
The `pyml_bindgen` itself doesn't handle recursive modules. But it is simple enough to edit the output by hand. Let's see how.
28+
29+
### Value specs
2330

2431
Since there are two classes to bind, we will make two val spec files.
2532

@@ -35,7 +42,7 @@ val make_bar : unit -> Bar.t
3542
val make_foo : unit -> Foo.t
3643
```
3744

38-
## Run `pyml_bindgen`
45+
### Run `pyml_bindgen`
3946

4047
Now, run `pyml_bindgen` with some extra shell commands to make the output look nicer.
4148

@@ -49,7 +56,7 @@ pyml_bindgen bar_val_specs.txt silly Bar --caml-module Bar -r no_check \
4956
| ocamlformat --enable --name=a.ml - >> lib.ml
5057
```
5158

52-
## Fix the output
59+
### Fix the output
5360

5461
If you were to try and compile that code, you'd get a lot of errors including about unknown`Bar` module.
5562

@@ -61,61 +68,27 @@ Here is what the output should look like:
6168

6269
```ocaml
6370
module rec Foo : sig
64-
type t
6571
66-
val of_pyobject : Pytypes.pyobject -> t
72+
... sig ...
6773
68-
val to_pyobject : t -> Pytypes.pyobject
69-
70-
val make_bar : unit -> Bar.t
7174
end = struct
72-
let filter_opt l = List.filter_map Fun.id l
73-
74-
let import_module () = Py.Import.import_module "silly"
75-
76-
type t = Pytypes.pyobject
7775
78-
let of_pyobject pyo = pyo
76+
... impl ...
7977
80-
let to_pyobject x = x
81-
82-
let make_bar () =
83-
let class_ = Py.Module.get (import_module ()) "Foo" in
84-
let callable = Py.Object.find_attr_string class_ "make_bar" in
85-
let kwargs = filter_opt [] in
86-
Bar.of_pyobject
87-
@@ Py.Callable.to_function_with_keywords callable [||] kwargs
8878
end
8979
9080
and Bar : sig
91-
type t
92-
93-
val of_pyobject : Pytypes.pyobject -> t
9481
95-
val to_pyobject : t -> Pytypes.pyobject
82+
... sig ...
9683
97-
val make_foo : unit -> Foo.t
9884
end = struct
99-
let filter_opt l = List.filter_map Fun.id l
100-
101-
let import_module () = Py.Import.import_module "silly"
102-
103-
type t = Pytypes.pyobject
104-
105-
let of_pyobject pyo = pyo
10685
107-
let to_pyobject x = x
86+
... impl ...
10887
109-
let make_foo () =
110-
let class_ = Py.Module.get (import_module ()) "Bar" in
111-
let callable = Py.Object.find_attr_string class_ "make_foo" in
112-
let kwargs = filter_opt [] in
113-
Foo.of_pyobject
114-
@@ Py.Callable.to_function_with_keywords callable [||] kwargs
11588
end
11689
```
11790

118-
## Using the generated modules
91+
### Using the generated modules
11992

12093
You can use the generated modules as you would any others.
12194

@@ -130,4 +103,4 @@ let (_foo : Foo.t) = Bar.make_foo ()
130103

131104
## Wrap-up
132105

133-
You may come across cyclic classes when binding Python code. If you want to bind them in OCaml as it, you will need to use recursive module. For now, `pyml_bindgen` won't generate them for you automatically, but it is not *too* bad to change them by hand :)
106+
You may come across cyclic classes when binding Python code. If you want to bind them in OCaml as it, you will need to use recursive module. This page shows you how to do it semi-manually using `pyml_bindgen`. If you would like a more automatic way to do this, see the [Recursive Modules](https://github.com/mooreryan/ocaml_python_bindgen/tree/main/examples/recursive_modules) example on GitHub.

examples/recursive_modules/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,4 @@ class Human:
4040

4141
You can see that the `Cat` and `Human` classes make reference to one another. This can be a problem when writing OCaml bindings.
4242

43-
One solution is to use [recursive modules](https://ocaml.org/manual/recursivemodules.html). Rather than run `pyml_bindgen` separately for each class we want to bind, and then manually modify the results to make the modules recursive, this directory shows you how you can use the helper scripts `gen_multi` and `combine_rec_modules` to automate this task.
43+
One solution is to use [recursive modules](https://ocaml.org/manual/recursivemodules.html). Rather than run `pyml_bindgen` separately for each class we want to bind, and then manually [modify](https://mooreryan.github.io/ocaml_python_bindgen/recursive/) the results to make the modules recursive, this directory shows you how you can use the helper scripts `gen_multi` and `combine_rec_modules` to automate this task.

0 commit comments

Comments
 (0)