Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Terminology? - nullable primitive type #203

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
24 changes: 12 additions & 12 deletions query-languages/m/m-spec-consolidated-grammar.md
Original file line number Diff line number Diff line change
Expand Up @@ -260,15 +260,13 @@ logical-and-expression:<br/>

_is-expression:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is-expression_ `is` _nullable-primitive-type<br/>
nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is-expression_ `is` _primitive-or-nullable-primitive-type_

#### As expression

_as-expression:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;equality-expression<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression_ `as` _nullable-primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression_ `as` _primitive-or-nullable-primitive-type_

#### Equality expression

Expand Down Expand Up @@ -448,15 +446,15 @@ fixed-parameter-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter_ `,` _fixed-parameter-list<br/>
parameter:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name primitive-parameter-type<sub>opt</sub><br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<sub>opt</sub><br/>
parameter-name:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;identifier<br/>
primitive-parameter-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-assertion<br/>
parameter-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-or-nullable-primitive-type-assertion<br/>
return-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-assertion<br/>
primitive-assertion:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _nullable-primitive-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-or-nullable-primitive-type-assertion<br/>
primitive-or-nullable-primitive-type-assertion:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _primitive-or-nullable-primitive-type<br/>
optional-parameter-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter_ `,` _optional-parameter-list<br/>
Expand Down Expand Up @@ -510,7 +508,9 @@ primary-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nullable-type<br/>
primitive-type:_ one of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`any anynonnull binary date datetime datetimezone duration function`<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`list logical none null number record table text time type`<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`list logical none null number record table text time type`<br/>
_primitive-or-nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_<br />
_record-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`[` _open-record-marker_ `]`<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`[` _field-specification-list<sub>opt</sub>_ `]`<br/>
Expand Down Expand Up @@ -548,7 +548,7 @@ optional-parameter-specification-list:<br/>
optional-parameter-specification:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`optional` _parameter-specification<br/>
parameter-specification:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<br/>
parameter-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertion<br/>
assertion:_<br/>
Expand Down
20 changes: 10 additions & 10 deletions query-languages/m/m-spec-functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ A _function_ is a value that represents a mapping from a set of argument values
Functions are written using a _function-expression_:

_function-expression:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`(` _parameter-list<sub>opt</sub>_ `)` _function-return-type<sub>opt</sub>_ `=>` _function-body<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`(` _parameter-list<sub>opt</sub>_ `)` _return-type<sub>opt</sub>_ `=>` _function-body<br/>
function-body:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expression<br/>
parameter-list:<br/>
Expand All @@ -26,24 +26,24 @@ parameter-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter-list<br/>
fixed-parameter-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter_ `,` _fixed-parameter-list<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter_ `,` _fixed-parameter-list<br/>
parameter:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<sub>opt</sub><br/>
parameter-name:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;identifier<br/>
parameter-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertion<br/>
function-return-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertion<br/>
assertion:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _nullable-primiitve-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-or-nullable-primitive-type-assertion<br/>
return-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-or-nullable-primitive-type-assertion<br/>
primitive-or-nullable-primitive-type-assertion:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _primitive-or-nullable-primitive-type<br/>
optional-parameter-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter_ `,` _optional-parameter-list<br/>
optional-parameter:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`optional` _parameter<br/>
nullable-primitve-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> _primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`optional` _parameter_<br />
_primitive-or-nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_

The following is an example of a function that requires exactly two values `x` and `y`, and produces the result of applying the `+` operator to those values. The `x` and `y` are _parameters_ that are part of the _parameter-list_ of the function, and the `x + y` is the _function-body_:

