Skip to content

Commit e5fdb92

Browse files
committed
Refine language and punctuation in user-defined functions documentation for clarity and consistency
1 parent 5aaf3b5 commit e5fdb92

6 files changed

Lines changed: 18 additions & 18 deletions

File tree

_mydocs/dax-internals/user-defined-functions/calculate-modifiers.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ published: true
55
order: /04
66
---
77

8-
Because UDFs expand as macros, a function body can contain expressions that are only syntactically valid in a specific calling position. In particular, a function can "return" a CALCULATE modifier provided the function is always called as a filter argument of `CALCULATE` or `CALCULATETABLE`.
8+
Because UDFs expand as macros, a function body can contain expressions that are only syntactically valid in a specific calling position. In particular, a function can "return" a CALCULATE modifier, provided the function is always called as a filter argument of `CALCULATE` or `CALCULATETABLE`.
99

1010
## Mechanism
1111

@@ -74,4 +74,4 @@ This pattern returns a scalar and has no calling-position restriction. The choic
7474

7575
## Practical use case
7676

77-
A common application is centralizing the list of **filter-keep columns**columns on a date table whose filters must be removed when computing a reference date, but preserved by time intelligence functions applied afterward. Placing the `REMOVEFILTERS` list in a function prevents it from being duplicated across many measures and simplifies maintenance when the column list changes.
77+
A common application is centralizing the list of **filter-keep columns**: columns on a date table whose filters must be removed when computing a reference date but preserved by time intelligence functions applied afterward. Placing the `REMOVEFILTERS` list in a function prevents it from being duplicated across many measures and simplifies maintenance when the column list changes.

_mydocs/dax-internals/user-defined-functions/index.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ next_reading: true
77
next_reading_title: false
88
---
99

10-
A DAX user-defined function (UDF) is a named, reusable expression declared with the `DEFINE FUNCTION` statement. UDFs are not subroutines invoked on a call stack; they expand inline at the call site as macros. The function body is substituted wherever the function is called, which means that expressions only valid in certain positions such as CALCULATE modifiers can be encapsulated inside a function and remain valid after expansion.
10+
A DAX user-defined function (UDF) is a named, reusable expression declared with the `DEFINE FUNCTION` statement. UDFs are not subroutines invoked on a call stack; they expand inline at the call site as macros. The function body is substituted wherever the function is called, which means that expressions only valid in certain positions (such as CALCULATE modifiers) can be encapsulated inside a function and remain valid after expansion.
1111

1212
UDFs can be defined at query level inside a `DEFINE` block or stored in a semantic model and shared across all measures and calculated columns in that model.
1313

_mydocs/dax-internals/user-defined-functions/model-dependency.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ published: true
55
order: /05
66
---
77

8-
A UDF is **model-dependent** when its body references model objects directly tables, columns, measures, or calendars by name. It is **model-independent** when all such references arrive exclusively through parameters, making the function portable across semantic models without modification.
8+
A UDF is **model-dependent** when its body references model objects directly (tables, columns, measures, or calendars) by name. It is **model-independent** when all such references arrive exclusively through parameters, making the function portable across semantic models without modification.
99

1010
## Hidden dependencies
1111

_mydocs/dax-internals/user-defined-functions/optional-parameters.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Increment ( 10, 20 ) -- y is 20; returns 30
3535

3636
### Skipping a middle parameter
3737

38-
To skip an optional parameter that is not the last one, write an **empty position** a comma with no value before it:
38+
To skip an optional parameter that is not the last one, write an **empty position**: a comma with no value before it:
3939

