Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
0873-Formatting-don-t-nest-code-inside-p-tag.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0873-Formatting-don-t-nest-code-inside-p-tag.patch of Package erlang
From 6d1152bcd592586bfc2d2cbee4b2a23e3a964378 Mon Sep 17 00:00:00 2001 From: Maxwell Elliot Heiber <mheiber@fb.com> Date: Wed, 22 Dec 2021 19:06:44 +0000 Subject: [PATCH 3/3] Formatting, don't nest code inside p tag --- system/doc/reference_manual/opaques.xml | 122 +++++++++++++++++++----- 1 file changed, 98 insertions(+), 24 deletions(-) diff --git a/system/doc/reference_manual/opaques.xml b/system/doc/reference_manual/opaques.xml index b14042cb19..8fa3bae3e5 100644 --- a/system/doc/reference_manual/opaques.xml +++ b/system/doc/reference_manual/opaques.xml @@ -1,10 +1,11 @@ -<?xml version="1.0" encoding="utf-8" ?> +<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE chapter SYSTEM "chapter.dtd"> <chapter> <header> <copyright> - <year>2021</year><year>2022</year> + <year>2021</year> + <year>2022</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -30,38 +31,111 @@ <file>opaques.xml</file> </header> - <section><title>Opaque Type Aliases</title> + <section> + <title>Opaque Type Aliases</title> <p>The main use case for opacity in Erlang is to hide the implementation of a data type, enabling evolving the API while minimizing the risk of breaking consumers. The runtime does not check opacity. Dialyzer provides some opacity-checking, but the rest is up to convention. </p> <p> -This document explains what Erlang opacity is (and the trade-offs involved) via the example of OTP's <c>sets:set()</c> data type. This type <em>was</em> defined in `sets` module like this: + This document explains what Erlang opacity is (and the trade-offs involved) via the example of OTP's + <c>sets:set()</c> + data type. This type + <em>was</em> + defined in `sets` module like this: + </p> + <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)}.</code> + <p>OTP 24 changed the definition to the following, in + <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url> + </p> + <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.</code> + <p> + And this change was safer and more backwards-compatible than if the type had been defined with + <c>-type</c> + instead of + <c>-opaque</c> + . Here's why: when a module defines an + <c>-opaque</c> + , the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition. </p> <p> - <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)}.</code> - OTP 24 changed the definition to the following, in <url href="https://github.com/erlang/otp/commit/e66941e8d7c47b973dff94c0308ea85a6be1958e">this commit</url>. - <code type="erl">-opaque set(Element) :: #set{segs :: segs(Element)} | #{Element => ?VALUE}.</code> -<p>And this change was safer and more backwards-compatible than if the type had been defined with <c>-type</c> instead of <c>-opaque</c>. Here's why: when a module defines an <c>-opaque</c>, the contract is that only the defining module should rely on the definition of the type: no other modules should rely on the definition.</p> -<p>This means that code that pattern-matched on <c>set</c> as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of <c>set()</c> changed. Before OTP 24, this code printed <c>ok</c>. In OTP 24 it may error:</p> + This means that code that pattern-matched on + <c>set</c> + as a record/tuple technically broke the contract, and opted in to being potentially broken when the definition of + <c>set()</c> + changed. Before OTP 24, this code printed + <c>ok</c> + . In OTP 24 it may error: + </p> <code type="erl"> case sets:new() of Set when is_tuple(Set) -> io:format("ok") end. </code> -</p> -<p><strong>When working with an opaque defined in another module, here are some recommendations:</strong></p> + <p> + <strong>When working with an opaque defined in another module, here are some recommendations:</strong> + </p> -<list type="bulleted"> -<item>Don't examine the underlying type using pattern-matching, guards, or functions that reveal the type, such as <c>tuple_size/1</c>.</item> -<item>Instead, use functions provided by the module for working with the type. For example, <c>sets</c> module provides <c>sets:new/0</c>, <c>sets:add/2</c>, <c>sets:is_element/2</c>, etc.</item> -<item><c>sets:set(a)</c> is a subtype of <c>sets:set(a | b)</c> and not the other way around. Generally, you can rely on the property that <c>the_opaque(T)</c> is a subtype of <c>the_opaque(U)</c> when T is a subtype of U.</item> -</list> -<p><strong>When defining your own opaques, here are some recommendations:</strong></p> -<list type="bulleted"> -<item>Since consumers are expected to not rely on the definition of the opaque type, you must provide functions for constructing and querying/deconstructing intances of your opaque type. For example, sets can be constructed with <c>sets:new/0</c>, <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with <c>sets:is_element/2</c>, and deconstructed with <c>sets:to_list/1</c>.</item> -<item>Don't define an opaque with a type variable in parameter position. This breaks the normal and expected behavior that (for example) <c>my_type(a)</c> is a subtype of <c>my_type(a | b)</c></item> -<item>Add <seeguide marker="typespec">specs</seeguide> to exported functions that use the opaque type</item> -</list> -<p>Note that opaques can be harder to work with for consumers, since the consumer is expected not to pattern-match and must instead use functions that the author of the opaque type provides to use instances of the type.</p> -<p>Also, opacity in Erlang is skin-deep: the runtime does not enforce opacity-checking. So now that sets are implemented in terms of maps, an <c>is_map</c> check on a set <em>will</em> pass. The opacity rules are only enforced by convention and by additional tooling such as Dialyzer. And this enforcement is not total: For example, determined consumer of <c>sets</c> can still do things that reveal the structure of the set, such as by printing, serializing, or using a set as <c>term()</c> and then inspecting via functions like <c>is_map</c> or <c>maps:get/2</c>. And Dialyzer must make some <url href="https://github.com/erlang/otp/issues/5118">approximations</url>. Opacity checking has limitations, but is still a vital tool in scalable Erlang development.</p></section> + <list type="bulleted"> + <item> + Don't examine the underlying type using pattern-matching, guards, or functions that reveal the type, such as + <c>tuple_size/1</c> + . + </item> + <item> + Instead, use functions provided by the module for working with the type. For example, + <c>sets</c> + module provides + <c>sets:new/0</c> + , + <c>sets:add/2</c> + , + <c>sets:is_element/2</c> + , etc. + </item> + <item> + <c>sets:set(a)</c> + is a subtype of + <c>sets:set(a | b)</c> + and not the other way around. Generally, you can rely on the property that + <c>the_opaque(T)</c> + is a subtype of + <c>the_opaque(U)</c> + when T is a subtype of U. + </item> + </list> + <p> + <strong>When defining your own opaques, here are some recommendations:</strong> + </p> + <list type="bulleted"> + <item> + Since consumers are expected to not rely on the definition of the opaque type, you must provide functions for constructing and querying/deconstructing intances of your opaque type. For example, sets can be constructed with + <c>sets:new/0</c>, <c>sets:from_list/1</c>, <c>sets:add/2</c>, queried with <c>sets:is_element/2</c>, and deconstructed with<c>sets:to_list/1</c>. + </item> + <item> + Don't define an opaque with a type variable in parameter position. This breaks the normal and expected behavior that (for example) + <c>my_type(a)</c> is a subtype of <c>my_type(a | b)</c> + </item> + <item> + Add <seeguide marker="typespec">specs</seeguide> to exported functions that use the opaque type + </item> + </list> + <p>Note that opaques can be harder to work with for consumers, since the consumer is expected not to pattern-match and must instead use functions that the author of the opaque type provides to use instances of the type.</p> + <p> + Also, opacity in Erlang is skin-deep: the runtime does not enforce opacity-checking. So now that sets are implemented in terms of maps, an + <c>is_map</c> + check on a set + <em>will</em> + pass. The opacity rules are only enforced by convention and by additional tooling such as Dialyzer. And this enforcement is not total: For example, determined consumer of + <c>sets</c> + can still do things that reveal the structure of the set, such as by printing, serializing, or using a set as + <c>term()</c> + and then inspecting via functions like + <c>is_map</c> + or + <c>maps:get/2</c> + . And Dialyzer must make some + <url href="https://github.com/erlang/otp/issues/5118">approximations</url> + . Opacity checking has limitations, but is still a vital tool in scalable Erlang development. + </p> + </section> </chapter> -- 2.31.1
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor