Une valeur est une donnée produite par l’évaluation d’une expression. Cette section décrit les genres de valeurs dans le langage M. Chaque genre de valeur est associé à une syntaxe littérale, un ensemble de valeurs qui sont de ce genre, un ensemble d’opérateurs définis sur cet ensemble de valeurs et un type intrinsèque attribué aux valeurs nouvellement construites.
Genre
Littéral
Null
null
Opérateurs logiques
truefalse
Nombre
01-11.52.3e-5
Time
#time(09,15,00)
Date
#date(2013,02,26)
DateTime
#datetime(2013,02,26, 09,15,00)
DateTimeZone
#datetimezone(2013,02,26, 09,15,00, 09,00)
Durée
#duration(0,1,30,0)
Texte
"hello"
Binaire
#binary("AQID")
Liste
{1, 2, 3}
Enregistrement
[ A = 1, B = 2 ]
Table
#table({"X","Y"},{{0,1},{1,0}})
Fonction
(x) => x + 1
Type
type { number }type table [ A = any, B = text ]
Les sections suivantes traitent de chaque genre de valeur en détail. Les types et les attributions de type sont définis de manière formelle dans Types. Les valeurs de fonction sont définies dans Fonctions. Les sections suivantes listent les opérateurs définis pour chaque genre de valeur et donnent des exemples. La définition complète de la sémantique d’opérateur suit dans Opérateurs.
Null
Une valeur Null est utilisée pour représenter l’absence de valeur ou une valeur à l’état indéterminé ou inconnu. Une valeur Null est écrite à l’aide du littéral null. Les opérateurs suivants sont définis pour les valeurs Null :
Opérateur
Résultat
x > y
Supérieur à
x >= y
Supérieur ou égal à
x < y
Inférieur(e) à
x <= y
Inférieur ou égal à
x = y
Égal à
x <> y
Différent de
x ?? y
Coalesce
Le type natif de la valeur null est le type intrinsèque null.
Logical
Une valeur logique est utilisée pour les opérations booléennes ; elle a la valeur true ou false. Une valeur logique est écrite à l’aide des littéraux true et false. Les opérateurs suivants sont définis pour les valeurs logiques :
Opérateur
Résultat
x > y
Supérieur à
x >= y
Supérieur ou égal à
x < y
Inférieur(e) à
x <= y
Inférieur ou égal à
x = y
Égal à
x <> y
Différent de
x or y
OR logique conditionnel
x ?? y
Coalesce
x and y
AND logique conditionnel
not x
NOT logique
Le type natif des deux valeurs logiques (true et false) est le type intrinsèque logical.
Nombre
Une valeur Nombre est utilisée pour les opérations numériques et arithmétiques. Voici quelques exemples de littéraux de nombres :
3.14 // Fractional number
-1.5 // Fractional number
1.0e3 // Fractional number with exponent
123 // Whole number
1e3 // Whole number with exponent
0xff // Whole number in hex (255)
Un nombre est représenté avec au moins la précision d’un double (mais peut conserver une plus grande précision). La représentation double est conforme à la norme IEEE double précision 64 bits pour l’arithmétique à virgule flottante binaire définie dans [IEEE 754-2008]. (La représentation double a une plage dynamique approximative comprise entre 5,0 x 10324 et 1,7 x 10308 avec une précision de 15-16 chiffres.)
Les valeurs spéciales suivantes sont également considérées comme des valeurs Nombre :
Infini positif (#infinity) et infini négatif (-#infinity). Les infinis sont produits par des opérations telles que la division d’un nombre différent de zéro par zéro. Par exemple, 1.0 / 0.0 produit l’infini positif et -1.0 / 0.0 produit l’infini négatif.
La valeur N’est pas un nombre (#nan), souvent abrégée NaN (Not-a-Number). Les valeurs NaN sont produites par des opérations à virgule flottante non valides, telles que la division de zéro par zéro.
Les opérations mathématiques binaires sont effectuées à l’aide d’une précision. La précision détermine le domaine vers lequel les opérandes sont arrondis et le domaine dans lequel l’opération est effectuée. En l’absence de précision explicitement spécifiée, ces opérations sont effectuées à l’aide de double précision.
Si le résultat d’une opération mathématique est trop petit pour le format de destination, le résultat de l’opération devient un zéro positif ou un zéro négatif.
Si le résultat d’une opération mathématique est trop grand pour le format de destination, le résultat de l’opération devient l’infini positif ou l’infini négatif.
Si une opération mathématique n’est pas valide, le résultat de l’opération devient NaN.
Si l’un ou les deux opérandes d’une opération à virgule flottante sont NaN, le résultat de l’opération devient NaN.
Les opérateurs suivants sont définis pour les valeurs Nombre :
Opérateur
Résultat
x > y
Supérieur à
x >= y
Supérieur ou égal à
x < y
Inférieur(e) à
x <= y
Inférieur ou égal à
x = y
Égal à
x <> y
Différent de
x + y
Somme
x - y
Différence
x * y
Produit
x / y
Quotient
x ?? y
Coalesce
+x
Plus unaire
-x
Négation
Le type natif des valeurs Nombre est le type intrinsèque number.
Heure
Une valeur Time stocke une représentation opaque de l’heure de la journée. Une heure est encodée sous la forme d’un nombre de cycles depuis minuit, qui compte le nombre de cycles de 100 nanosecondes qui se sont écoulés sur une horloge de 24 heures. Le nombre maximal de cycles depuis minuit correspond à 23:59:59,9999999 heures.
Bien qu’il n’existe aucune syntaxe littérale pour les heures, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs d’heure peuvent également être construites à l’aide de la fonction intrinsèque #time :
#time(hour, minute, second)
Les conditions suivantes doivent être remplies, sinon une erreur avec le code de raison Expression.Error est générée :
0 ≤ hour ≤ 24
0 ≤ minute ≤ 59
0 ≤ seconde ≤ 59
De plus, si heure = 24, minute et seconde doivent être égales à zéro.
Les opérateurs suivants sont définis pour les valeurs Time :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
Les opérateurs suivants autorisent que l’un ou les deux opérandes soient une date :
Opérateur
Opérande gauche
Opérande droit
Signification
x + y
time
duration
Date décalée d’une durée
x + y
duration
time
Date décalée d’une durée
x - y
time
duration
Date décalée d’une durée négative
x - y
time
time
Durée entre dates
x & y
date
time
Datetime fusionné
Le type natif des valeurs Time est le type intrinsèque time.
Date
Une valeur Date stocke une représentation opaque d’un jour spécifique. Une date est encodée sous la forme d’un nombre de jours depuis l’époque, à partir du 1er janvier 0001 de l’ère commune sur le calendrier grégorien. Le nombre maximal de jours depuis l’époque est de 3652058, ce qui correspond au 31 décembre 9999.
Bien qu’il n’existe aucune syntaxe littérale pour les dates, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs de dates peuvent également être construites à l’aide de la fonction intrinsèque #date :
#date(year, month, day)
Les conditions suivantes doivent être remplies, sinon une erreur avec le code de raison Expression.Error est générée :
1 ≤ year ≤ 9999
1 ≤ month ≤ 12
1 ≤ day ≤ 31
En outre, le jour doit être valide pour le mois et l’année choisis.
Les opérateurs suivants sont définis pour les valeurs Date :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
Les opérateurs suivants autorisent que l’un ou les deux opérandes soient une date :
Opérateur
Opérande gauche
Opérande droit
Signification
x + y
date
duration
Date décalée d’une durée
x + y
duration
date
Date décalée d’une durée
x - y
date
duration
Date décalée d’une durée négative
x - y
date
date
Durée entre dates
x & y
date
time
Datetime fusionné
Le type natif des valeurs Date est le type intrinsèque date.
Date/Heure
Une valeur DateTime contient à la fois une date et une heure.
Bien qu’il n’existe aucune syntaxe littérale pour DateHeure, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs DateHeure peuvent également être construites à l’aide de la fonction intrinsèque #datetime :
#datetime(year, month, day, hour, minute, second)
Les conditions suivantes doivent être remplies, sinon une erreur avec le code de raison Expression.Error est générée : 1 ≤ year ≤ 9999
1 ≤ month ≤ 12
1 ≤ day ≤ 31
0 ≤ hour ≤ 23
0 ≤ minute ≤ 59
0 ≤ seconde ≤ 59
En outre, le jour doit être valide pour le mois et l’année choisis.
Les opérateurs suivants sont définis pour les valeurs DateTime :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
Les opérateurs suivants autorisent que l’un ou les deux opérandes soient une valeur DateTime :
Opérateur
Opérande gauche
Opérande droit
Signification
x + y
datetime
duration
Datetime décalé d’une durée
x + y
duration
datetime
Datetime décalé d’une durée
x - y
datetime
duration
Datetime décalé d’une durée négative
x - y
datetime
datetime
Durée entre datetimes
Le type natif des valeurs DateTime est le type intrinsèque datetime.
DateTimeZone
Une valeur DateTimeZone contient une valeur DateTime et un fuseau horaire. Un fuseau horaire est encodé sous la forme d’un nombre de minutes de décalage par rapport à l’heure UTC, qui compte le nombre de minutes desquelles la partie heure de la valeur DateTime doit être décalée par rapport au temps universel coordonné (UTC, Universal Coordinated Time). Le nombre minimal de minutes de décalage par rapport à l’heure UTC est -840, ce qui représente un décalage UTC de -14:00, ou quatorze heures antérieures à l’heure UTC. Le nombre maximal de minutes de décalage par rapport à l’heure UTC est 840, ce qui correspond à un décalage UTC de 14:00.
Bien qu’il n’existe aucune syntaxe littérale pour datetimezones, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs datetimezones peuvent également être construites à l’aide de la fonction intrinsèque #datetimezone :
En outre, le jour doit être valide pour le mois et l’année choisis et, si offset-hours = 14, alors offset-minutes <= 0 et, si offset-hours = -14, alors offset-minutes >= 0.
Les opérateurs suivants sont définis pour les valeurs DateTimeZone :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
Les opérateurs suivants autorisent que l’un ou les deux opérandes soient une valeur DateTimeZone :
Opérateur
Opérande gauche
Opérande droit
Signification
x + y
datetimezone
duration
Datetimezone décalé d’une durée
x + y
duration
datetimezone
Datetimezone décalé d’une durée
x - y
datetimezone
duration
Datetimezone décalé d’une durée négative
x - y
datetimezone
datetimezone
Durée entre datetimezones
Le type natif des valeurs DateTimeZone est le type intrinsèque datetimezone.
Durée
Une valeur Durée stocke une représentation opaque de la distance entre deux points sur une chronologie mesurée en cycles de 100 nanosecondes. La grandeur d’une durée peut être positive ou négative, les valeurs positives indiquant une progression vers l’avant dans le temps et les valeurs négatives indiquant une progression en arrière dans le temps. La valeur minimale qui peut être stockée dans une durée est de -9 223 372 036 854 775 808 cycles, soit 10 675 199 jours 2 heures 48 minutes 05,4775808 secondes en arrière dans le temps. La valeur maximale qui peut être stockée dans une durée est de 9 223 372 036 854 775 807 cycles, soit 10 675 199 jours 2 heures 48 minutes 05,4775807 secondes vers l’avant dans le temps.
Bien qu’il n’existe aucune syntaxe littérale pour les durées, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs de durée peuvent également être construites à l’aide de la fonction intrinsèque #duration :
Les opérateurs suivants sont définis sur les valeurs de durée :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
De plus, les opérateurs suivants autorisent que l’un ou les deux opérandes soient une valeur de durée :
Opérateur
Opérande gauche
Opérande droit
Signification
x + y
datetime
duration
Datetime décalé d’une durée
x + y
duration
datetime
Datetime décalé d’une durée
x + y
duration
duration
Somme de durées
x - y
datetime
duration
Datetime décalé d’une durée négative
x - y
datetime
datetime
Durée entre datetimes
x - y
duration
duration
Différence de durées
x * y
duration
number
N fois une durée
x * y
number
duration
N fois une durée
x / y
duration
number
Fraction d’une durée
Le type natif des valeurs de durée est le type intrinsèque duration.
Texte
Une valeur Texte représente une séquence de caractères Unicode. Les valeurs de texte ont une forme littérale conforme à la grammaire suivante :
_text-literal: " text-literal-charactersopt" text-literal-characters :
text-literal-character text-literal-charactersopt
text-literal-character :
single-text-character
character-escape-sequence
double-quote-escape-sequence
single-text-character :
Tout caractère sauf " (U+0022) ou # (U+0023) suivi de ( (U+0028) double-quote-escape-sequence: "" (U+0022, U+0022)
Voici un exemple de valeur Texte :
"ABC" // the text value ABC
Les opérateurs suivants sont définis pour les valeurs Texte :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x & y
Concaténation
x ?? y
Coalesce
Le type natif des valeurs de texte est le type intrinsèque text.
Binaire
Une valeur binaire représente une séquence d’octets.
Bien qu’il n’existe aucune syntaxe littérale pour les valeurs binaires, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les valeurs binaires peuvent également être construites à l’aide de la fonction intrinsèque #binary.
Voici un exemple de valeur binaire construite à partir d’une liste d’octets :
#binary( {0x00, 0x01, 0x02, 0x03} )
Les opérateurs suivants sont définis pour les valeurs binaires :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x >= y
Supérieur ou égal à
x > y
Supérieur à
x < y
Inférieur à
x <= y
Inférieur ou égal à
x ?? y
Coalesce
Le type natif des valeurs binaires est le type intrinsèque binary.
Liste
Une valeur Liste est une valeur qui produit une séquence de valeurs en cas d’énumération. Une valeur produite par une liste peut contenir n’importe quel genre de valeur, y compris une liste. Vous pouvez construire des listes à l’aide de la syntaxe d’initialisation comme suit :
Voici un exemple de list-expression qui définit une liste avec trois valeurs de texte : "A", "B" et "C".
{"A", "B", "C"}
La valeur "A" est le premier élément de la liste et la valeur "C" est le dernier élément de la liste.
Les éléments d’une liste ne sont pas évalués tant qu’ils ne sont pas sollicités.
Bien que les valeurs de liste construites à l’aide de la syntaxe de liste produisent des éléments dans l’ordre dans lequel elles apparaissent dans item-list, en général, les listes retournées à partir de fonctions de bibliothèque peuvent produire un ensemble différent ou un nombre différent de valeurs chaque fois qu’elles sont énumérées.
Pour inclure une séquence de nombres entiers dans une liste, vous pouvez utiliser la forme a..b :
{ 1, 5..9, 11 } // { 1, 5, 6, 7, 8, 9, 11 }
Le nombre d’éléments dans une liste, appelé list count, peut être déterminé à l’aide de la fonction List.Count.
Une liste peut effectivement avoir un nombre infini d’éléments ; la fonction List.Count pour ces listes n’est pas définie et peut générer une erreur ou ne pas se terminer.
Si une liste ne contient aucun élément, elle est appelée liste vide. Une liste vide est écrite sous la forme suivante :
{} // empty list
Les opérateurs suivants sont définis pour les listes :
Le type natif des valeurs de liste est le type intrinsèque list, qui spécifie un type d’élément any.
Enregistrement
Une valeur Enregistrement est une séquence ordonnée de champs. Un champ est constitué d’un nom de champ, qui est une valeur de texte qui identifie de façon unique le champ dans l’enregistrement, et d’une valeur de champ. La valeur de champ peut être n’importe quel genre de valeur, y compris un enregistrement. Les enregistrements peuvent être construits à l’aide de la syntaxe d’initialisation comme suit :
record-expression: [field-listopt] field-list :
champ
champ,de liste de champs
field :
expression de nom=de champ
field-name :
generalized-identifier
quoted-identifier
L’exemple suivant construit un enregistrement avec un champ nommé x avec la valeur 1, et un champ nommé y avec la valeur 2.
[ x = 1, y = 2 ]
L’exemple suivant construit un enregistrement avec un champ a nommé a avec une valeur d’enregistrement imbriquée. L’enregistrement imbriqué contient un champ nommé b avec la valeur 2.
[ a = [ b = 2 ] ]
Les comportements suivants s’appliquent lors de l’évaluation d’une expression d’enregistrement :
L’expression assignée à chaque nom de champ est utilisée pour déterminer la valeur du champ associé.
Si l’expression assignée à un nom de champ produit une valeur lors de l’évaluation, cette valeur devient la valeur du champ de l’enregistrement résultant.
Si l’expression assignée à un nom de champ génère une erreur quand elle est évaluée, le fait qu’une erreur ait été générée est enregistré avec le champ, en plus de la valeur d’erreur générée. L’accès ultérieur à ce champ provoquera la nouvelle génération d’une erreur avec la valeur d’erreur enregistrée.
L’expression est évaluée dans un environnement tel que l’environnement parent uniquement avec des variables fusionnées qui correspondent à la valeur de chaque champ de l’enregistrement, à l’exception de celui qui est initialisé.
Une valeur dans un enregistrement n’est pas évaluée tant que le champ correspondant n’est pas sollicité.
Une valeur dans un enregistrement est évaluée au plus une fois.
Le résultat de l’expression est une valeur d’enregistrement avec un enregistrement de métadonnées vide.
L’ordre des champs dans l’enregistrement est défini par l’ordre dans lequel ils apparaissent dans record-initializer-expression.
Chaque nom de champ spécifié doit être unique dans l’enregistrement, sinon il s’agit d’une erreur. Les noms sont comparés à l’aide d’une comparaison ordinale.
[ x = 1, x = 2 ] // error: field names must be unique
[ X = 1, x = 2 ] // OK
Un enregistrement sans champ est appelé enregistrement vide et écrit comme suit :
[] // empty record
Bien que l’ordre des champs d’un enregistrement ne soit pas significatif lors de l’accès à un champ ou de la comparaison de deux enregistrements, il est significatif dans d’autres contextes, par exemple quand les champs d’un enregistrement sont énumérés.
Les deux mêmes enregistrements produisent des résultats différents quand les champs sont obtenus :
Record.FieldNames([ x = 1, y = 2 ]) // [ "x", "y" ]
Record.FieldNames([ y = 1, x = 2 ]) // [ "y", "x" ]
Le nombre de champs dans un enregistrement peut être déterminé à l’aide de la fonction Record.FieldCount. Par exemple :
Record.FieldCount([ x = 1, y = 2 }) // 2
Record.FieldCount([]) // 0
Outre l’utilisation de la syntaxe d’initialisation d’enregistrement [ ], les enregistrements peuvent être construits à partir d’une liste de valeurs, et d’une liste de noms de champs ou un type d’enregistrement. Par exemple :
Record.FromList({1, 2}, {"a", "b"})
Ce qui équivaut à :
[ a = 1, b = 2 ]
Les opérateurs suivants sont définis pour les valeurs d’enregistrement :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x & y
Fusionner
x ?? y
Coalesce
Les exemples suivants illustrent l’utilisation des opérateurs ci-dessus. Notez que la fusion d’enregistrements utilise les champs de l’opérande droit pour remplacer les champs de l’opérande gauche dans le cas où les noms de champs se chevauchent.
[ a = 1, b = 2 ] & [ c = 3 ] // [ a = 1, b = 2, c = 3 ]
[ a = 1, b = 2 ] & [ a = 3 ] // [ a = 3, b = 2 ]
[ a = 1, b = 2 ] = [ b = 2, a = 1 ] // true
[ a = 1, b = 2, c = 3 ] <> [ a = 1, b = 2 ] // true
Le type natif des valeurs d’enregistrement est le type intrinsèque record, qui spécifie une liste de champs vide ouverte.
Table
Une valeur Table est une séquence ordonnée de lignes. Une ligne est une séquence ordonnée de valeurs de colonne. Le type de la table détermine la longueur de toutes les lignes de la table, les noms des colonnes de la table, les types des colonnes de la table et la structure des clés de la table (le cas échéant).
Bien qu’il n’existe aucune syntaxe littérale pour les tables, plusieurs fonctions de bibliothèque standard sont fournies pour les construire. Les tables peuvent également être construites à l’aide de la fonction intrinsèque #table.
Voici un exemple de table construite à partir d’une liste de noms de colonnes et d’une liste de lignes. La table obtenue contient deux colonnes de type any et trois lignes.
#table({"x", "x^2"}, {{1,1}, {2,4}, {3,9}})
Vous pouvez aussi utiliser #table pour spécifier un type de table complet :
#table(
type table [Digit = number, Name = text],
{{1,"one"}, {2,"two"}, {3,"three"}}
)
Ici, la nouvelle valeur de table a un type de table qui spécifie des noms de colonnes et des types de colonnes.
Les opérateurs suivants sont définis pour les valeurs de table :
Opérateur
Résultat
x = y
Égal à
x <> y
Différent de
x & y
Concaténation
x ?? y
Coalesce
La concaténation de tables aligne les colonnes de même nom et insère la valeur null pour les colonnes qui apparaissent dans une seule des tables d’opérandes. L’exemple suivant illustre la concaténation de tables :
Le type natif des valeurs de table est un type de table personnalisé (dérivé du type intrinsèque table) qui liste les noms de colonnes, spécifie tous les types de colonnes comme étant « any », et n’a pas de clé. (Pour plus d’informations sur les types de tables, consultez Types de tables.)
Fonction
Une valeur Fonction est une valeur qui mappe un jeu d’arguments à une valeur unique. Les détails des valeurs de fonction sont décrits dans Fonctions.
Type
Une valeur Type est une valeur qui classifie d’autres valeurs. Les détails des valeurs de type sont décrits dans Types.
Vous souhaitez en savoir plus sur les types de tables de Business Central ? Dans ce module, vous allez découvrir les différents types de tables fonctionnelles et leurs caractéristiques spécifiques, comme les champs spéciaux, les propriétés et les pages liées.