4040
```dax
4141
IncrementLimit ( 5, , 20 ) -- y uses its default; limit is 20
@@ -45,7 +45,7 @@ IncrementLimit ( 5, , 20 ) -- y uses its default; limit is 20
4545

4646
Optional parameters can appear in any position in the signature; required parameters can follow optional ones. Callers can always reach a required parameter by leaving an empty position for each optional parameter before it (`MyFunc ( 1, , 3 )` omits the second argument).
4747

48-
The minimum number of arguments a caller must supply the function's arity is determined by the **position of the rightmost required parameter**. If a function has three parameters and only the second is optional, callers must still supply at least three arguments: there is no way to omit the third, because it is required and comes last.
48+
The minimum number of arguments a caller must supply (the function's arity) is determined by the **position of the rightmost required parameter**. If a function has three parameters and only the second is optional, callers must still supply at least three arguments: there is no way to omit the third, because it is required and comes last.
4949

5050
The recommended practice is: **once a parameter is optional, all following parameters should also be optional.** Placing a required parameter after an optional one forces callers to write empty positions just to reach it, which is harder to read and easy to get wrong.
5151

@@ -80,7 +80,7 @@ Like the function expression body, a default expression inherits the **filter co
8080

8181
### Scope
8282

83-
A default expression can only reference names columns, tables, measures, variables, functions that are **visible at the point where the UDF is defined**, not where it is called. It cannot reference another parameter of the same function.
83+
A default expression can only reference names (columns, tables, measures, variables, functions) that are **visible at the point where the UDF is defined**, not where it is called. It cannot reference another parameter of the same function.
8484

8585
### Type
8686

_mydocs/dax-internals/user-defined-functions/parameter-types.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,20 @@ FUNCTION F = ( a : VAL, b : EXPR ) => ...
8686

8787
Type checking and coercion apply differently depending on the parameter category:
8888

89-
**Scalar subtypes** (`INT64`, `DECIMAL`, `DOUBLE`, etc.) do not reject incompatible arguments they coerce them. Each argument is independently converted to the declared type before the function body runs. No error is raised; see the coercion note under *Scalar subtypes* above.
89+
**Scalar subtypes** (`INT64`, `DECIMAL`, `DOUBLE`, etc.) do not reject incompatible arguments; they coerce them. Each argument is independently converted to the declared type before the function body runs. No error is raised; see the coercion note under *Scalar subtypes* above.
9090

9191
**Reference types** (`MEASUREREF`, `COLUMNREF`, `TABLEREF`, `CALENDARREF`) perform genuine type checking at call time. Passing an incompatible expression produces an error that identifies the expected and received types, for example: *"An invalid argument type was passed into parameter 'amountMeasure' of the user-defined function. Expected 'MEASUREREF' but got 'SCALAR'."* There is a known limitation for `COLUMNREF`: when a column reference is invalid, the internal syntax error from the function body surfaces before any custom validation error the function author may have written.
9292

93-
**`ANYREF`** performs no type checking. An incompatible argument may produce confusing errors deep inside the function body or, in the worst case, incorrect results with no error at all. Functions using `ANYREF` must handle the general case defensivelyfor example, wrapping every reference to the parameter in `CALCULATE` to guarantee context transition regardless of what was passed.
93+
**`ANYREF`** performs no type checking. An incompatible argument may produce confusing errors deep inside the function body or, in the worst case, incorrect results with no error at all. Functions using `ANYREF` must handle the general case defensively, for example by wrapping every reference to the parameter in `CALCULATE` to guarantee context transition regardless of what was passed.
9494

9595
## Introspection functions
9696

9797
Two functions are available for use inside a function body with `COLUMNREF` or `TABLEREF` parameters:
9898

99-
- **`TABLEOF ( columnRef )`** returns the table in which the referenced column is defined.
100-
- **`NAMEOF ( columnRef )`** returns the column's fully qualified name as a string.
99+
- **`TABLEOF ( columnRef )`**: returns the table in which the referenced column is defined.
100+
- **`NAMEOF ( columnRef )`**: returns the column's fully qualified name as a string.
101101

102-
These functions are intended to support runtime validationfor example, checking that two `COLUMNREF` parameters belong to the same table:
102+
These functions are intended to support runtime validation, for example checking that two `COLUMNREF` parameters belong to the same table:
103103

104104
```dax
105105
IF (

_mydocs/dax-internals/user-defined-functions/syntax.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,22 +40,22 @@ Function names use **Pascal case** to distinguish user-defined functions from bu
4040

4141
UDFs can be defined in two places:
4242

43-
- **Query level** inside the `DEFINE` block of a DAX query. The function is visible only within that query.
44-
- **Model level** stored as a named object in a semantic model. The function is visible from any measure, calculated column, or calculated table in that model, and from DAX queries run against it.
43+
- **Query level**: inside the `DEFINE` block of a DAX query. The function is visible only within that query.
44+
- **Model level**: stored as a named object in a semantic model. The function is visible from any measure, calculated column, or calculated table in that model, and from DAX queries run against it.
4545

4646
## Return type
4747

4848
A function can return:
4949

50-
- A **scalar value** usable anywhere a scalar expression is valid.
51-
- A **table** usable anywhere a table expression is valid.
52-
- A **CALCULATE modifier** (e.g., `REMOVEFILTERS`) only valid as a filter argument inside `CALCULATE` or `CALCULATETABLE`. This special case is possible because UDFs expand as macros; see [Returning CALCULATE modifiers](calculate-modifiers.md).
50+
- A **scalar value**: usable anywhere a scalar expression is valid.
51+
- A **table**: usable anywhere a table expression is valid.
52+
- A **CALCULATE modifier** (e.g., `REMOVEFILTERS`): only valid as a filter argument inside `CALCULATE` or `CALCULATETABLE`. This special case is possible because UDFs expand as macros; see [Returning CALCULATE modifiers](calculate-modifiers.md).
5353

5454
## Macro-expansion semantics
5555

5656
UDFs are not subroutines. There is no separate call stack or isolated execution context. When a UDF is called, its body is substituted inline at the call site, with each argument replacing its corresponding parameter according to the parameter's passing mode. The result is semantically identical to having written the substituted expression directly at the call site.
5757

58-
A consequence is that the function body may contain language constructs such as CALCULATE modifiers that are only syntactically valid in certain positions, provided the function is always called from a position where those constructs are valid.
58+
A consequence is that the function body may contain language constructs (such as CALCULATE modifiers) that are only syntactically valid in certain positions, provided the function is always called from a position where those constructs are valid.
5959

6060
## Limitations
6161

0 commit comments

Comments
 (0)