Expand Down
26 changes: 14 additions & 12 deletions query-languages/m/m-spec-operators.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: M Language Operators
description: Describes using operators in the Power Query M formula language
ms.topic: conceptual
ms.date: 12/12/2024
ms.date: 1/7/2025
ms.custom: "nonautomated-date"
ms.subservice: m-specification
---
Expand Down Expand Up @@ -133,12 +133,12 @@ The following table summarizes the M operators, listing the operator categories
<tr>
<td>Type assertion</td>
<td><em>x</em> <code>as</code> <em>y</em></td>
<td>Is compatible nullable-primitive type or error</td>
<td>Is compatible with primitive or nullable primitive type or error</td>
</tr>
<tr>
<td>Type conformance</td>
<td><em>x</em> <code>is</code> <em>y</em></td>
<td>Test if compatible nullable-primitive type</td>
<td>Test if compatible with primitive or nullable primitive type</td>
</tr>
<tr>
<td>Logical AND</td>
Expand Down Expand Up @@ -1253,21 +1253,21 @@ The type compatibility operator `x is y` is defined for the following types of

| X | Y | Result |
| --- | --- | --- |
| `type any` | _nullable-primitive-type_ | `type logical` |
| `type any` | _primitive-or-nullable-primitive-type_ | `type logical` |

The expression `x is y` returns `true` if the ascribed type of `x` is compatible with `y`, and returns `false` if the ascribed type of `x` is incompatible with `y`. `y` must be a _nullable-primitivetype_.
The expression `x is y` returns `true` if the ascribed type of `x` is compatible with `y`, and returns `false` if it is not compatible. `y` must be a _primitive-or-nullable-primitive-type_.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still some prose references to 'primtive-or-nullable-primitive-type' around here.


_is-expression:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is-expression_ `is` _nullable-primitive-type<br/>
nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;is-expression_ `is` _primitive-or-nullable-primitive-type<br />
primitive-or-nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_<br />

Type compatibility, as supported by the `is` operator, is a subset of [general type compatibility](m-spec-types.md) and is defined using the following rules:

* If `x` is null then it is compatible if `y` is the type `any`, the type `null`, or a nullable type.

* If `x` is non-null then if it is a compatible if the the primitive type of `x` is the same as `y`.
* If `x` is non-null then it is a compatible if the primitive type of `x` is the same as `y`.

The following holds when evaluating the expression `x is y`:

Expand All @@ -1279,13 +1279,15 @@ The type assertion operator `x as y` is defined for the following types of value

| X | Y | Result |
| --- | --- | --- |
| `type any` | _nullable-primitive-type_ | `type any` |
| `type any` | _primitive-or-nullable-primitive-type_ | `type any` |

The expression `x as y` asserts that the value `x` is compatible with `y` as per the `is` operator. If it is not compatible, an error is raised. `y` must be a _nullable-primitive-type_.
The expression `x as y` asserts that the value `x` is compatible with `y` as per the `is` operator. If it is not compatible, an error is raised. `y` must be a primitive type or a nullable primitive type.

_as-expression:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;equality-expression<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression_ `as` _nullable-primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;as-expression_ `as` _primitive-or-nullable-primitive-type<br />
primitive-or-nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_

The expression `x as y` is evaluated as follows:

Expand Down
38 changes: 20 additions & 18 deletions query-languages/m/m-spec-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: M Language types
description: Describes using types in the Power Query M formula language
ms.topic: conceptual
ms.date: 1/31/2024
ms.date: 1/3/2025
ms.custom: "nonautomated-date"
ms.subservice: m-specification
---
Expand All @@ -29,22 +29,24 @@ The set of _primitive types_ includes the types of primitive values, and a numbe

All types that are not members of the closed set of primitive types plus their nullable counterparts are collectively referred to as _custom types_. Custom types can be written using a `type-expression`:

_primitive-type:_ one of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`any anynonnull binary date datetime datetimezone duration function list logical`<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`none null number record table text time type`<br/>
_primitive-or-nullable-primitive-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`nullable`_<sub>opt</sub> primitive-type_<br />

All other types are collectively referred to as _custom types_. Custom types can be written using a `type-expression`:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this supposed to be here? Seems redundant with the previous prose paragraph.


