Understanding Erlang documentation

Whenever I want to understand the input and output expected by a specific function, I refer to Erlang documentation. I am unable to find all the required data. Here are my questions. Please clarify.

  1. How to identify the mandatory inputs and optional inputs?
  2. Some example Types are Options = [option()] and Opts = [OptTuples]. What is the difference between them, one with a function bracket and one without? I think we need to give the inputs as a list of tuples in both cases.
  3. The function Erlang -- ct takes a huge input. Which inputs are mandatory?
  4. Erlang -- ct_netconfc says that “Common options are user, password and user_dir”. Input tuple user_dir is defined in ssh:client_option(). Where is the user, password defined?

Erlang -- ct_netconfc

open(Options) -> Result
Types
Options = [option()]
Result = {ok, handle()} | {error, error_reason()}

option() =
    {host | ssh, host()} |
    {port, inet:port_number()} |
    {timeout, timeout()} |
    {capability, string() | [string()]} |
    {receiver, term()} |
    ssh:client_option()
Options host and port specify the server endpoint to which to connect, and are passed directly to ssh:connect/4, as are arbitrary ssh options. Common options are user, password and user_dir.

Erlang -- ct

run_test(Opts) -> Result
Types
Opts = [OptTuples]
OptTuples = {dir, TestDirs} | {suite, Suites} | {group, Groups} | {testcase, Cases} | {spec, TestSpecs} | {join_specs, Bool} | {label, Label} | {config, CfgFiles} | {userconfig, UserConfig} |
1 Like

Hi,

here are some attempts of answering your questions (I am not a full-time erlang developer, so please see my answers as those of a fellow user of erlang).

  1. Technically, erlang has no optional parameters, all parameters must be supplied with values.
    As you have already seen, some functions have an Opts parameter, which most of the time is a list
    of options. Here you are free to select a set of options.
    Optional parameters could be implemented by providing functions with different arities, where the functions with lesser parameters call the implementation with all parameters and supply default values for the “omitted” parameters.

  2. option() and OptTuples should be declared on the respective documentation page.
    Each documentation page has a section Data Types, which contains all types used in that module.
    In my opinion, there is no big difference between OptTuple and option(), they both have the same semantic, just the specification differs a bit. I think that my be due to historical reasons, and not everybody using the same guidelines to documentation (or the guidelines changed over time).

  3. None. you can run
    ct:run_test([]).
    Depending on your configuration, you might need one or more options to configure the test run for your needs.
    I usually run rebar3 ct, mostly just as-is, sometimes with --suite, when I do TDD.

  4. I think the documentation is a bit lazy here. common_option() is defined in the ssh module. It seems that it can also be used in ct_netconfc. A link to ssh in the ct_netconf documentation would be helpful.

By the way, if you discover something to be improved, you can always bring this to discussion, either here or as a pull request on github. Everybody is grateful for improvements to the documentation.

3 Likes

I think you have to realise that there is a very significant difference between Options = [option()] and Opts = [OtpTuples]. The second one is explicitly a list of tuples while the first is a list of things of the type option() and there is nothing here stating that elements of the type option() are tuples, they can in fact be anything like booleans, numbers, atoms, … . You have to go look at the definition of the type option() to find out what tehy are.

4 Likes

Yes, that was a bit sloppy on my side. I looked up an example for each, and they were defined identically.
So I made a shortcut…
In general, anything could be hidden behind the type definitions.

By the way, OptTuples does not seem to be defined in the current sources, I could only find the term in the documentation files of ct.

1 Like

Not all documented types are generated from code (you found one such case).

When the types are defined from the code, though, you’ll find something like this in the XML:

    <datatype>
      <name name="ct_testname" n_vars="0"/>
      <desc><p>The name of the testcase function.</p></desc>
    </datatype>

where the actual type (an atom, in this case) is defined here.


As a bonus, Erlang/OTP does accept pull requests :wink: in which case you could also help improve the documentation-from-code.

3 Likes

If ct: prevent documentation errors and ease maintenance by paulo-ferraz-oliveira · Pull Request #6420 · erlang/otp · GitHub gets accepted, we’ll have ct spec.s (functions and types) generated from the code. (this also surfaced some potential issues that I’ve since fixed)

1 Like

Thanks Robert, for the clarification. I am fortunate to interact with the creator of Erlang.

1 Like

Thanks Dieter for a detailed response. I want to rephrase my question 1 & 3 as “In the case of a list of tuples, how to identify the mandatory and optional tuples/options?”.

As you clarified, depending on my configuration, I need to pass on one or more options. Is that right?

1 Like

This is the same as Function overloading used in OO languages such as Java, C++.

I found the answer myself by traversing through the Type definition. user, password are defined in authentication_client_options

1 Like

Thanks Paulo. If not defined in code, where else does the documentation generation get the data from? Excuse me if my question is basic, as I am new to Erlang.

After a quick googling, I understood as follows. Correct me if I am wrong.

  1. Developer shall add documentation input while coding in .erl file as recommended in Types and Function Specification
  2. Using some tool, .xml will be generated (ex: ct_suite.xml)
  3. Finally, .html will be generated from the .xml.
  4. .html is the documentation file we refer (ex: ct_suite.html)
1 Like

yes, exactly.

1 Like

There are several ways of producing documentation for Erlang APIs in OTP there are 2 ways dominating:

  1. Write the doc for module m in a file m.xml according to an XML DTD called erlref (for Erlang reference manuals). From the m.xml there is .html, .pdf, and man pages and docchunks that can be generated. This is the way used for CommonTest.
  2. This is also handwritten doc in m.xml but with references to the source code in m.erl from which the -type and -spec information is fetched. So from m.xml and m.erl as input the same formats as above can be generated.

There is also the edoc way of writing documentation where the doc is written as comments inside the .erl file and from that the .html and docchunks can be generated.

But for OTP it is always the documentation that is the source of information for users. For example functions not documented are not officially supported and you should avoid using them. The same goes for function parameters for example the list of options. Only the documented options should be used.

4 Likes

Thanks Kenneth for a detailed response.

I understood from your response that - In Erlang, documentation inputs are specified in two places; mainly in m.xml, and also in m.erl as -type and -spec.

I am coming from Java world, wherein the documentation input is specified in a single place, that is in the code.

Each approach has its own pros and cons.

1 Like

… which you may document using edoc:

-spec foo() -> ok
%% @doc Call foo with default options.
%% @equiv foo([{bar, 42}])
2 Likes