Article directory
What is routine, subroutine, tag, function, tag, procedure, class method, static method, instance method, object method
I believe that many friends are confused about the concept of some "methods" when they first come into contact with ObjectScript
programming languages ( M
languages). Different people call these "methods" differently. These "methods" are generally similar in function, but there are some subtle differences. There are so many ways to call "methods" that it is very confusing as to what the difference is between these "methods". This article will lead you to understand the concepts and definitions of these "methods".
After understanding the concept of these "methods", you can figure out Not ProduceBlock
the principle and use of keywords. If you don't know Not ProduceBlock
the function, a little carelessness may cause some serious failures during the use of the method, such as an infinite loop that causes temporary Global
infinite growth and bursts the disk, resulting in normal business downtime.
Programming language
Here is a clear concept. The programming language we use is ISC
officially defined as ObjectScript
an object scripting language, which is actually an extension of ObjectScript
the underlying M
( ) language. Mumps
Can be compared Java
with Android
, C#
and .Net
.
MUMPS
Language, abbreviation:M
technology, full name: Massachusetts General Hospital Utility Multi-Programming System, Massachusetts General Hospital multi-purpose programming system; it is also an ancient language, andFORTRAN
belongsCOBOL
to the contemporary language. Because this language is mainly used in medical databases, its application is not as widespread asSQL Server
,Oracle
etc.
Routine -Routine
A routine is a callable block of code written by the user. It is ObjectScript
a program. Traditional M
programming uses routines, because object-oriented programming has not yet appeared in ancient times.
Generally, the saved .mac
file is a routine, and mac
the file name is the routine name. int
Files are also called routines. Any file containing ObjectScript
code is called a routine.
Note: A routine refers to a file, not a method in a specific routine. Execution routines refer to execution .mac
files.
When executing a routine, use DO
the command as follows:
do ^routinename
routinename
- is the name of the routine file.
The creation routine file Routine.mac
contains the following code:
w "执行例程文件",!
Write the following method execution routine:
ClassMethod Routine()
{
d ^Routine
}
USER>d ##class(M.Method).Routine()
执行例程文件
Note: The routine can only be executed, and the return value of the routine cannot be obtained.
You may see the following execution methods:
s var = $$^RoutineName
This way the routine is not actually executed, but the first method of the routine is executed.
The creation routine file Routine1.mac
contains the following code:
Note: The first line of code must be the method name of the subroutine label, if it is another call, <PARAMETER>+1^Routine
an error will occur.
Routine()
ret "这是例程的第一个子例程方法!"
Routine1()
ret "这是例程的第二个子例程方法!"
Note: If you directly use a variable to receive the return value of the file name, the first subroutine method of the file .mac
will be called by default , and this method cannot be a label or return a variable directly with a routine. .mac
**
ClassMethod Routine1()
{
s var = $$^Routine1
w var,!
}
USER>d ##class(M.Method).Routine1()
这是例程的第一个子例程方法!
Subroutine -Subroutine
A subroutine is a named block of code within a routine. Usually, a subroutine starts LABEL
with , can accept parameters, and QUIT
ends with statement . Although QUIT
it ends with command, please note that it does not return a value.
Usually what we often call routine methods actually refers to subroutines.
To call a subroutine, use the following syntax:
d Subroutine^Routine
Subroutine
- subroutine nameRoutine
- Routine name
The form of the subroutine is:
Label(arg) scopekeyword // 作用域关键字
//code 代码
quit // 注意,QUIT没有参
Label
- Label name, routine method name.arg
- parameters, is an optional comma-separated list of parameters. If there are no parameters, the parentheses are optional.scopekeyword
- Scope keyword, the optional scope keyword isPublic
(default for subroutines) orPrivate
.code
- Execute code.quit
- Exits the command without returning a value.
Routine.mac
Add SubRoutine
a parameterless subroutine method in :
SubRoutine()
w "这是例程的第一个子例程方法!"
q
Write the calling method as follows:
Note: The parentheses can be omitted if the subroutine has no parameters.
ClassMethod Routine2()
{
d SubRoutine^Routine
}
USER>d ##class(M.Method).Routine2()
这是例程子例程方法!
Routine.mac
Add SubRoutineParams
a subroutine method with parameters in :
SubRoutineParams(str)
w "这是例程子例程方法!" _ "参数:"_str,!
q
Write the calling method as follows:
ClassMethod Routine3()
{
d SubRoutine^Routine("yx")
}
ClassMethod Routine3()
{
d SubRoutineParams^Routine("yx")
}
Note: Because the subroutine has no return value, it generally only executes the method when calling the subroutine, and generally uses do
commands or job
commands.
function -Function
Functions are named blocks of code within routines. Typically, a function LABEL
starts with , can accept parameters, QUIT
ends with a statement, and has a return value. This is different from subroutines.
Can also return a value. To call a function, the following valid syntax forms are:
Label(args) scopekeyword
zcode
QUIT optionalreturnvalue
Label
- Label name, routine method name.arg
- parameters, is an optional comma-separated list of parameters. If there are no parameters, the parentheses are optional.scopekeyword
- Scope keyword, the optional scope keyword isPublic
(default for subroutines) orPrivate
.code
- Execute code.quit
- Exit the command with a return value.
To call a function, use the following syntax:
d Function^RoutineName(params) /* 忽略返回值 */
s x = $$Function^RoutineName(params)
Function
- function nameRoutineName
- Routine nameparams
- Parameters$$
- If you need to get the return value, you must include$$
syntax.
Routine.mac
Add Fuction
parameterless methods to FuctionParams
subroutine methods with parameters:
Fuction()
w "这是例程函数方法!",!
q "这是例程函数方法!"
FuctionParams(str)
w "这是例程函数方法!"_ "参数:"_str,!
q "这是例程函数方法!"_ "参数:"_str
Ignore the return value calling method:
ClassMethod Routine4()
{
d Fuction^Routine
d FuctionParams^Routine("yx")
}
USER>d ##class(M.Method).Routine4()
这是例程函数方法!
这是例程函数方法!参数:yx
Get the return value calling method:
ClassMethod Routine5()
{
s ret = $$Fuction^Routine
w ret,!
s ret = $$FuctionParams^Routine("yx")
w ret,!
}
USER>d ##class(M.Method).Routine5()
这是例程函数方法!
这是例程函数方法!
这是例程函数方法!参数:yx
这是例程函数方法!参数:yx
Note: The default method scope in subroutines and functions is Public
, if you want to change it to a private scope, you can set the keyword Private
.
Routine.mac
Add FuctionPrivate
private function method in :
FuctionPrivate() Private
w "这是私有方法不允许调用",!
q "这是私有方法不允许调用"
Call this method:
ClassMethod Routine6()
{
d FuctionPrivate^Routine
}
Observable: <NOLINE>
An error is prompted when calling a private subroutine or function method.
Note: When the keyword is added to the method PRIVATE
, it cannot be called by programs other than this routine. An error will be reported <NOLINE>
. Can only be used on current macs.
USER>d ##class(M.Method).Routine6()
d FuctionPrivate^Routine }
^
<NOLINE>zRoutine6+1^M.Method.1
- In functions and subroutines, declared local variables are shared by default, that is, global variables. In this situation, it is easy for variable coverage to occur and create an infinite loop.
FuctionPublicVar()
s x = 5
s y = 10
w "FuctionPublicVar中 x + y:" _ (x + y),!
d FuctionPublicVar1()
q x + y
FuctionPublicVar1()
w "FuctionPublicVar1中 x + y:" _ (x + y),!
q x + y
ClassMethod Routine12()
{
d FuctionPublicVar^Routine
}
USER>d ##class(M.Method).Routine12()
FuctionPublicVar中 x + y:15
FuctionPublicVar1中 x + y:15
In order to scope local variables inside the current method, you need to declare a command on the first line of the function or subroutine method new
to open a new stack to initialize the variables.
Label -Label
Labels are named blocks of code within routines. Does not accept parameters and has no return value.
To call a tag, use the following syntax:
d Label^Routine
Routine.mac
Add Lable
tag method in :
Lable
w "这是一个标签方法",!
Call this method:
ClassMethod Routine7()
{
d Lable^Routine
}
USER>d ##class(M.Method).Routine7()
这是一个标签方法
Note: Even if a return value is added to the label, it cannot actually be obtained.
Routine.mac
Add LableValue
a label method with a return value in :
LableValue
w "有返回值的标签方法",!
q "有返回值的标签方法"
Call this method:
ClassMethod Routine8()
{
s ret = $$LableValue^Routine
w ret,!
}
Since the label does not have parentheses, it prompts that the parameter is wrong and the return value cannot be obtained.
USER>d ##class(M.Method).Routine8()
LableValue
^
<PARAMETER>LableValue^Routine
Common ways to use tags:
- Extract duplicate parts in class methods.
Query
Collect data in and put it into temporaryGlobal
.
Examples are as follows:
The code output
is the usage of tags. No parameters and no return value. The general calling method is d label
actually equivalent to goto
the use of commands.
ClassMethod QueryPersonByAgeExecute(ByRef qHandle As %Binary, pAge As %String = "", count As %Integer = "10") As %Status
{
s pid = $i(^CacheTemp) // 注释1
s qHandle = $lb(0, pid, 0) // 注释2
s index = 1 // 注释3
/* 业务逻辑代码 注释4 */
s id = ""
for {
s id = $o(^M.T.PersonD(id))
q:(id = "")
q:(id > count)
s data = ^M.T.PersonD(id)
s i = 1
s name = $lg(data, $i(i))
s age = $lg(data, $i(i))
continue:(age < pAge)
s no = $lg(data, $i(i))
d output
}
/* 业务逻辑代码 */
q $$$OK
output
s ^CacheTemp(pid, index) = $lb(id, age, name, no) // 注释6
s index = index + 1 // 注释7
}
Another point to note is that if the defined label does not have an exit command, for example quit
, retrun
the command is the label that can be executed sequentially until the exit command is encountered.
Routine.mac
Modify the label method in Lable
:
Lable
w "这是一个标签Lable方法",!
Lable1
w "这是一个标签Lable1方法",!
Lable2
w "这是一个标签Lable2方法",!
Lable3
w "这是一个标签Lable3方法",!
LableValue
w "有返回值的标签方法",!
q "有返回值的标签方法"
Call the method again:
USER>d ##class(M.Method).Routine7()
这是一个标签Lable方法
这是一个标签Lable1方法
这是一个标签Lable2方法
这是一个标签Lable3方法
有返回值的标签方法
process -Procedure
Procedures
- Translated online as: [computer] process; (a text program specially designed to solve a special problem). Some are also called procedures, but here we call them more rigorous processes.
Procedures
Process is a special ObjectScript
method. Procedures are the most powerful block of custom code within a routine, and are also the most recommended form.
Procedure
Procedural syntax form:
label([param[=default]][,...]) [[pubvar[,...]]] [access] {
code
}
-
label
- Process name. -
param
- variables. -
default
- Optional default values for parameters. -
pubvar
- Public variables. -
access
- Optional keyword to declare whether the procedure is public or private. There are two available values:public
,private
. -
code
- Code enclosed in curly braces.
Procedure
Procedures are also called procedure blocks ProcedureBlock
.
Note: ProcedureBlock
It is the default keyword when creating a class, which means that the class method is actually ProcedureBlock
.
To call a procedure, use the following syntax:
d Procedure^RoutineName(params) /* 忽略返回值 */
s x = $$Procedure^RoutineName(params)
- By default, procedures are private, meaning they can only be called from elsewhere in the same routine. If called externally,
<NOLINE>
an error will be prompted.
Routine.mac
Add Procedure
procedure method in :
Procedure(x, y) {
w "x + y = ", x + y,!
q x + y
}
ClassMethod Routine10()
{
s ret = $$Procedure^Routine(2, 8)
w ret,!
}
USER>d ##class(M.Method).Routine10()
s ret = $$Procedure^Routine(2, 8)
^
<NOLINE>zRoutine10+1^M.Method.1
- If the procedure needs to be called externally, you can create a public procedure and use the keyword after the procedure name
Public
. Public procedures can be called from other routines.
Procedure(x, y) Public {
w "x + y = ", x + y,!
q x + y
}
USER>d ##class(M.Method).Routine10()
x + y = 10
10
- Another feature of procedures is the declaration of public variables. Public variables are equivalent to global variables and environment variables, and can be used in all processes. That is, global variables can be used by both the procedure this procedure calls and the procedure that calls this procedure. To define public variables, list them in square brackets after the name of the procedure and its parameters.
Add a procedural method and declare public variables in , local variables Routine.mac
, and call the procedural method:ProceduresPublicVar
ProceduresPublicVar1
a
b
c
ProceduresPublicVar1
ProceduresPublicVar(e, f) [a, b] Public{
s a = 10
s b = 20
s c = 30
w "e + f = ",e + f,!
d ProceduresPublicVar1(9,9)
}
ProceduresPublicVar1(g, h)[a, b] Public{
w "a:", $d(a),!
w "b:", $d(b),!
w "c:", $d(c),!
w g + h,!
w a + b,!
}
When calling the method and observing ProceduresPublicVar1
the public variables a
, b
it is $d
judged that they exist and the local variables c
do not exist.
ClassMethod Routine11()
{
d ProceduresPublicVar^Routine(5, 10)
}
USER>d ##class(M.Method).Routine11()
e + f = 15
a:1
b:1
c:0
18
30
Note: Procedures are more advanced coding than previously provided in subroutines, functions. Procedure parameters are automatically local to the scope within the procedure. No NEW
commands are required to ensure they do not override other values, since they are private to the procedure, and in addition, explicit declaration of public variables allows references to global variables in the application.
The difference between the process and other methods
- Subroutines
Subroutine
are public by default and cannot return values. - Functions
Function
are public by default, and local variables are public variables by default, which will override external variables with the same name and must have a return value. - Routines
Routine
areObjectScript
programs. Can include one or more procedures, subroutines, and functions, as well as any combination of the three. - It is recommended to use procedures
Procedure
because they simplify controlling variable scoping. However, in existing code, you may also see functions and subroutines and need to be able to identify and distinguish them. Functions and subroutines should not be written in new coding.
The following table summarizes the differences between routines, subroutines, functions, and procedures:
Routine | Subroutine | Function | Procedure | |
---|---|---|---|---|
Can accept parameters | no | yes | yes | yes |
Can return value | no | no | yes | yes |
Can be called outside a routine (by default) | yes | yes | yes | no |
Variables defined in it are available after code execution completes | yes | yes | yes | depends on the nature of the variable |
Note: In everyday usage, the term "subroutine subroutine
" is often used to refer to a procedure procedure
, function function
, or subroutine subroutine
.
Class methods -ClassMethod
Class methods are the most commonly used method types in our daily development. They are methods that can be called directly and are called static methods in other languages.
To define class methods in a class, use the following format:
ClassMethod MethodName(Arguments) as Classname [ Keywords]
{
//method implementation
}
-
MethodName
- The name of the method, the method name can be up to180
characters. -
Arguments
- Parameters are separated by commas. -
Classname
- An optional class name indicating the type of value returned by this method. If the method does not return a value,As Classname
the section is omitted. -
Keywords
- represents keywords.
The format for calling class methods is:
##class(Package.Class).Method(Args)
-
Package.Class
- Fully qualified class name. -
Method
- method name. -
Args
- Method parameters. -
##class
- Calling prefix, case-insensitive.
If the called class is under the same level package, or use IMPORT
import package. You can use the class name directly.
##class(Class).Method(Args)
To call methods in the same class to each other or to call methods inherited from the parent class, use the following expression:
..Method(Args)
Define a class method:
ClassMethod ClassMethod(x As %Integer, y As %Integer) As %Integer
{
q x + y
}
Call this class method:
USER>w ##class(M.Method).ClassMethod(5,10)
15
Not ProcedureBlock
Keyword principle
At this point we view the file corresponding to the class method int
:
It can be found that cls
the defined class method is actually int
the process of generating the routine Procedure
. The two correspond one to one. It is also why the scope of the default local variables of class methods are all inside their own methods.
Declaring keywords when defining a class method Not ProcedureBlock
:
ClassMethod ClassMethod1(x As %Integer, y As %Integer) As %Integer [ ProcedureBlock = 0 ]
{
q x + y
}
At this point we view the file corresponding to the class method int
:
It can be found that after cls
adding keywords to the defined class method , the method in the Not ProcedureBlock
generated file is no longer a procedure, but becomes a function or subroutine . As mentioned in the previous section, local variables in functions or subroutines are global variables. That is why you need to add commands in the class method .int
Procedure
Function
Subroutine
Not ProcedureBlock
new
Instance method - Method
Instance methods are actually object methods. As the name suggests, calling this method requires an object. With the object, we can do object-oriented programming. Understanding object orientation is important for programming.
To define instance methods in a class, use the following format:
Method MethodName(arguments) as Classname [ Keywords]
{
//method implementation
}
Note: Instance methods are only related to object classes, because instance methods cannot be executed without an instance of the object, so instance methods are only useful when defined in an object class.
The format for calling instance methods is:
do obj.MethodName()
set value = obj.MethodName(args)
obj
- The declared object is used%New()
to construct the object, which is equivalent to the construction method.MethodName
- method nameargs
- method parameters
Create a simple instance method and call:
Method Method(x As %Integer, y As %Integer) As %Integer
{
q x + y
}
USER>w ##class(M.Method).%New().Method(5,10)
15
It should be noted here that objects can actually call class methods.
USER>w ##class(M.Method).%New().ClassMethod(5,10)
15
Create value, share learning, grow together, and move forward together. Everyone is welcome to provide opinions and communicate together.