No `t_of_sexp` generated by ` [@@deriving sexp]`

According to RWO:

type t = { foo: int; bar: float } [@@deriving sexp] ;;
type t = { foo : int; bar : float; }
val t_of_sexp : Ppx_sexp_conv_lib.Sexp.t -> t = <fun>
val sexp_of_t : t -> Ppx_sexp_conv_lib.Sexp.t = <fun>
t_of_sexp (Sexp.of_string "((bar 35) (foo 3))") ;;
- : t = {foo = 3; bar = 35.}

I tried

# type t = { foo: int; bar: float } [@@deriving sexp] ;;
type t = { foo : Base.int; bar : Base.float; }

# t_of_sexp (Sexp.of_string "((bar 35) (foo 3))");;
Error: Unbound value t_of_sexp
Hint: Did you mean mat_of_sexp or int_of_sexp?

Try typing

# #require "ppx_jane";;

first.

Thank you Yaron.

I was wondering why defining a type with [@@deriving sexp] success even without #require "ppx_jane" first?

It make sense to me that if I could define a type with [@@deriving sexp] success, it should come along with t_of_sexp and so on.

By default, the compiler ignores annotations it doesn’t understand. (though once you turn on ppx_jane, you’ll get an error message for an unknown annotation.)

y

1 Like

You are right, there will an error if I just type:

#require "ppx_jane";;
# type person = {name: string}[@@deriving bin_io];;
Error: Unbound value bin_shape_string

In order to make it works ,I have to search bin_prot’s github repo, and find some hints there:

##require "bin_prot";;
# open Bin_prot.Std;;
# type person = {name: string}[@@deriving bin_io];;
Characters 0-47:
Warning 3: deprecated: module Base.Pervasives
[2016-09] this element comes from the stdlib distributed with OCaml.
Refering to the stdlib directly is discouraged by Base. You should either
use the equivalent functionality offered by Base, or if you really want to
refer to the stdlib, use Caml.Pervasives instead
type person = { name : string; }
val bin_shape_person : Bin_prot.Shape.t = <abstr>
val bin_size_person : person -> int = <fun>
val bin_write_person : Bin_prot.Common.buf -> pos:int -> person -> int = <fun>
val bin_writer_person : person Bin_prot.Type_class.writer0 =
  {Bin_prot.Type_class.size = <fun>; write = <fun>}
val bin_read_person :
  Bin_prot.Common.buf -> pos_ref:Bin_prot.Common.pos_ref -> person = <fun>
val bin_reader_person : person Bin_prot.Type_class.reader0 =
  {Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}
val bin_person : person Bin_prot.Type_class.t0 =
  {Bin_prot.Type_class.shape = <abstr>;
   writer = {Bin_prot.Type_class.size = <fun>; write = <fun>};
   reader = {Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}}

If you open Core_kernel, bin_io will work more smoothly. Base has built-in support for s-expression conversion, but not bin_io. Core_kernel supports both.

y

1 Like

Great thanks for your help, I like yours Lightweight versioning for lightweight protocols very much and want to dig a little deeper.

#require "core_kernel";;
#require "ppx_jane";;
# open Core_kernel;;
# type phone = |MOBILE |HOME |WORK [@@deriving bin_io, sexp];;
type phone = MOBILE | HOME | WORK
val bin_shape_phone : Bin_prot.Shape.t = <abstr>
val bin_size_phone : phone -> Bin_prot.Common.pos = <fun>
val bin_write_phone :
  Bin_prot.Common.buf ->
  pos:Bin_prot.Common.pos -> phone -> Bin_prot.Common.pos = <fun>
val bin_writer_phone : phone Bin_prot.Type_class.writer0 =
  {Core_kernel.Bin_prot.Type_class.size = <fun>; write = <fun>}
val bin_read_phone :
  Bin_prot.Common.buf -> pos_ref:Bin_prot.Common.pos_ref -> phone = <fun>
val bin_reader_phone : phone Bin_prot.Type_class.reader0 =
  {Core_kernel.Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}
val bin_phone : phone Bin_prot.Type_class.t0 =
  {Core_kernel.Bin_prot.Type_class.shape = <abstr>;
   writer = {Core_kernel.Bin_prot.Type_class.size = <fun>; write = <fun>};
   reader = {Core_kernel.Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}}
val phone_of_sexp : Sexplib0.Sexp.t -> phone = <fun>
val sexp_of_phone : phone -> Sexplib0.Sexp.t = <fun>

# type person = {name:string; id:int; email: string option; phonetype:phone} [@@deriving bin_io, sexp];;
Error: Unbound value Sexplib.Conv.record_check_extra_fields

Once again, there’re another Error: Unbound value. I’d tried to Google for that but found no answer.

Is there anything I missed here?

It looks like you’re missing sexplib, which you can get by writing #require “sexplib”. But that shouldn’t be necessary, and I don’t see this issue on my setup, so I’m a little confused.

1 Like

Well, my system is MacOS 10.13.4.

Now I use docker to start a ubuntu system, and it works in it:

#  type person = {name:string; id:int; email: string option; phonetype:phone} [@@deriving bin_io, sexp];;
type person = {
  name : string;
  id : int;
  email : string option;
  phonetype : phone;
}
val bin_shape_person : Bin_prot.Shape.t = <abstr>
val bin_size_person : person -> int = <fun>
val bin_write_person : Bin_prot.Common.buf -> pos:int -> person -> int = <fun>
val bin_writer_person : person Bin_prot.Type_class.writer0 =
  {Core_kernel.Bin_prot.Type_class.size = <fun>; write = <fun>}
val bin_read_person :
  Bin_prot.Common.buf -> pos_ref:Bin_prot.Common.pos_ref -> person = <fun>
val bin_reader_person : person Bin_prot.Type_class.reader0 =
  {Core_kernel.Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}
val bin_person : person Bin_prot.Type_class.t0 =
  {Core_kernel.Bin_prot.Type_class.shape = <abstr>;
   writer = {Core_kernel.Bin_prot.Type_class.size = <fun>; write = <fun>};
   reader = {Core_kernel.Bin_prot.Type_class.read = <fun>; vtag_read = <fun>}}
val person_of_sexp : Sexplib0.Sexp.t -> person = <fun>
val sexp_of_person : person -> Sexplib0.Sexp.t = <fun>

Thanks again.