Syntactic sugar for field accessing?

Is there any syntactic sugar for record field accessor?

I.e for

module T = struct
  type t = {
    value : int
  }
end

instead of doing

let value_list = List.map (fun t -> t.T.value)  t_list

we do similar to

let value_list = List.map (.T.value) t_list

If there is no such thing in OCaml, is it a good idea to add it to the language?

Not directly, but you can use ppx_fields_conv which allows you to write:

module T = struct
  type t = {
    value : int
  } [@@deriving fields]
end

and defines, amongst other things,

val value : t -> int

allowing:

let value_list = List.map T.value t_list

Related suggestions have been made before (e.g. ocaml/ocaml#9005)

4 Likes

that would be so nice to have, especially since currently (.ident) is an illegal form.

1 Like

In general the answer to ‘should there be xyz syntax sugar’, should be, ‘Think very carefully if saving a few characters is worth the added maintenance burden forever’ :slight_smile:

3 Likes

I don’t love it.

But it’s really hard to talk about syntaxic sugar without being subjective :slight_smile: . Would others actually use the sugar if it was added? I think we can get an idea by grepping the existing code published on opam:

  • There are 838 examples of lambdas used only to access a record field that could benefit from the sugar, for a codebase that contains over 500k usages of the fun keyword. It’s not nothing, but it’s not much.

  • But perhaps adding the sugar would encourage people to use it more! (do we really want that?) For context, the ( >>= ) operator is still used ~50k times while let* has only been adopted on ~10k lines. The new .%() operators aren’t really popular. It takes a lot of time and motivation to introduce new syntax.

I’m not saying that lesser used features are bad though! But that this specific sugar wouldn’t make a huge difference… in my opinion.

(These links are neither uptodate nor representative of all the OCaml code ever written… And the counts are approximate, you need to click the “More” button a few times for it to converge to a better answer: it’s only exact if you manage to hit the last page.)

2 Likes

This is one of the pluses of PPX extensions for this sort of thing: you shift the burden of maintenance from the compiler writer (and maintainer) to the user of the PPX extension (and, sure, the maintainers of the extension, if it’s popular enough).

2 Likes

Thanks! I will check the issue.

Some really nice data!

  • But I’d argue people writing this in different ways. i.e
(fun {value} -> value)

or named

let value t = value

or as dra27 point outed above, indirectly through [@@deriving fields].

  • And as you said, new sugar would effect how people write codes. i.e. let* actually significantly changed how I write Lwt. I found let* being very useful. I think people will use this more if easier to write.

  • Will this make a huge difference. Obviously no. This is only a syntactic sugar. I’d also argue this following syntactic sugar does not make a huge difference. But that is some of the most important syntactic sugar. I even found let* more useful for my use cases.

let my_fun = (fun var1 -> ...)
(* vs *)
let my_fun var1 = ...

I’ve recently found out that only ~0.3% of functions are partially-applied in a more partial-application-happy language (Haskell), here’s the source (the journal version has more code samples and reaches similar numbers), yet curried functions are the default in our stdlib, and significant work was put into ensuring curried function application is efficient in OCaml. I’d say it’s not always a matter of “how often X is used”, more like “how nice X is when you need it”.

Apologies for going off-topic, but the choice for using curried instead of n-ary or tupled functions in OCaml is argued in detail in the ZINC paper (see p13) and it has to do with “how nice it is”, but even more so with the fact that there is no clear agreement as to how n-ary functions should be integrated with ML-style typing discipline.

Cheers,
Nicolas

9 Likes

To go further, “supporting curried functions well” isn’t a mere question of syntax: it’s a question of efficiency. @nojb is right to reference the original ZINC paper (a lovely work).

But really, I don’t understand what the problem is: if you want support for .foo as a shorthand for (fun x -> x.foo, you can get it: just add a minor extension to the OCaml grammar in Camlp5 and you’re done.
But the thing is, it was widely agreed in the OCaml community that such hacking on the grammar of OCaml was a bad idea, and the result of that agreement was PPX.

Why not just add the syntax support and see if enough people actually use it? (which I kinda doubt, b/c ppx_fields_conv is already good enough).

[this is not a plug for Camlp5, but rather, pointing out that if you’re actually serious about wanting new syntax, you can get it without asking anybody else to do the work.]

Inspired by ocaml/ocaml#9005, I created a proposal for the exact syntax I mentioned here.

1 Like

Cool. If the mentioned nested record field access and setter syntax are actually implemented, then this becomes a pretty serviceable lens syntax.

I certainly have no dog in this fight (and since I maintain and use Camlp5, I’m a general fan of syntax extension) but I did wonder: how much of this could be achieved easily, by modular implicits? It seems like … a lot ?

Just curious, not making a point of any sort.

1 Like