From 8fba65c59586910265ea17ec6b45ba2491a38384 Mon Sep 17 00:00:00 2001 From: arnaud-4d Date: Fri, 29 May 2026 17:22:27 +0200 Subject: [PATCH 1/5] first draft --- docs/Concepts/methods.md | 2 +- docs/Notes/updates.md | 10 ++ docs/language-legacy/Interruptions/defer.md | 134 ++++++++++++++++++++ docs/language-legacy/Interruptions/throw.md | 9 +- 4 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 docs/language-legacy/Interruptions/defer.md diff --git a/docs/Concepts/methods.md b/docs/Concepts/methods.md index 9083e73d5daeeb..8c7ec211e2217e 100644 --- a/docs/Concepts/methods.md +++ b/docs/Concepts/methods.md @@ -21,6 +21,6 @@ In the 4D Language, there are several categories of methods. The category depend |**Form method**|Automatic, when an event involves the form to which the method is attached|No|Property of a form. You can use a form method to manage data and objects, but it is generally simpler and more efficient to use an object method for these purposes.| |**Trigger** (aka *Table method*)|Automatic, each time that you manipulate the records of a table (Add, Delete and Modify)|No|Property of a table. Triggers are methods that can prevent "illegal" operations with the records of your database.| |**Database method**|Automatic, when a working session event occurs|Yes (predefined)|There are 16 database methods in 4D. | -|**Class**|Automatically called when an object of the class is instantiated or when a function of the class is executed on an object instance in any other methods or in a [database field](../Develop/field-properties.md#class).|yes (class functions)|A **Class** is used to declare and configure the class [constructor](./classes.md#class-constructor), [properties](./classes.md#property), and [functions](./classes.md#function) of objects. See [**Classes**](classes.md) | +|**Class**|Automatically called when an object of the class is instantiated or when a function of the class is executed on an object instance in any other methods or in a [database field](../Develop/field-properties.md#class).|yes (class functions)|A **Class** is used to declare and configure the class [constructor](./classes.md#class-constructor), [properties](./classes.md#property), and [functions](./classes.md#function) of objects. See [**Classes**](classes.md) and [**Function** class](../API/FunctionClass.md). | diff --git a/docs/Notes/updates.md b/docs/Notes/updates.md index 4dc9c84d0d049b..7298d1f6b03368 100644 --- a/docs/Notes/updates.md +++ b/docs/Notes/updates.md @@ -3,6 +3,16 @@ id: updates title: Release Notes --- +## 4D 21 R4 + +Read [**What’s new in 4D 21 R4**](https://blog.4d.com/whats-new-in-4d-21-r4/), the blog post that lists all new features and enhancements in 4D 21 R4. + +#### Highlights + +- New [`defer`](../commands/defer) command to declare some code to be always executed at method or function exit. + + + ## 4D 21 R3 Read [**What’s new in 4D 21 R3**](https://blog.4d.com/whats-new-in-4d-21-r3/), the blog post that lists all new features and enhancements in 4D 21 R3. diff --git a/docs/language-legacy/Interruptions/defer.md b/docs/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..097b2f16d30663 --- /dev/null +++ b/docs/language-legacy/Interruptions/defer.md @@ -0,0 +1,134 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| Parameter | Type | | Description | +| --- | --- | --- | --- | +| exitFormula | Expression | → | Expression to be executed at exit| +
+ + +
+
History + +|Release|Changes| +|---|---| +|21 R4|Created| + +
+
+ +## Description + +The `defer` command declares an *exitFormula* expression that will always be executed when the method or function exits, even if an error has been thrown or a `return` has been executed. Using a `defer` command allows you to ensure that a method or function ends correctly by executing completion code on exit. In addition, this command saves you from having to duplicate the same exit code for every return or catch block. + +:::tip Related blog post + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + +In *exitFormula*, you pass the expression that you want to be evaluated upon method or function exit, whatever the way it exited. Note however that: + +- if *exitFormula* contains another `defer` statement, an error is thrown, +- if *exitFormula* calls a `return` statement, it is ignored. + +The `defer` command can be called anywhere in the method or function code. You can insert as many `defer` expressions as you want in the code. During execution, all encountered *exitFormula* expressions are stacked. When the code execution stops, whatever the reason (normal flow, break, error, user abort, return...), all expressions in the "deferred stack" are popped and executed in LIFO (*Last In First Out)* order. For example: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// At exit, alerts will display "2" and then "1" +``` + +Behind the scenes, the command works as follows: every time a `defer` is called, 4D converts *exitFormula* into a formula and adds it to a collection associated with the method or function. When the method or function ends, all formulas stored in the collection are evaluated in the order they appear in the collection. + +As for all [formulas](../../commands/formula), if the *exitFormula* expression uses local variables, their current values are copied and stored in the formula object returned **when it is put in the *deferred stack***. When executed, the formula uses these copied values rather than the current values of the local variables. Note that the use of arrays as local variables is not supported. + + +Local variables and ORDA values at the expressio + +Thus, the *exitFormula* formula is evaluated with the following current values: + +- local variables and ORDA values at the expression deferring call (i.e. when the expression is put in the *deferred stack*), +- process and interprocess variables as well as database field values at the method or function end. + +If the *exitFormula* expression throws an error, it is automatically caught without any interruption and the execution flow continues as it runs with a [`Try`](../../Concepts/error-handling.md#tryexpression) expression. + + + +## Example 1 + +These examples illustrate the various supported *exitCode* expressions: + +```4d +// Method call +defer(aMethod) + +// Object function call +defer(myObject.aFunction(something)) + +// Singleton function call +defer(cs.aClass.me.aFunction(something)) + +// Singleton function call and if an error accors, another singleton function call (here for error management) +defer(cs.aClass.me.aFunction(something) || cs.errorManager.me.log(Last errors)) +``` + +## Example 2 + +You want to make sure an XML reference will be always properly released, to avoid potential memory leaks: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## Example 3 + +You want to make sure the activity monitoring stops at the end of the method: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## Example 4 + +You want to control your log generation: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` +streamline-your-clean-up-code-with-the-new-defer-command + +## See also + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## Properties + +| | | +| --- | --- | +| Command number | 1805 | +| Thread safe | no | + + + diff --git a/docs/language-legacy/Interruptions/throw.md b/docs/language-legacy/Interruptions/throw.md index 17dd63ec419ef0..45e5f8b70691db 100644 --- a/docs/language-legacy/Interruptions/throw.md +++ b/docs/language-legacy/Interruptions/throw.md @@ -38,7 +38,7 @@ Errors thrown using the **throw** command are managed by the 4D runtime as any n The command supports three syntaxes: -### **throw(errorCode{; description})** +### throw(errorCode{; description}) It specifies the error code and an optional description text, the error is thrown immediately. If no description is provided, it is filled with: @@ -46,7 +46,7 @@ If no description is provided, it is filled with: * Error code errorCode: (host) in the host application * Error code errorCode: (C00x) in a component -### **throw(errorObj)** +### throw(errorObj) *errorObj* object allows for more detailed error information and control over error handling. It can contain the following properties, as well as any custom property that you can refer to using placeholders within the **message** property. @@ -61,7 +61,7 @@ When you use this syntax, the *errorObj* object is returned in [Last errors](../ **Note:** It is possible to call the command several times in the same project method to generate several errors. You can use the deferred option to send all errors at once. -### **throw** +### throw It throws all current errors in **deferred mode**, meaning they will be added to a stack and handled when the calling method returns. This is typically done from within an [ON ERR CALL](../commands/on-err-call) callback. @@ -111,7 +111,8 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## See also [ASSERT](../commands/assert) -[Last errors](../commands/last-errors) +[defer](../commands/defer) +[Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call) ## Properties From 999fd45a06e155fa671c625445f7283a648deab1 Mon Sep 17 00:00:00 2001 From: arnaud-4d Date: Fri, 29 May 2026 17:50:38 +0200 Subject: [PATCH 2/5] Update flow-control.md --- docs/Concepts/flow-control.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/Concepts/flow-control.md b/docs/Concepts/flow-control.md index 51a18d47d67092..f5d16f11e884a3 100644 --- a/docs/Concepts/flow-control.md +++ b/docs/Concepts/flow-control.md @@ -799,3 +799,28 @@ logConsole($message) ``` +## defer (expression) + +
History + +|Release|Changes| +|---|---| +|21 R4|Added +
+ + +The [`defer`](../commands/defer) command allows you to stack one or more expression(s) that will automatically execute when the current method or function **finishes running**. + +Whether you are managing document closings, resetting interprocess flags, or freeing up resources, ensuring that your housekeeping tasks execute flawlessly no matter how or where your function terminates can be handled by `defer` keywords. + +#### Example + +If you are optimizing your application, you want to be 100% sure your performance metrics are recorded, regardless of where or how your code exits. + +```4d + //Guarantee the benchmark stops and records data at the very end of the execution +defer(benchmarkStop(Current method name)) + //Do something... +``` + +See the [`defer`](../commands/defer) command description for more information. \ No newline at end of file From 4a473d37b438deb8bd5ef618839f91829bb248e1 Mon Sep 17 00:00:00 2001 From: arnaud-4d Date: Mon, 1 Jun 2026 17:02:34 +0200 Subject: [PATCH 3/5] fixed object refs --- docs/Concepts/dt_collection.md | 32 +++++++++++++++++++++ docs/Concepts/dt_object.md | 28 +++++++++++++++++- docs/Concepts/operators.md | 7 +++-- docs/language-legacy/Interruptions/defer.md | 8 ++---- 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/docs/Concepts/dt_collection.md b/docs/Concepts/dt_collection.md index 0b13103072c5a5..b184f08bb7f4cb 100644 --- a/docs/Concepts/dt_collection.md +++ b/docs/Concepts/dt_collection.md @@ -40,6 +40,38 @@ If you assign an element's index that surpasses the last existing element of the //myCol[4]=null ``` +## Assignment + +Collection and [object](./dt_object.md) data types are handled in the 4D language through **references** (i.e., internal pointers), unlike scalar data types (integer, date, etc.). As a result, when assigning a collection to a variable (e.g. `$myVar:=[1;2;3]`), it is the **reference** that is assigned, not the value itself. Any subsequent modification of the *$myVar* variable will therefore be reflected everywhere the original collection is referenced. This follows the same principle as [pointers](./dt_collection.md), except that the *$myVar* variable does not need to be dereferenced. + +For example: + +```4d +var $col1; $col2 : Collection +var $o : Object + +$col1:=[1;2;3] //a reference to the collection is created +$col2:=$col1 //both variables share the same collection reference +$o:={ list:$col1 } //the object stores a reference to the same collection + +$col1.push(4) +//$col2 = [1,2,3,4] +//$o = {"list":[1,2,3,4]} + +$col2[0]:=10 +//$col1 = [10,2,3,4] +//$o = {"list":[10,2,3,4]} + +$o.list.push(5) +//$col1 = [10,2,3,4,5] +//$col2 = [10,2,3,4,5] + +ASSERT($col1=$col2) //True +``` + +This principle applies wherever objects or collections are used, including in [parameters](./parameters.md) or [formula](../commands/formula) expressions. + + ## Instantiation Collections must have been instantiated, otherwise trying to read or modify their elements will generate a syntax error. diff --git a/docs/Concepts/dt_object.md b/docs/Concepts/dt_object.md index 13e3e68512db76..ccb371990ce0e2 100644 --- a/docs/Concepts/dt_object.md +++ b/docs/Concepts/dt_object.md @@ -29,7 +29,7 @@ Keep in mind that property names differentiate between upper and lower case. ::: -You manage Object type variables, fields or expressions using the standard [object notation](#properties) or the commands available in the **Objects (Language)** theme. Note that specific commands of the **Queries** theme such as `QUERY BY ATTRIBUTE`, `QUERY SELECTION BY ATTRIBUTE`, or `ORDER BY ATTRIBUTE` can be used to carry out processing on object fields. +You manage Object type variables, fields or expressions using the standard [object notation](#properties) or the commands available in the **Objects (Language)** theme. Each property value accessed through the object notation is considered an expression. You can use such values wherever 4D expressions are expected: @@ -37,6 +37,32 @@ Each property value accessed through the object notation is considered an expres - in the Expression areas of the Debugger and the Runtime explorer, - in the Property list of the Form editor for form objects: Variable or Expression field as well as various selection list box and columns expressions (Data Source, background color, style, or font color). + +## Assignment + +Object and [collection](./dt_collection.md) data types are handled in the 4D language through **references** (i.e., internal pointers), unlike scalar data types (integer, date, etc.). As a result, when assigning an object or a collection to a variable (e.g. `$myVar:={ a:2 }`), it is the **reference** that is assigned, not the value itself. Any subsequent modification of the *$myVar* variable will therefore be reflected everywhere the original object is referenced. This follows the same principle as [pointers](./dt_collection.md), except that the *$myVar* variable does not need to be dereferenced. + +For example: + +```4d +var $o1; $o2 : Object +var $col : Collection + +$col:=[1;2;3] //a reference to the collection is created +$o1:={ a:2 ; b:$col } //a reference to the object is created +$o2:=$o1 //both variables $o1 and $o2 share the reference to the same object + +$o1.a:=10 //$o2 = {"a":10,"b":[1,2,3]} +$o2.a:=20 //$o1 = {"a":20,"b":[1,2,3]} +$col.push(4) +//$o1 = {"a":20,"b":[1,2,3,4]} +//$o2 = {"a":20,"b":[1,2,3,4]} +ASSERT($o1=$o2) //True +``` + +This principle applies wherever objects or collections are used, including in [parameters](./parameters.md) or [formula](../commands/formula) expressions. + + ## Instantiation Objects must have been instantiated, otherwise trying to read or modify their properties will generate a syntax error. diff --git a/docs/Concepts/operators.md b/docs/Concepts/operators.md index d15c09b5e9319c..e816769552ce9c 100644 --- a/docs/Concepts/operators.md +++ b/docs/Concepts/operators.md @@ -24,15 +24,18 @@ The values that operators affect are operands. In the expression `1 + 2`, the + The **assignment operator** (`a:=b`) initializes or updates the value of `a` with the value of `b`: ```4d -$myNumber:=3 //assigns 3 to MyNumber variable -$myDate:=!2018/01/21! //assigns a date literal +$myNumber:=3 //assigns 3 to $myNumber variable +$myDate:=!2026/01/21! //assigns a date literal $myLength:=Length("Acme") //assigns the result of the command (4) to $myLength $col:=New collection //$col is initialized with an empty collection +$myObject:={ a:2 ; b:$col } //assigns an object reference to $myObject +$myObject.a:=3 //assigns a value to an object property ``` > Do NOT confuse the assignment operator `:=` with the equality comparison operator `=`. A different assignment operator (and not `=`) was deliberately chosen to avoid issues and confusion which often occur with == or === in other programming languages. Such errors are often difficult to recognize by the compiler and lead to time-consuming troubleshooting. + ## Basic operators Operator results depend on the **data types** they are applied to. 4D supports different operators on scalar data types. They are described with the data types, in the following sections: diff --git a/docs/language-legacy/Interruptions/defer.md b/docs/language-legacy/Interruptions/defer.md index 097b2f16d30663..b5e77c56a3fd3c 100644 --- a/docs/language-legacy/Interruptions/defer.md +++ b/docs/language-legacy/Interruptions/defer.md @@ -52,13 +52,11 @@ Behind the scenes, the command works as follows: every time a `defer` is called, As for all [formulas](../../commands/formula), if the *exitFormula* expression uses local variables, their current values are copied and stored in the formula object returned **when it is put in the *deferred stack***. When executed, the formula uses these copied values rather than the current values of the local variables. Note that the use of arrays as local variables is not supported. +:::note -Local variables and ORDA values at the expressio +Keep in mind that local variables store **references** for [object](../../Concepts/dt_object.md#assignment) and [collection](../../Concepts/dt_collection.md#assignment) values. -Thus, the *exitFormula* formula is evaluated with the following current values: - -- local variables and ORDA values at the expression deferring call (i.e. when the expression is put in the *deferred stack*), -- process and interprocess variables as well as database field values at the method or function end. +::: If the *exitFormula* expression throws an error, it is automatically caught without any interruption and the execution flow continues as it runs with a [`Try`](../../Concepts/error-handling.md#tryexpression) expression. From 88f8f30ba414f75fd64af87deb24bd1e15f58048 Mon Sep 17 00:00:00 2001 From: arnaud-4d Date: Fri, 29 May 2026 17:22:27 +0200 Subject: [PATCH 4/5] squaqhed commits first draft Update flow-control.md fixed object refs --- docs/Concepts/dt_collection.md | 42 ++++++ docs/Concepts/dt_object.md | 38 +++++- docs/Concepts/flow-control.md | 22 +++ docs/Concepts/methods.md | 2 +- docs/Concepts/operators.md | 7 +- docs/Notes/updates.md | 10 ++ .../Formulas/execute-formula.md | 4 +- docs/language-legacy/Formulas/formula.md | 2 +- docs/language-legacy/Interruptions/defer.md | 128 ++++++++++++++++++ docs/language-legacy/Interruptions/throw.md | 9 +- .../version-19/API/FunctionClass.md | 2 +- .../Formulas/execute-formula.md | 4 +- .../language-legacy/Formulas/formula.md | 2 +- 13 files changed, 257 insertions(+), 15 deletions(-) create mode 100644 docs/language-legacy/Interruptions/defer.md diff --git a/docs/Concepts/dt_collection.md b/docs/Concepts/dt_collection.md index 0b13103072c5a5..2841f0fe111c35 100644 --- a/docs/Concepts/dt_collection.md +++ b/docs/Concepts/dt_collection.md @@ -40,6 +40,8 @@ If you assign an element's index that surpasses the last existing element of the //myCol[4]=null ``` + + ## Instantiation Collections must have been instantiated, otherwise trying to read or modify their elements will generate a syntax error. @@ -112,6 +114,46 @@ You can create two types of collections: For more information, refer to the [Shared objects and collections](shared.md) section. + +## Assignment + +Collection and [object](./dt_object.md) data types are handled in the 4D language through **references** (i.e., internal pointers), unlike scalar data types (integer, date, etc.). As a result, when assigning a collection to a variable (e.g. `$myVar:=[1;2;3]`), it is the **reference** that is assigned, not the value itself. Any subsequent modification of the *$myVar* variable will therefore be reflected everywhere the original collection is referenced. This follows the same principle as [pointers](./dt_collection.md), except that the *$myVar* variable does not need to be dereferenced. + +For example: + +```4d +var $col1; $col2 : Collection +var $o : Object + +$col1:=[1;2;3] //a reference to the collection is created +$col2:=$col1 //both variables share the same collection reference +$o:={ list:$col1 } //the object stores a reference to the same collection + +$col1.push(4) +//$col2 = [1,2,3,4] +//$o = {"list":[1,2,3,4]} + +$col2[0]:=10 +//$col1 = [10,2,3,4] +//$o = {"list":[10,2,3,4]} + +$o.list.push(5) +//$col1 = [10,2,3,4,5] +//$col2 = [10,2,3,4,5] + +ASSERT($col1=$col2) //True +``` + +This principle applies wherever objects or collections are assigned, including in [parameters](./parameters.md) or [formula](../commands/formula) expressions. + +:::note + +If you want to create a **deep copy** of a collection, use the [`collection.copy()`](../API/CollectionClass.md#copy) function. + +::: + + + ## Collection functions 4D collection references benefit from special class functions (sometimes named *member functions*). Collection functions are listed in the [Class API Reference](../API/CollectionClass.md) section. diff --git a/docs/Concepts/dt_object.md b/docs/Concepts/dt_object.md index 13e3e68512db76..56f60368d66359 100644 --- a/docs/Concepts/dt_object.md +++ b/docs/Concepts/dt_object.md @@ -29,7 +29,7 @@ Keep in mind that property names differentiate between upper and lower case. ::: -You manage Object type variables, fields or expressions using the standard [object notation](#properties) or the commands available in the **Objects (Language)** theme. Note that specific commands of the **Queries** theme such as `QUERY BY ATTRIBUTE`, `QUERY SELECTION BY ATTRIBUTE`, or `ORDER BY ATTRIBUTE` can be used to carry out processing on object fields. +You manage Object type variables, fields or expressions using the standard [object notation](#properties) or the commands available in the **Objects (Language)** theme. Each property value accessed through the object notation is considered an expression. You can use such values wherever 4D expressions are expected: @@ -37,6 +37,11 @@ Each property value accessed through the object notation is considered an expres - in the Expression areas of the Debugger and the Runtime explorer, - in the Property list of the Form editor for form objects: Variable or Expression field as well as various selection list box and columns expressions (Data Source, background color, style, or font color). + + + + + ## Instantiation Objects must have been instantiated, otherwise trying to read or modify their properties will generate a syntax error. @@ -122,6 +127,37 @@ You can create two types of objects: For more information, refer to the [Shared objects and collections](shared.md) section. +## Assignment + +Object and [collection](./dt_collection.md) data types are handled in the 4D language through **references** (i.e., internal pointers), unlike scalar data types (integer, date, etc.). As a result, when assigning an object or a collection to a variable (e.g. `$myVar:={ a:2 }`), it is the **reference** that is assigned, not the value itself. Any subsequent modification of the *$myVar* variable will therefore be reflected everywhere the original object is referenced. This follows the same principle as [pointers](./dt_collection.md), except that the *$myVar* variable does not need to be dereferenced. + +For example: + +```4d +var $o1; $o2 : Object +var $col : Collection + +$col:=[1;2;3] //a reference to the collection is created +$o1:={ a:2 ; b:$col } //a reference to the object is created +$o2:=$o1 //both variables $o1 and $o2 share the reference to the same object + +$o1.a:=10 //$o2 = {"a":10,"b":[1,2,3]} +$o2.a:=20 //$o1 = {"a":20,"b":[1,2,3]} +$col.push(4) +//$o1 = {"a":20,"b":[1,2,3,4]} +//$o2 = {"a":20,"b":[1,2,3,4]} +ASSERT($o1=$o2) //True +``` + +This principle applies wherever objects or collections are used, including in [parameters](./parameters.md) or [formula](../commands/formula) expressions. + + +:::note + +If you want to create a **deep copy** of an object, use the [`OB COPY`](../commands/ob-copy) command. + +::: + ## Properties {#properties} diff --git a/docs/Concepts/flow-control.md b/docs/Concepts/flow-control.md index 51a18d47d67092..66776000bc18e7 100644 --- a/docs/Concepts/flow-control.md +++ b/docs/Concepts/flow-control.md @@ -799,3 +799,25 @@ logConsole($message) ``` +## defer (expression) + +
History + +|Release|Changes| +|---|---| +|21 R4|Added +
+ + +The [`defer`](../commands/defer) command allows you to stack one or more expression(s) that will automatically execute when the current method or function **finishes running**. + +Whether you are managing document closings, resetting interprocess flags, or freeing up resources, ensuring that your housekeeping tasks execute flawlessly no matter how or where your function terminates can be handled by `defer` keywords. + + +```4d + //make sure some code is executed at exit +defer(myCleaningMethod) + //Do something... +``` + +See the [`defer`](../commands/defer) command description for more information. \ No newline at end of file diff --git a/docs/Concepts/methods.md b/docs/Concepts/methods.md index 9083e73d5daeeb..8c7ec211e2217e 100644 --- a/docs/Concepts/methods.md +++ b/docs/Concepts/methods.md @@ -21,6 +21,6 @@ In the 4D Language, there are several categories of methods. The category depend |**Form method**|Automatic, when an event involves the form to which the method is attached|No|Property of a form. You can use a form method to manage data and objects, but it is generally simpler and more efficient to use an object method for these purposes.| |**Trigger** (aka *Table method*)|Automatic, each time that you manipulate the records of a table (Add, Delete and Modify)|No|Property of a table. Triggers are methods that can prevent "illegal" operations with the records of your database.| |**Database method**|Automatic, when a working session event occurs|Yes (predefined)|There are 16 database methods in 4D. | -|**Class**|Automatically called when an object of the class is instantiated or when a function of the class is executed on an object instance in any other methods or in a [database field](../Develop/field-properties.md#class).|yes (class functions)|A **Class** is used to declare and configure the class [constructor](./classes.md#class-constructor), [properties](./classes.md#property), and [functions](./classes.md#function) of objects. See [**Classes**](classes.md) | +|**Class**|Automatically called when an object of the class is instantiated or when a function of the class is executed on an object instance in any other methods or in a [database field](../Develop/field-properties.md#class).|yes (class functions)|A **Class** is used to declare and configure the class [constructor](./classes.md#class-constructor), [properties](./classes.md#property), and [functions](./classes.md#function) of objects. See [**Classes**](classes.md) and [**Function** class](../API/FunctionClass.md). | diff --git a/docs/Concepts/operators.md b/docs/Concepts/operators.md index d15c09b5e9319c..e816769552ce9c 100644 --- a/docs/Concepts/operators.md +++ b/docs/Concepts/operators.md @@ -24,15 +24,18 @@ The values that operators affect are operands. In the expression `1 + 2`, the + The **assignment operator** (`a:=b`) initializes or updates the value of `a` with the value of `b`: ```4d -$myNumber:=3 //assigns 3 to MyNumber variable -$myDate:=!2018/01/21! //assigns a date literal +$myNumber:=3 //assigns 3 to $myNumber variable +$myDate:=!2026/01/21! //assigns a date literal $myLength:=Length("Acme") //assigns the result of the command (4) to $myLength $col:=New collection //$col is initialized with an empty collection +$myObject:={ a:2 ; b:$col } //assigns an object reference to $myObject +$myObject.a:=3 //assigns a value to an object property ``` > Do NOT confuse the assignment operator `:=` with the equality comparison operator `=`. A different assignment operator (and not `=`) was deliberately chosen to avoid issues and confusion which often occur with == or === in other programming languages. Such errors are often difficult to recognize by the compiler and lead to time-consuming troubleshooting. + ## Basic operators Operator results depend on the **data types** they are applied to. 4D supports different operators on scalar data types. They are described with the data types, in the following sections: diff --git a/docs/Notes/updates.md b/docs/Notes/updates.md index 4dc9c84d0d049b..7298d1f6b03368 100644 --- a/docs/Notes/updates.md +++ b/docs/Notes/updates.md @@ -3,6 +3,16 @@ id: updates title: Release Notes --- +## 4D 21 R4 + +Read [**What’s new in 4D 21 R4**](https://blog.4d.com/whats-new-in-4d-21-r4/), the blog post that lists all new features and enhancements in 4D 21 R4. + +#### Highlights + +- New [`defer`](../commands/defer) command to declare some code to be always executed at method or function exit. + + + ## 4D 21 R3 Read [**What’s new in 4D 21 R3**](https://blog.4d.com/whats-new-in-4d-21-r3/), the blog post that lists all new features and enhancements in 4D 21 R3. diff --git a/docs/language-legacy/Formulas/execute-formula.md b/docs/language-legacy/Formulas/execute-formula.md index 94503e0742c6da..a687d70bc8aa35 100644 --- a/docs/language-legacy/Formulas/execute-formula.md +++ b/docs/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs The statement string must be one line. If *statement* is an empty string, **EXECUTE FORMULA** does nothing. The rule of thumb is that if the *statement* can be executed as a one-line method, then it will execute properly. Use **EXECUTE FORMULA** sparingly, as it can slow down execution speed. In a compiled database, the line of code is not compiled. This means that *statement* will be executed, but it will not have been checked by the compiler at compilation time. -**Note:** Executing formulas in compiled mode can be optimized using a cache (see *Cache for formulas in compiled mode* below). +**Note:** Executing formulas in compiled mode can be optimized using a cache (see [Cache for formulas in compiled mode](#cache-for-formulas-in-compiled-mode) below). The *statement* can include the following elements: @@ -46,7 +46,7 @@ The *statement* can include the following elements: * If *statement* is a project method, it is recommended to use the [EXECUTE METHOD](../commands/execute-method) that allows you to pass parameters. * It is not recommend to call any variable declaration in *statement* since it can generate conflicts in the code. -The formula can include process variables and interprocess variables. However, the statement cannot contain control of flow statements (If, While, etc.), because it must be in one line of code. +The formula can include process variables and interprocess variables. However, the statement cannot contain control of flow statements (If, While, Return, Break, etc.), because it must be in one line of code. These keywords will be ignored. To ensure that the *statement* will be evaluated correctly regardless of the 4D language or version used, we recommend using the *token* syntax for elements whose name might vary between different versions (commands, tables, fields, constants). For example, to insert the [Current time](../commands/current-time) command, enter '**Current time:C178**'. For more information about this, refer to *Using tokens in formulas*. diff --git a/docs/language-legacy/Formulas/formula.md b/docs/language-legacy/Formulas/formula.md index c28488aa386901..b060f56d3d90b0 100644 --- a/docs/language-legacy/Formulas/formula.md +++ b/docs/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## Description -The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. +The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. For more information on what *formulaExp* can contain, please refer to the [`EXECUTE FORMULA`](../commands/execute-formula) command description. Having a formula as an object allows it to be passed as a parameter (calculated attribute) to commands or methods or to be executed from various components without needing to declare them as "shared by components and host database". When called, the formula object is evaluated within the context of the database or component that created it. diff --git a/docs/language-legacy/Interruptions/defer.md b/docs/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..088897bff608e6 --- /dev/null +++ b/docs/language-legacy/Interruptions/defer.md @@ -0,0 +1,128 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| Parameter | Type | | Description | +| --- | --- | --- | --- | +| exitFormula | Expression | → | Expression to be executed at exit| +
+ + +
+
History + +|Release|Changes| +|---|---| +|21 R4|Created| + +
+
+ +## Description + +The `defer` command declares an *exitFormula* expression that will always be executed when the method or function exits, even if an error has been thrown or a `return` has been executed. Using a `defer` command allows you to ensure that a method or function ends correctly by executing completion code on exit. In addition, this command saves you from having to duplicate the same exit code for every return or catch block. + + +:::tip Related blog post + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + + +The `defer` command can be called anywhere in the method or function code, and you can insert as many `defer` expressions as you want in the code. During execution, all encountered *exitFormula* expressions are stacked. When the code execution stops, whatever the reason (normal flow, break, error, user abort, return...), all expressions in the "deferred stack" are popped and executed in LIFO (*Last In First Out)* order. + +For example: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// At exit, alerts will display "2" and then "1" +``` + +In *exitFormula*, you pass the expression that you want to be evaluated upon method or function exit, whatever the way it exited. Behind the scenes, every time a `defer` is called, 4D converts *exitFormula* into a [formula](../../commands/formula) and adds it to a stack associated with the method or function. When the method or function ends, all formulas stored in the stack are evaluated in the order they appear in the collection. + +As for all [formulas](../../commands/formula), if the *exitFormula* expression uses local variables, their current values are copied and stored in the formula object returned **when it is put in the *deferred stack***. When executed, the formula uses these copied values rather than the current values of the local variables. + +:::note Notes + +- Keep in mind that local variables store **references** for [object](../../Concepts/dt_object.md#assignment) and [collection](../../Concepts/dt_collection.md#assignment) values. +- If *exitFormula* contains another `defer` statement, an error is thrown. + +::: + +If the *exitFormula* expression throws an error, it is automatically intercepted and ignored and the execution flow continues without any interruption. + + + +## Example 1 + +These examples illustrate the various supported *exitFormula* expressions: + +```4d +// Method call +defer(aMethod) + +// Object function call +defer(myObject.aFunction(something)) + +// Singleton function call +defer(cs.aClass.me.aFunction(something)) +``` + +## Example 2 + +You want to make sure an XML reference will be always properly released, to avoid potential memory leaks: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## Example 3 + +You want to make sure the activity monitoring stops at the end of the method: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## Example 4 + +You want to control your log generation: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` + +## See also + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## Properties + +| | | +| --- | --- | +| Command number | 1805 | +| Thread safe | no | + + + diff --git a/docs/language-legacy/Interruptions/throw.md b/docs/language-legacy/Interruptions/throw.md index 17dd63ec419ef0..45e5f8b70691db 100644 --- a/docs/language-legacy/Interruptions/throw.md +++ b/docs/language-legacy/Interruptions/throw.md @@ -38,7 +38,7 @@ Errors thrown using the **throw** command are managed by the 4D runtime as any n The command supports three syntaxes: -### **throw(errorCode{; description})** +### throw(errorCode{; description}) It specifies the error code and an optional description text, the error is thrown immediately. If no description is provided, it is filled with: @@ -46,7 +46,7 @@ If no description is provided, it is filled with: * Error code errorCode: (host) in the host application * Error code errorCode: (C00x) in a component -### **throw(errorObj)** +### throw(errorObj) *errorObj* object allows for more detailed error information and control over error handling. It can contain the following properties, as well as any custom property that you can refer to using placeholders within the **message** property. @@ -61,7 +61,7 @@ When you use this syntax, the *errorObj* object is returned in [Last errors](../ **Note:** It is possible to call the command several times in the same project method to generate several errors. You can use the deferred option to send all errors at once. -### **throw** +### throw It throws all current errors in **deferred mode**, meaning they will be added to a stack and handled when the calling method returns. This is typically done from within an [ON ERR CALL](../commands/on-err-call) callback. @@ -111,7 +111,8 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## See also [ASSERT](../commands/assert) -[Last errors](../commands/last-errors) +[defer](../commands/defer) +[Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call) ## Properties diff --git a/versioned_docs/version-19/API/FunctionClass.md b/versioned_docs/version-19/API/FunctionClass.md index f5864250d3a92a..b3005a8dfbf1e0 100644 --- a/versioned_docs/version-19/API/FunctionClass.md +++ b/versioned_docs/version-19/API/FunctionClass.md @@ -133,7 +133,7 @@ Parameters are received within the method, in the order they are specified in th #### Description -The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. +The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. For more information on what *formulaExp* can contain, please refer to the [`EXECUTE FORMULA`](../commands/execute-formula) command description. Having a formula as an object allows it to be passed as a parameter (calculated attribute) to commands or methods or to be executed from various components without needing to declare them as "shared by components and host database". When called, the formula object is evaluated within the context of the database or component that created it. diff --git a/versioned_docs/version-21-R3/language-legacy/Formulas/execute-formula.md b/versioned_docs/version-21-R3/language-legacy/Formulas/execute-formula.md index 94503e0742c6da..a687d70bc8aa35 100644 --- a/versioned_docs/version-21-R3/language-legacy/Formulas/execute-formula.md +++ b/versioned_docs/version-21-R3/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs The statement string must be one line. If *statement* is an empty string, **EXECUTE FORMULA** does nothing. The rule of thumb is that if the *statement* can be executed as a one-line method, then it will execute properly. Use **EXECUTE FORMULA** sparingly, as it can slow down execution speed. In a compiled database, the line of code is not compiled. This means that *statement* will be executed, but it will not have been checked by the compiler at compilation time. -**Note:** Executing formulas in compiled mode can be optimized using a cache (see *Cache for formulas in compiled mode* below). +**Note:** Executing formulas in compiled mode can be optimized using a cache (see [Cache for formulas in compiled mode](#cache-for-formulas-in-compiled-mode) below). The *statement* can include the following elements: @@ -46,7 +46,7 @@ The *statement* can include the following elements: * If *statement* is a project method, it is recommended to use the [EXECUTE METHOD](../commands/execute-method) that allows you to pass parameters. * It is not recommend to call any variable declaration in *statement* since it can generate conflicts in the code. -The formula can include process variables and interprocess variables. However, the statement cannot contain control of flow statements (If, While, etc.), because it must be in one line of code. +The formula can include process variables and interprocess variables. However, the statement cannot contain control of flow statements (If, While, Return, Break, etc.), because it must be in one line of code. These keywords will be ignored. To ensure that the *statement* will be evaluated correctly regardless of the 4D language or version used, we recommend using the *token* syntax for elements whose name might vary between different versions (commands, tables, fields, constants). For example, to insert the [Current time](../commands/current-time) command, enter '**Current time:C178**'. For more information about this, refer to *Using tokens in formulas*. diff --git a/versioned_docs/version-21-R3/language-legacy/Formulas/formula.md b/versioned_docs/version-21-R3/language-legacy/Formulas/formula.md index c28488aa386901..b060f56d3d90b0 100644 --- a/versioned_docs/version-21-R3/language-legacy/Formulas/formula.md +++ b/versioned_docs/version-21-R3/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## Description -The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. +The `Formula` command creates a `4D Function` object based upon the *formulaExp* expression. *formulaExp* can be as simple as a single value or complex, such as a project method with parameters. For more information on what *formulaExp* can contain, please refer to the [`EXECUTE FORMULA`](../commands/execute-formula) command description. Having a formula as an object allows it to be passed as a parameter (calculated attribute) to commands or methods or to be executed from various components without needing to declare them as "shared by components and host database". When called, the formula object is evaluated within the context of the database or component that created it. From dff5ea2ac8a5ae4078abae11d9f7182886c1596b Mon Sep 17 00:00:00 2001 From: arnaud-4d Date: Wed, 3 Jun 2026 18:48:40 +0200 Subject: [PATCH 5/5] translations by AI --- .../Formulas/execute-formula.md | 6 +- .../language-legacy/Formulas/formula.md | 2 +- .../language-legacy/Interruptions/defer.md | 121 ++++++++++++++++++ .../language-legacy/Interruptions/throw.md | 7 +- .../Formulas/execute-formula.md | 4 +- .../language-legacy/Formulas/formula.md | 2 +- .../language-legacy/Interruptions/defer.md | 121 ++++++++++++++++++ .../language-legacy/Interruptions/throw.md | 5 +- .../Formulas/execute-formula.md | 4 +- .../language-legacy/Formulas/formula.md | 2 +- .../language-legacy/Interruptions/defer.md | 121 ++++++++++++++++++ .../language-legacy/Interruptions/throw.md | 7 +- .../Formulas/execute-formula.md | 4 +- .../language-legacy/Formulas/formula.md | 2 +- .../language-legacy/Interruptions/defer.md | 121 ++++++++++++++++++ .../language-legacy/Interruptions/throw.md | 7 +- 16 files changed, 512 insertions(+), 24 deletions(-) create mode 100644 i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md create mode 100644 i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md create mode 100644 i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md create mode 100644 i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md diff --git a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md index 30ed3f64e238c7..6fe5b3cfd1d432 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs La cadena de instrucción debe ser de una sola línea. Si *instruccion* es una cadena vacía, **EXECUTE FORMULA** no hace nada. La regla es que si la instrucción puede ejecutarse como un método de una línea, entonces se ejecutará correctamente. El comando **EXECUTE FORMULA** debe utilizarse con precaución, ya que disminuye la velocidad de ejecución. En una base compilada, el código de la instrucción no está compilado. Esto significa que la instrucción será ejecutada, pero no será verificada por el compilador en el momento de la compilación. -**Nota:** la ejecución de fórmulas en modo compilado se puede optimizar utilizando una memoria caché (ver *Caché para fórmulas en modo compilado* abajo). +**Nota:** la ejecución de fórmulas en modo compilado se puede optimizar utilizando una memoria caché (ver [Caché para fórmulas en modo compilado](#cache-para-formulas-en-modo-compilado) abajo). La *instrucción* puede incluir los siguientes elementos: @@ -41,7 +41,7 @@ La *instrucción* puede incluir los siguientes elementos: * una llamada a un comando 4D * una tarea -La fórmula puede incluir variables proceso e interproceso. La instrucción no puede contener instrucciones de control de flujo (If, While, etc.), porque la instrucción debe tener sólo una línea de código. +La fórmula puede incluir variables proceso e interproceso. La instrucción no puede contener instrucciones de control de flujo (If, While, Return, Break, etc.), porque la instrucción debe tener sólo una línea de código. Estas palabras clave se ignorarán. Para asegurarse de que la *instruccion* sea evaluada correctamente independientemente del lenguaje o versión 4D utilizada, se recomienda utilizar la sintaxis tokenizada para los elementos cuyo nombre puede variar entre las diferentes versiones (comandos, tablas, campos, constantes). Por ejemplo, para insertar el comando [Current time](../commands/current-time), introduzca **'Current time:C178'**. Para más información, consulte *Utilizar tokens en fórmulas*. @@ -50,7 +50,7 @@ Para asegurarse de que la *instruccion* sea evaluada correctamente independiente * Si la *instruccion* es un método proyecto, se recomienda utilizar [EXECUTE METHOD](../commands/execute-method) que le permite pasar parámetros. * No se recomienda llamar a ningún comando de declaración de variable como *C\_DATE* en *instruccion* ya que puede generar conflictos en el código. -La fórmula puede incluir variables de proceso y variables entre procesos. Sin embargo, la declaración no puede contener el control de las instrucciones de flujo (If, While, etc.), ya que debe estar en una línea de código. +La fórmula puede incluir variables de proceso y variables entre procesos. Sin embargo, la declaración no puede contener el control de las instrucciones de flujo (If, While, Return, Break, etc.), ya que debe estar en una línea de código. Estas palabras clave se ignorarán. Para garantizar que la *instrucción* se evalúe correctamente, independientemente del lenguaje 4D o la versión utilizada, se recomienda utilizar la sintaxis del *token* para los elementos cuyo nombre puede variar entre diferentes versiones (comandos, tablas, campos, constantes). Por ejemplo, para insertar el comando \[#cmd id="178"/\], introduzca '**Current time:C178**'. Para más información al respecto, consulte *Utilizar tokens en fórmulas*. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md index 1457c6f40ef403..8233830fd8c001 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## Descripción -El comando `Formula` crea un objeto `4D Function` basado en la expresión *formulaExp*. *formulaExp* puede ser tan simple como un valor único o complejo, como un método proyecto con parámetros. +El comando `Formula` crea un objeto `4D Function` basado en la expresión *formulaExp*. *formulaExp* puede ser tan simple como un valor único o complejo, como un método proyecto con parámetros. Para más información sobre lo que puede contener *formulaExp*, consulte la descripción del comando [`EXECUTE FORMULA`](../commands/execute-formula). Tener una fórmula como objeto permite pasarla como parámetro (atributo calculado) a los comandos o a los métodos o ejecutarla desde varios componentes sin necesidad de declararla como "compartida por los componentes y la base de datos local". Cuando se llama, el objeto fórmula se evalúa en el contexto de la base de datos o del componente que lo creó. diff --git a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..4202d4f7c22d63 --- /dev/null +++ b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md @@ -0,0 +1,121 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| Parámetro | Tipo | | Descripción | +| --- | --- | --- | --- | +| exitFormula | Expression | → | Expresión a ejecutar al salir | +
+ + +
+
Historial + +|Versión|Cambios| +|---|---| +|21 R4|Creado| + +
+
+ +## Descripción + +El comando `defer` declara una expresión *exitFormula* que siempre se ejecutará al salir del método o de la función, incluso si se ha lanzado un error o se ha ejecutado un `return`. Usar `defer` le permite garantizar que un método o una función termine correctamente ejecutando código de finalización al salir. Además, este comando evita duplicar el mismo código de salida en cada bloque de retorno o captura de errores. + +:::tip Entrada de blog relacionada + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + +El comando `defer` puede llamarse en cualquier parte del código del método o de la función, y puede insertar tantas expresiones `defer` como desee. Durante la ejecución, todas las expresiones *exitFormula* encontradas se apilan. Cuando se detiene la ejecución, sea cual sea el motivo (flujo normal, break, error, interrupción del usuario, return...), todas las expresiones de la pila diferida se desapilan y se ejecutan en orden LIFO (*Last In First Out*). + +Por ejemplo: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// Al salir, las alertas mostrarán "2" y luego "1" +``` + +En *exitFormula*, usted pasa la expresión que desea evaluar al salir del método o función, sin importar cómo haya terminado. Internamente, cada vez que se llama a `defer`, 4D convierte *exitFormula* en una [formula](../../commands/formula) y la añade a una pila asociada al método o función. Cuando finaliza el método o función, todas las fórmulas almacenadas en la pila se evalúan en el orden en que aparecen en la colección. + +Como ocurre con todas las [formulas](../../commands/formula), si la expresión *exitFormula* usa variables locales, sus valores actuales se copian y se almacenan en el objeto fórmula devuelto **cuando se coloca en la pila diferida**. Al ejecutarse, la fórmula utiliza esos valores copiados en lugar de los valores actuales de las variables locales. + +:::note Notas + +- Tenga en cuenta que las variables locales almacenan **referencias** para valores [object](../../Concepts/dt_object.md#assignment) y [collection](../../Concepts/dt_collection.md#assignment). +- Si *exitFormula* contiene otra instrucción `defer`, se lanza un error. + +::: + +Si la expresión *exitFormula* lanza un error, este se intercepta e ignora automáticamente y el flujo de ejecución continúa sin interrupción. + +## Ejemplo 1 + +Estos ejemplos ilustran las distintas expresiones *exitFormula* compatibles: + +```4d +// Llamada a método +defer(aMethod) + +// Llamada a función de objeto +defer(myObject.aFunction(something)) + +// Llamada a función singleton +defer(cs.aClass.me.aFunction(something)) +``` + +## Ejemplo 2 + +Quiere asegurarse de que una referencia XML siempre se libere correctamente, para evitar posibles fugas de memoria: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## Ejemplo 3 + +Quiere asegurarse de que la supervisión de actividad se detenga al final del método: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## Ejemplo 4 + +Quiere controlar la generación de registros: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` + +## Ver también + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## Propiedades + +| | | +| --- | --- | +| Número de comando | 1805 | +| Hilo seguro | no | diff --git a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md index 1715a8b6c3d718..caa4c5195dbeaf 100644 --- a/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md +++ b/i18n/es/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md @@ -38,7 +38,7 @@ Los errores lanzados utilizando el comando **throw** son gestionados por el runt El comando admite tres sintaxis: -### **throw(errorCode{; description})** +### throw(errorCode{; description}) Especifica el código de error y un texto de descripción opcional, el error se lanza inmediatamente. Si no se indica ninguna descripción: se llena con: @@ -46,7 +46,7 @@ Si no se indica ninguna descripción: se llena con: * Código de error (errorCode): (host) en la aplicación local * Código de error (errorCode): (C00x) en un componente -### **throw(errorObj)** +### throw(errorObj) El objeto *errorObj* permite obtener información de error más detallada y controlar la gestión de errores. Puede contener las siguientes propiedades, así como toda propiedad personalizada a la que pueda hacer referencia la propiedad **message**. @@ -63,7 +63,7 @@ Cuando se utiliza esta sintaxis, el objeto *errorObj* se devuelve en Últimos er **Nota:** es posible llamar al comando varias veces en el mismo método proyecto para generar varios errores. Puede utilizar la opción diferido para enviar todos los errores a la vez. -### **throw** +### throw Lanza todos los errores actuales en **modo diferido**, lo que significa que se añadirán a una pila y se gestionarán cuando vuelva el método que los llama. Esto se hace típicamente desde dentro de una retrollamada [ON ERR CALL](../commands/on-err-call). @@ -113,6 +113,7 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## Ver también [ASSERT](../commands/assert) +[defer](../commands/defer) [Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call) diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md index 034c0e753afde8..f41c86d7540ecb 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs La chaîne d'instructions doit comporter une seule ligne. Si *instruction* est une chaîne vide, **EXECUTE FORMULA** ne fait rien. Le principe est que si *instruction* peut être exécutée comme une méthode d'une seule ligne, alors elle s'exécutera correctement. La commande **EXECUTE FORMULA** doit être utilisée avec précautions, car elle ralentit la vitesse d'exécution. Dans une base compilée, le code d'*instruction* n'est pas compilé. Cela signifie que l'*instruction* sera bien exécutée, mais ne sera pas vérifiée par le compilateur au moment de la compilation. -**Note :** L'exécution de formules en mode compilé peut être optimisée à l'aide d'un cache (cf. paragraphe "Cache de formules en mode compilé" ci-dessous). +**Note :** L'exécution de formules en mode compilé peut être optimisée à l'aide d'un cache (voir [Cache de formules en mode compilé](#cache-de-formules-en-mode-compile) ci-dessous). L'*instruction* peut notamment contenir les éléments suivants : @@ -46,7 +46,7 @@ L'*instruction* peut notamment contenir les éléments suivants : * Si *instruction* est une méthode projet, il est recommandé d'utiliser [EXECUTE METHOD](../commands/execute-method) qui permet de passer des paramètres. * Il est déconseillé d'appeler des commandes de déclaration de variables telles que *C\_DATE* dans *instruction* afin d'éviter tout risque de conflit de type. -La formule peut utiliser des variables process et interprocess. En revanche, *instruction* ne doit pas contenir d'instructions de contrôle de flux (Si, Tant que...) car le code doit "tenir" sur une seule ligne. +La formule peut utiliser des variables process et interprocess. En revanche, *instruction* ne doit pas contenir d'instructions de contrôle de flux (Si, Tant que, Return, Break, etc.) car le code doit "tenir" sur une seule ligne. Ces mots-clés seront ignorés. Pour assurer une évaluation correcte de l'*instruction* quelle que soit la langue ou la version de 4D, il est recommandé d'utiliser la syntaxe *tokenisée* pour les éléments dont le nom peut varier au fil des versions (commandes, tables, champs, constantes). Par exemple, pour insérer la commande [Current time](../commands/current-time), saisissez '**Current time:C178**'. Pour plus d'informations sur ce point, reportez-vous à la section *Utiliser des tokens dans les formules*. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md index 3cb432c80bdb60..eabb4a1eff1df6 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## Description -La commande `Formula` crée un objet `4D Function` basé sur l'expression *formulaExp*. *formulaExp* peut être simple comme une valeur unique ou complexe comme une méthode projet avec des paramètres. +La commande `Formula` crée un objet `4D Function` basé sur l'expression *formulaExp*. *formulaExp* peut être simple comme une valeur unique ou complexe comme une méthode projet avec des paramètres. Pour plus d'informations sur ce que *formulaExp* peut contenir, consultez la description de la commande [`EXECUTE FORMULA`](../commands/execute-formula). Le fait d'avoir une formule en tant qu'objet permet de la passer en tant que paramètre (champ calculé) à des commandes ou à des méthodes ou de l'exécuter à partir de divers composants sans avoir à les déclarer comme "partagés par les composants et la base de données hôte". Lorsqu'il est appelé, l'objet formula est évalué dans le contexte de la base de données ou du composant qui l'a créé. diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..751e148df9b7cf --- /dev/null +++ b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md @@ -0,0 +1,121 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| Paramètre | Type | | Description | +| --- | --- | --- | --- | +| exitFormula | Expression | → | Expression à exécuter à la sortie | +
+ + +
+
Historique + +|Version|Changements| +|---|---| +|21 R4|Créé| + +
+
+ +## Description + +La commande `defer` déclare une expression *exitFormula* qui sera toujours exécutée à la sortie de la méthode ou de la fonction, même si une erreur a été levée ou si un `return` a été exécuté. L'utilisation de `defer` vous permet de garantir qu'une méthode ou une fonction se termine correctement en exécutant du code de finalisation à la sortie. De plus, cette commande évite de dupliquer le même code de sortie dans chaque bloc de retour ou de capture d'erreur. + +:::tip Article de blog associé + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + +La commande `defer` peut être appelée n'importe où dans le code d'une méthode ou d'une fonction, et vous pouvez insérer autant d'expressions `defer` que nécessaire. Pendant l'exécution, toutes les expressions *exitFormula* rencontrées sont empilées. Quand l'exécution s'arrête, quelle qu'en soit la raison (flux normal, break, erreur, interruption utilisateur, return...), toutes les expressions de la pile différée sont dépilées et exécutées dans l'ordre LIFO (*Last In First Out*). + +Par exemple: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// A la sortie, les alertes afficheront "2" puis "1" +``` + +Dans *exitFormula*, vous passez l'expression à évaluer à la sortie de la méthode ou de la fonction, quelle que soit la manière dont elle se termine. En interne, à chaque appel de `defer`, 4D convertit *exitFormula* en [formula](../../commands/formula) et l'ajoute à une pile associée à la méthode ou à la fonction. Quand la méthode ou la fonction se termine, toutes les formules stockées dans la pile sont évaluées dans l'ordre où elles apparaissent dans la collection. + +Comme pour toutes les [formulas](../../commands/formula), si l'expression *exitFormula* utilise des variables locales, leurs valeurs courantes sont copiées et stockées dans l'objet formule retourné **au moment où il est placé dans la pile différée**. Lors de l'exécution, la formule utilise ces valeurs copiées et non les valeurs courantes des variables locales. + +:::note Notes + +- Gardez à l'esprit que les variables locales stockent des **références** pour les valeurs de type [object](../../Concepts/dt_object.md#assignment) et [collection](../../Concepts/dt_collection.md#assignment). +- Si *exitFormula* contient une autre instruction `defer`, une erreur est générée. + +::: + +Si l'expression *exitFormula* génère une erreur, celle-ci est automatiquement interceptée et ignorée, et l'exécution continue sans interruption. + +## Exemple 1 + +Ces exemples illustrent les différentes expressions *exitFormula* prises en charge: + +```4d +// Appel de méthode +defer(aMethod) + +// Appel d'une fonction d'objet +defer(myObject.aFunction(something)) + +// Appel d'une fonction singleton +defer(cs.aClass.me.aFunction(something)) +``` + +## Exemple 2 + +Vous voulez vous assurer qu'une référence XML est toujours correctement libérée, afin d'éviter des fuites mémoire potentielles: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## Exemple 3 + +Vous voulez vous assurer que la surveillance d'activité s'arrête à la fin de la méthode: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## Exemple 4 + +Vous voulez contrôler la génération de logs: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` + +## Voir aussi + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## Propriétés + +| | | +| --- | --- | +| Numéro de commande | 1805 | +| Thread safe | no | diff --git a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md index f895f3edf98ca0..37737d7b011e83 100644 --- a/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md +++ b/i18n/fr/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md @@ -41,7 +41,7 @@ Les erreurs générées à l'aide de la commande **throw** sont gérées par le La commande prend en charge trois syntaxes : -### **throw(errorCode{; description})** +### throw(errorCode{; description}) Elle spécifie le code d'erreur et un texte de description facultatif ; l'erreur est immédiatement déclenchée. Si aucune description n'est fournie, elle est remplie par : @@ -64,7 +64,7 @@ Lorsque vous utilisez cette syntaxe, l'objet *errorObj* est renvoyé dans [Last **Note :** Il est possible d'appeler la commande plusieurs fois dans la même méthode de projet pour générer plusieurs erreurs. Vous pouvez utiliser l'option **deferred** pour envoyer toutes les erreurs en une seule fois. -### **throw** +### throw Elle lance toutes les erreurs courantes en ***mode différé***, ce qui signifie qu'elles seront ajoutées à une pile et traitées au retour de la méthode appelante. Ceci est typiquement fait à l'intérieur d'un [ON ERR CALL](../commands/on-err-call) callback. @@ -116,6 +116,7 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## Voir aussi [ASSERT](../commands/assert) +[defer](../commands/defer) [Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call) diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md index 7c56de0c71f14e..11ae99210ed996 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs ステートメントの文字列は必ず1行だけです。*statement* に空の文字列を指定した場合、**EXECUTE FORMULA**コマンドは何も行いません。*statement* が一行のメソッドとして実行されるかぎり、それは正しく実行される、というのが大原則です。**EXECUTE FORMULA** は実行速度を低下させるので、代替え手段として利用します。コンパイル済みデータベースにおいても、そのコードはコンパイルされていません。つまり*statement*は実行されますが、コンパイル時にコンパイラによるチェックはされません。 -**注:** コンパイル済みモードでのフォーミュラの実行はキャッシュを使用する事によって最適化することができます(以下の*コンパイル済みモードでのフォーミュラのキャッシュ*を参照して下さい)。 +**注:** コンパイル済みモードでのフォーミュラの実行はキャッシュを使用する事によって最適化することができます(以下の[コンパイル済みモードでのフォーミュラのキャッシュ](#コンパイル済みモードでのフォーミュラのキャッシュ)を参照して下さい)。 *statement* には以下をの要素を含めることができます: @@ -46,7 +46,7 @@ displayed_sidebar: docs * *statement* がプロジェクトメソッドである場合、引数を渡すことのできる[EXECUTE METHOD](../commands/execute-method) を使用することが推奨されます。 * *statement* 内にて、例えば*C\_DATE* のような、変数の宣言コマンドを呼び出すことは推奨されていません。コード内で衝突を起こす可能性があるためです。 -フォーミュラにはプロセス変数とインタープロセス変数を含めることができます。しかし*statement*は1行でなければならないため、(*If*, While, などの) フローコントロールを含めることはできません。 +フォーミュラにはプロセス変数とインタープロセス変数を含めることができます。しかし*statement*は1行でなければならないため、(*If*, While, Return, Break, などの) フローコントロールを含めることはできません。これらのキーワードは無視されます。 使用する4Dの言語やバージョンやに関わらず、*statement* が正常に評価されると言う事を保証するためには、異なるバージョン間において名前が変化する可能性のある要素(コマンド、テーブル、フィールド、定数)に対しては*トークン*シンタックスを使用する事が推奨されます。例えば、[Current time](../commands/current-time)コマンドを挿入するためには'**Current time:C178**'と入力します。この点についてのより詳細な情報については、*フォーミュラ内でのトークンの使用*を参照して下さい。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md index 944dd7383730e8..de9a038733e8b9 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## 説明 -`Formula` コマンドは、 *formulaExp* の式に基づいた `4D Function` オブジェクトを作成します。 *formulaExp* には単一の値のようにシンプルなものから、引数を持つプロジェクトメソッドのように複雑なものまで指定することができます。 +`Formula` コマンドは、 *formulaExp* の式に基づいた `4D Function` オブジェクトを作成します。 *formulaExp* には単一の値のようにシンプルなものから、引数を持つプロジェクトメソッドのように複雑なものまで指定することができます。*formulaExp* に含められる内容の詳細については、[`EXECUTE FORMULA`](../commands/execute-formula) コマンドの説明を参照してください。 フォーミュラがオブジェクトとして存在することで、コマンドやメソッドに対して引数 (計算された属性) として渡したり、"コンポーネントとホストデータベース間で共有" として宣言せずとも様々なコンポーネントから実行したりできるようになります。 呼び出されたフォーミュラオブジェクトは、それを作成したデータベースあるいはコンポーネントのコンテキストにおいて評価されます。 diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..c93006f5020977 --- /dev/null +++ b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md @@ -0,0 +1,121 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| 引数 | 型 | | 説明 | +| --- | --- | --- | --- | +| exitFormula | Expression | → | 終了時に実行される式 | +
+ + +
+
履歴 + +|リリース|内容| +|---|---| +|21 R4|追加| + +
+
+ +## 説明 + +`defer` コマンドは、*exitFormula* 式を宣言します。これはメソッドまたは関数の終了時に必ず実行され、エラーがスローされた場合や `return` が実行された場合でも実行されます. `defer` を使用すると、終了時に後処理コードを実行して、メソッドや関数を正しく終了させることができます。さらに、各 return や catch ブロックで同じ終了コードを重複して記述する必要がなくなります。 + +:::tip 関連ブログ記事 + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + +`defer` コマンドはメソッドまたは関数コード内の任意の場所で呼び出すことができ、必要な数だけ `defer` 式を記述できます。実行中に見つかった *exitFormula* 式はすべてスタックに積まれます。実行が停止すると、その理由が通常フロー、break、エラー、ユーザー中断、return などのいずれであっても、遅延スタック内の式が LIFO (*Last In First Out*) 順で取り出されて実行されます。 + +例: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// 終了時に "2"、次に "1" の順でアラートが表示されます +``` + +*exitFormula* には、メソッドまたは関数終了時に評価させたい式を渡します。終了理由は問いません。内部的には、`defer` が呼ばれるたびに 4D は *exitFormula* を [formula](../../commands/formula) に変換し、メソッドまたは関数に関連付けられたスタックへ追加します。メソッドまたは関数が終了すると、スタックに保存されたすべての formula がコレクション内の順序に従って評価されます。 + +すべての [formulas](../../commands/formula) と同様に、*exitFormula* がローカル変数を使用している場合、その時点の値は **遅延スタックに格納されるタイミングで** 返される formula オブジェクトへコピーされて保存されます。実行時には、ローカル変数の現在値ではなく、コピーされた値が使用されます。 + +:::note 注記 + +- ローカル変数は [object](../../Concepts/dt_object.md#assignment) 値および [collection](../../Concepts/dt_collection.md#assignment) 値について **参照** を保持することに注意してください。 +- *exitFormula* に別の `defer` ステートメントが含まれている場合、エラーがスローされます。 + +::: + +*exitFormula* がエラーをスローした場合、そのエラーは自動的に補足されて無視され、実行フローは中断せずに継続します。 + +## 例題 1 + +以下は、サポートされる *exitFormula* 式の例です: + +```4d +// メソッド呼び出し +defer(aMethod) + +// オブジェクト関数呼び出し +defer(myObject.aFunction(something)) + +// シングルトン関数呼び出し +defer(cs.aClass.me.aFunction(something)) +``` + +## 例題 2 + +メモリーリークの可能性を避けるため、XML 参照を必ず適切に解放したい場合: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## 例題 3 + +メソッドの終了時にアクティビティ監視を確実に停止したい場合: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## 例題 4 + +ログ出力を制御したい場合: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` + +## 参照 + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## プロパティ + +| | | +| --- | --- | +| コマンド番号 | 1805 | +| スレッドセーフである | no | diff --git a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md index 29fe950e20a601..c8948d6d6fa31d 100644 --- a/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md +++ b/i18n/ja/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md @@ -39,7 +39,7 @@ displayed_sidebar: docs このコマンドは 3つのシンタックスをサポートしています: -### **throw(errorCode{; description})** +### throw(errorCode{; description}) このシンタックスでは、エラーコードと説明のテキスト (任意) を指定し、エラーは即座にスローされます。 description 引数を渡さなかった場合には、次の情報が提示されます: @@ -47,7 +47,7 @@ description 引数を渡さなかった場合には、次の情報が提示さ * ホストアプリケーションでは: Error code {errorCode}: (host) * コンポーネントでは: Error code {errorCode}: (C00x) -### **throw(errorObj)** +### throw(errorObj) *errorObj* オブジェクト引数を使うことで、エラー情報をより詳細に指定し、エラー処理の管理をさらに強化できます。このオブジェクト引数には以下のプロパティのほか、**message**プロパティのプレースホルダーを置き換えるためのカスタムプロパティを含めることができます。 @@ -62,7 +62,7 @@ description 引数を渡さなかった場合には、次の情報が提示さ **注記:** 同じプロジェクトメソッド内でこのコマンドを複数回呼び出して、複数のエラーを生成することができます。遅延モードを使って、これらのエラーを一度にスローできます。 -### **throw** +### throw このシンタックスは、カレントエラーをすべて**遅延モード**でスローします。つまり、これらのエラーはエラースタックに追加され、カレントメソッド終了時に処理されます。これは通常、[ON ERR CALL](../commands/on-err-call) コールバック内でおこなわれます。 @@ -112,6 +112,7 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## 参照 [ASSERT](../commands/assert) +[defer](../commands/defer) [Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call) diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md index 6e9fe0ef8d757c..4fb8ce6b65e9c8 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/execute-formula.md @@ -33,7 +33,7 @@ displayed_sidebar: docs A string *instruçao* deve ser uma linha de código.\[#/descv\] Se *instruçao* for uma string vazia,EXECUTE FORMULA não faz nada. A regra geral é que se instrução puder ser executada como um método de uma-linha, então será executado propriamente. Use **EXECUTE FORMULA** apenas eventualmente, pois pode desacelerar a velocidade de execução. Em um banco de dados compilado, a linha de código não é compilada. Isso significa que instrução será compilada, mas não será verificada pelo compilador no momento da compilação. -**Nota:** a execução de fórmulas em modo compilado pode ser otimizada utilizando uma memória caché (ver \[#cmd id="63" anchor="2882913"/\] abaixo). +**Nota:** a execução de fórmulas em modo compilado pode ser otimizada utilizando uma memória caché (ver [Cache para formulas em modo compilado](#cache-para-formulas-em-modo-compilado) abaixo). A instrução pode estar em: @@ -47,7 +47,7 @@ A instrução pode estar em: * Se l *instrução* for um método projeto, se recomenda utilizar [EXECUTE METHOD](../commands/execute-method) que lhe permite passar parâmetros. * Não se recomenda chamar a nenhum comando de declaração de variável como *C\_DATE* em *instrução* já que pode gerar conflitos no código. -A fórmula pode incluir variáveis de processo e variáveis entre processos. Entretanto, a declaração não pode conter o controle das instruções de fluxo (If, While, etc.), já que deve estar em uma linha de código. +A fórmula pode incluir variáveis de processo e variáveis entre processos. Entretanto, a declaração não pode conter o controle das instruções de fluxo (If, While, Return, Break, etc.), já que deve estar em uma linha de código. Essas palavras-chave serão ignoradas. Para garantir que a *instrução* seja avaliada corretamente, independentemente da linguagem 4D ou a versão utilizada, se recomenda utilizar a sintaxe de *token* para os elementos cujo nome possa variar entre diferentes versões (comandos, tabelas, campos, constantes). Por exemplo, para inserir o comando \[#cmd id="178"/\], introduza '**Current time:C178**'. Para saber mais, consulte *Usar tokens em fórmulas*. diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md index 99bb4d2e90e7a0..ebdd52d8e6c6c9 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Formulas/formula.md @@ -32,7 +32,7 @@ displayed_sidebar: docs ## Descrição -O comando `Formula` cria um objeto `4D Function` com base na expressão *formulaExp*. *formulaExp* pode ser tão simples quanto um único valor ou tão complexo quanto um método projeto com parâmetros. +O comando `Formula` cria um objeto `4D Function` com base na expressão *formulaExp*. *formulaExp* pode ser tão simples quanto um único valor ou tão complexo quanto um método projeto com parâmetros. Para mais informações sobre o que *formulaExp* pode conter, consulte a descrição do comando [`EXECUTE FORMULA`](../commands/execute-formula). Ter uma fórmula como se fosse um objeto permite que seja passada como um parâmetro (atributo calculado) para comandos ou métodos, ou para ser executado a partir de vários componentes, sem precisar declará-los como "partilhados por componentes e database host". Quando chamado, o objeto fórmula é avaliado sem o contexto do banco de dados ou componente que o criou. diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md new file mode 100644 index 00000000000000..ba09a589f734b4 --- /dev/null +++ b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/defer.md @@ -0,0 +1,121 @@ +--- +id: defer +title: defer +slug: /commands/defer +displayed_sidebar: docs +--- + +**defer** ( *exitFormula* : Expression ) + +
+ +| Parâmetro | Tipo | | Descrição | +| --- | --- | --- | --- | +| exitFormula | Expression | → | Expressão a ser executada na saída | +
+ + +
+
Histórico + +|Versão|Alterações| +|---|---| +|21 R4|Criado| + +
+
+ +## Descrição + +O comando `defer` declara uma expressão *exitFormula* que sempre será executada quando o método ou a função terminar, mesmo que um erro tenha sido lançado ou que um `return` tenha sido executado. O uso de `defer` permite garantir que um método ou função termine corretamente executando código de finalização na saída. Além disso, esse comando evita duplicar o mesmo código de saída em cada bloco de retorno ou de tratamento de erro. + +:::tip Post de blog relacionado + +[Streamline Your Clean-Up Code with the “defer” Command](https://blog.4d.com/streamline-your-clean-up-code-with-the-defer-command) + +::: + +O comando `defer` pode ser chamado em qualquer lugar do código do método ou função, e você pode inserir quantas expressões `defer` quiser. Durante a execução, todas as expressões *exitFormula* encontradas são empilhadas. Quando a execução termina, seja qual for o motivo (fluxo normal, break, erro, interrupção do usuário, return...), todas as expressões da pilha diferida são desempilhadas e executadas em ordem LIFO (*Last In First Out*). + +Por exemplo: + +```4d +defer(ALERT("1")) +defer(ALERT("2")) +// Na saída, os alertas exibirão "2" e depois "1" +``` + +Em *exitFormula*, você passa a expressão que deseja avaliar na saída do método ou função, independentemente da forma de término. Internamente, toda vez que `defer` é chamado, o 4D converte *exitFormula* em uma [formula](../../commands/formula) e a adiciona a uma pilha associada ao método ou função. Quando o método ou função termina, todas as formulas armazenadas na pilha são avaliadas na ordem em que aparecem na coleção. + +Como para todas as [formulas](../../commands/formula), se a expressão *exitFormula* usar variáveis locais, seus valores atuais são copiados e armazenados no objeto formula retornado **no momento em que ele é colocado na pilha diferida**. Quando executada, a formula usa esses valores copiados em vez dos valores atuais das variáveis locais. + +:::note Notas + +- Tenha em mente que variáveis locais armazenam **referências** para valores [object](../../Concepts/dt_object.md#assignment) e [collection](../../Concepts/dt_collection.md#assignment). +- Se *exitFormula* contiver outra instrução `defer`, um erro será lançado. + +::: + +Se a expressão *exitFormula* lançar um erro, ele é automaticamente interceptado e ignorado, e o fluxo de execução continua sem interrupção. + +## Exemplo 1 + +Estes exemplos ilustram as várias expressões *exitFormula* suportadas: + +```4d +// Chamada de método +defer(aMethod) + +// Chamada de função de objeto +defer(myObject.aFunction(something)) + +// Chamada de função singleton +defer(cs.aClass.me.aFunction(something)) +``` + +## Exemplo 2 + +Você quer garantir que uma referência XML seja sempre liberada corretamente, para evitar possíveis vazamentos de memória: + +```4d +var $xmlRef:=DOM Create XML ref("theRoot") +defer(DOM CLOSE XML($xmlRef)) +... +``` + +## Exemplo 3 + +Você quer garantir que o monitoramento de atividade seja interrompido no final do método: + +```4d +START MONITORING ACTIVITY(0.001;Activity all) +defer(STOP MONITORING ACTIVITY()) +... +``` + +## Exemplo 4 + +Você quer controlar a geração de logs: + +```4d +$logRecording:=Get database parameter(Diagnostic log recording) +SET DATABASE PARAMETER(Diagnostic log recording; 1) +defer(SET DATABASE PARAMETER(Diagnostic log recording; $logRecording)) + +$logLevel:=Get database parameter(Diagnostic log level) +SET DATABASE PARAMETER(Diagnostic log level; Log trace) +defer(SET DATABASE PARAMETER(Diagnostic log level; $logLevel)) +``` + +## Ver também + +[throw](../commands/throw) +[Last errors](../commands/last-errors) +[ON ERR CALL](../commands/on-err-call) + +## Propriedades + +| | | +| --- | --- | +| Número do comando | 1805 | +| Thread-seguro | no | diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md index 400d68949e1d5f..a07ac3fca714bb 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/language-legacy/Interruptions/throw.md @@ -38,7 +38,7 @@ Os erros lançados utilizando o comando **throw** são gestionados pelo runtime O comando admite três sintaxes: -### **throw(errorCode{; description})** +### throw(errorCode{; description}) Especifica o código de erro e um texto de descrição opcional, o erro se lança imediatamente. Se não indicar nenhuma descrição, se preenche com: @@ -46,7 +46,7 @@ Se não indicar nenhuma descrição, se preenche com: * Código de erro (errorCode): (host) na aplicação local * Código de erro (errorCode): (C00x) em um componente -### **throw(errorObj)** +### throw(errorObj) O objeto *errorObj* permite obter informação de erro mais detalhada e controlar a gestão de erros. Pode conter as seguintes propriedades, assim como toda propriedade personalizada à que possa fazer referência à propriedade **message**. @@ -63,7 +63,7 @@ Quando se utilizar esta sintaxe, o objeto *errorObj* se devolve em Últimos erro **Nota:** é possível chamar o comando várias vezes no mesmo projeto para gerar vários erros. Pode usar a opção diferida para enviar todos os erros de vez. -### **throw** +### throw Lança todos os erros atuais em **modo diferido**, o que significa que se adicionarão a uma pilha e serão geridas quando voltar ao método que os chama. Isso se faz tipicamente desde dentro de uma retrochamada [ON ERR CALL](../commands/on-err-call). @@ -113,6 +113,7 @@ throw({componentSignature: "xbox"; errCode: 600; name: "myFileName"; path: "myFi ## Ver também [ASSERT](../commands/assert) +[defer](../commands/defer) [Last errors](../commands/last-errors) [ON ERR CALL](../commands/on-err-call)