_type-expression:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primary-expression_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`type` _primary-type<br/>
type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primary-expression<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primary-type<br/>
primary-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;primitive-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;record-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;function-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;table-type<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nullable-type<br/>
primitive-type:_ one of<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`any anynonnull binary date datetime datetimezone duration function list logical`<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`none null number record table text time type`
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nullable-type_

The _primitive-type_ names are _contextual keywords_ recognized only in a _type_ context. The use of parentheses in a _type_ context moves the grammar back to a regular expression context, requiring the use of the type keyword to move back into a type context. For example, to invoke a function in a _type_ context, parentheses can be used:

Expand Down Expand Up @@ -95,7 +97,7 @@ Value.Type( 1 as number ) // type number
{2} as text // error, type mismatch
```

Note that the `is` and `as` operators only accept nullable primitive types as their right operand. M does not provide means to check values for conformance to custom types.
Note that the `is` and `as` operators only accept a _primitive or nullable primitive type_ (i.e. a _non-custom type_) as their right operand. M does not provide means to check values for conformance to custom types.

A type `X` is _compatible_ with a type `Y` if and only if all values that conform to `X` also conform to `Y`. All types are compatible with type `any` and no types (but `none` itself) are compatible with type `none`. The following graph shows the compatibility relation. (Type compatibility is reflexive and transitive. It forms a lattice with type `any` as the top and type `none` as the bottom value.) The names of abstract types are set in _italics_.

Expand Down Expand Up @@ -210,28 +212,28 @@ A conforming value may contain field names not listed in the field specification

Any function value conforms to the primitive type `function`, which does not place any restrictions on the types of the function's formal parameters or the function's return value. A custom _function-type value_ is used to place type restrictions on the signatures of conformant function values.

_function-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`function (` _parameter-specification-list<sub>opt</sub>_ `)` _function-return-type<br/>
function-type:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`function (` _parameter-specification-list<sub>opt</sub>_ `)` _return-type<br/>
parameter-specification-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required-parameter-specification-list<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required-parameter-specification-list_ `,` _optional-parameter-specification-list<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter-specification-list<br/>
required-parameter-specification-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required-parameter-specification<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required-parameter-specification_ `,` _required-parameter-specification-list<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;required-parameter-specification_ `,` _required-parameter-specification-list<br/>
required-parameter-specification:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-specification<br/>
optional-parameter-specification-list:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter-specification<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter-specification_ `,` _optional-parameter-specification-list<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;optional-parameter-specification_ `,` _optional-parameter-specification-list<br/>
optional-parameter-specification:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`optional` _parameter-specification<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`optional` _parameter-specification<br/>
parameter-specification:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<br/>
function-return-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameter-name parameter-type<br/>
parameter-type:<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;assertion<br/>
assertion:_<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _nullable-primitive-type_
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`as` _type_
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this is correct, as variables, etc., can be used in an as clause in a function type definition.


The result of evaluating a _function-type_ is a type value whose base type is `function`.

Expand Down Expand Up @@ -364,7 +366,7 @@ Value.Type( Value.ReplaceType( {1}, type {number} )

Type equivalence is not defined in M. An M implementation may optionally choose to use its own rules to perform equality comparisons between type values. Comparing two type values for equality should evaluate to `true` if they are considered identical by the implementation, and `false` otherwise. In either case, the response returned must be consistent if the same two values are repeatedly compared. Note that within a given implementation, comparing some identical type values (such as `(type text) = (type text)`) may return `true`, while comparing others (such as `(type [a = text]) = (type [a = text])`) may not.

Compatibility between a given type and a nullable primitive type can be determined using the library function `Type.Is`, which accepts an arbitrary type value as its first and a nullable primitive type value as its second argument:
Compatibility between a given type and either a primitive type or a nullable primitive type can be determined using the library function `Type.Is`, which accepts an arbitrary type value as its first argument and a primitive or nullable primitive type value as its second argument:

```powerquery-m
Type.Is(type text, type nullable text) // true
Expand Down