2

In Lua there's a short notation for sending the "self" to a function, so a.withdraw(a, 100.0) can be written a:withdraw(100.0). Shouldn't it be possible to do a similar extension to OCaml, letting List.length l be written l::length and List.map (fun e -> e + 1) l written like l::map (fun e -> e + 1)?

Olle Härstedt
  • 3,799
  • 1
  • 24
  • 57
  • I think you are confusing *methods* and *functions*. See some of the questions about what the difference is like this: http://stackoverflow.com/questions/155609/what-is-the-difference-between-a-method-and-a-function. – Dave L. Oct 19 '13 at 04:39

4 Answers4

4

This was asked by Fabrice Le Fessant on the ocaml bugtracker a few months ago: PR#6012 object-like notation for module functions, inspired by his work on the wxOCaml library (see thee design description in this PDF).

The feature request generated a discussion (go see the PR#6012 link for the discussion), but I think the consensus is that it's not such a good idea. People were not happy with adding a specific language feature to support making module programming similar to object programming.

I think you could break down this idea into smaller pieces that are each interesting in isolation, but would need much more work to be well-understood enough to be intregrated in a mature programming language. You're hinting at some form of code inference, for example.

gasche
  • 31,259
  • 3
  • 78
  • 100
  • What do you mean by “dding”? – Pascal Cuoq Oct 19 '13 at 08:41
  • @PascalCuoq, typo for "adding", I suppose. – Andreas Rossberg Oct 19 '13 at 08:55
  • I would be happy with the pure syntactic version using camlp4, but I guess there is no such extension written? – Olle Härstedt Oct 19 '13 at 14:56
  • I don't know what you mean, as the example you demonstrated clearly couldn't be done with camlp4 only. How would you guess from the identifier `l` that `l:map` is in fact `List.map`? – gasche Oct 19 '13 at 17:04
  • You could use convention, maybe? `l` has type `list`, so look for function `map` in `List` module (capital first letter)? You have reflection in camlp4, no? Of course, this would clash with the convention to use `t` as main type in all modules. You could also introduce short notation with `let f (l -> List)` as garrigue suggests (in your link). – Olle Härstedt Oct 19 '13 at 17:27
  • camlp4 has no introspection on types, no. But the `(l -> List)` sugar suggested by Jacques could work. I think it has limited applicability (especially if compared to what you write after `module L = List`), but if you really think that it could have a positive effect on your personal OCaml practice, I could write the camlp4 extension for that. – gasche Oct 19 '13 at 18:01
  • I don't know, is it much work? I'd prefer the Lua-like syntax instead of `-->`. I mailed Le Fessant earlier, maybe he's intereseted. Off-topic, but how did they make `dyntype` if there's no introspection in camlp4? – Olle Härstedt Oct 19 '13 at 19:59
  • It's rather easy -- I'd say less than one hour of work if the syntax you want is well-defined and not tricky precedence-wise. But my guess would be that in practice you would find it painful to integrate with your workflow, annoying when sharing sources with other people, and not worth the gain. Dyntype, and all type-conv extensions, work by inspecting the *syntax* of algebraic type definitions and generating code immediately after those. – gasche Oct 19 '13 at 20:04
  • Just one more question: In `List.length`, `l` is the _first_ argument, but in `List.map` it is the second (and third in `List.fold_left` IIRC). Is there a solution to this, making `l:map` and `l:length` work as is? – Olle Härstedt Oct 19 '13 at 21:51
  • Not "as is", but you could pick an API convention to solve this, such as always making `l` the first non-labelled argument -- this works as-is with `ListLabels`. – gasche Oct 19 '13 at 22:08
  • OK, Le Fessant had already made a syntax extension (in his link), but unfortunatley it bugs out when you use `when` in a match case. Do you have time to fix it? Or hint what is wrong? – Olle Härstedt Oct 24 '13 at 02:19
  • Sorry, missed you at IRC. Here's the link: https://github.com/OCamlPro/ocplib-wxOCaml/blob/wx-syntax/samples/wxSamples-syntax/pa_wx.ml – Olle Härstedt Oct 24 '13 at 20:52
2

List is an ocaml module not an ocaml object. When you are writing List.length you call the function length belonging to the module List (See module as namespace, or library, for a first intuition).

From the doc,

A primary motivation for modules is to package together related definitions (such as the definitions of a data type and associated operations over that type) and enforce a consistent naming scheme for these definitions. This avoids running out of names or accidentally confusing names.

Moreover for an object you need to create one (using new) before to use it (call the function f on it, for example, myobject # f),

An example, from the documentation here,

We now create a new point p, instance of the point class.

# let p = new point;;
val p : point = <obj>

We now invoke some methods to p:

# p#get_x;;
- : int = 0
zurgl
  • 1,930
  • 1
  • 14
  • 20
2

If you look in this syntax directory, you will find the camlp4 syntax extension that I wrote to do that in wxOCaml context (it is in branch "wx-syntax" of wxOCaml).

The current syntax is

 module x -> M in E

where you can use

 x->f

instead of

 M.f x

in the expression E. I think this latter syntax is actually nice, but I would advice to change the first one by:

 let module x -> M in E

to please the indenter. The syntax file "pa_wx.ml" is short and easy to modify, you can see the resulting code in "drawing.ml" at lines 563- for example.

Fabrice Le Fessant
  • 4,222
  • 23
  • 36
1

Not very elegantly, because neither OCaml values nor their type are owned by a module. Even if we knew the full type of an expression, we wouldn't know from which module the function should be taken by default.

In the example l->length standing for List.length l, the compiler would need to know that our thinking is that l belongs to module List (which doesn't even provide a type alias for the built-in type 'a list). Or maybe we mean Batteries.List.length.

As a result, a declaration saying "l uses module List" would be required.

Martin Jambon
  • 4,629
  • 2
  • 22
  • 28