ジョブフローの書き方FAQ(その1)

ここでは、Kompira Enterprise のセミナーでご質問頂いたジョブフローの書き方についてご紹介します。


動作確認環境

ソフトウェア バージョン
Kompira Enterprise 1.5.5.post11
OS CentOS 7.8.2003

または

ソフトウェア バージョン
Kompira Enterprise 1.6.2.post4
OS CentOS 7.8.2003

または

ソフトウェア バージョン
Kompira Enterprise 1.6.8
OS CentOS Stream 8

(1) 文字列と数字を “+” したらどうなるの?

Kompira Enterprise では型の異なる変数間の演算はエラーとなります。
また、Kompira Enterprise の変数は、その時に格納されている値をどのような型で評価しているかにより、演算の結果が変わります。

# (a) 数字を "+" すると加算
[
val1 = 123,
val2 = 456
] ->
[result = val1 + val2] ->
print(result) -> # 579
# (b) 文字列を "+" すると文字列結合
[
val1 = "123",
val2 = "456"
] ->
[result = val1 + val2] ->
print(result) -> # 123456
# (c) 数字の文字列化
[
val1 = 123,
val2 = 456
] ->
[result = string(val1) + string(val2)] ->
print(result)-> # 123456
# (d) 文字列の数値化
[
val1 = "123",
val2 = "456"
] ->
[result = int(val1) + int(val2)] ->
print(result) -> # 579
# (e) 数字と文字列を "+" するとエラーになる
[
val1 = 123,
val2 = "456"
] ->
[result = val1 + val2] ->
# Failed to execute binary operation: unsupported operand type(s) for +: 'int' and 'str'
print(result)
# (a) 数字を "+" すると加算 [ val1 = 123, val2 = 456 ] -> [result = val1 + val2] -> print(result) -> # 579 # (b) 文字列を "+" すると文字列結合 [ val1 = "123", val2 = "456" ] -> [result = val1 + val2] -> print(result) -> # 123456 # (c) 数字の文字列化 [ val1 = 123, val2 = 456 ] -> [result = string(val1) + string(val2)] -> print(result)-> # 123456 # (d) 文字列の数値化 [ val1 = "123", val2 = "456" ] -> [result = int(val1) + int(val2)] -> print(result) -> # 579 # (e) 数字と文字列を "+" するとエラーになる [ val1 = 123, val2 = "456" ] -> [result = val1 + val2] -> # Failed to execute binary operation: unsupported operand type(s) for +: 'int' and 'str' print(result)
# (a) 数字を "+" すると加算
[
    val1 = 123,
    val2 = 456
] ->
[result = val1 + val2] -> 
print(result) ->   # 579
 
# (b) 文字列を "+" すると文字列結合
[
    val1 = "123", 
    val2 = "456"
] -> 
[result = val1 + val2] -> 
print(result) ->   # 123456
 
# (c) 数字の文字列化
[
    val1 = 123,
    val2 = 456
] -> 
[result = string(val1) + string(val2)] -> 
print(result)->   # 123456
 
# (d) 文字列の数値化
[
    val1 = "123", 
    val2 = "456"
] -> 
[result = int(val1) + int(val2)] -> 
print(result) ->   # 579
 
# (e) 数字と文字列を "+" するとエラーになる
[
    val1 = 123, 
    val2 = "456"
] -> 
[result = val1 + val2] -> 
# Failed to execute binary operation: unsupported operand type(s) for +: 'int' and 'str'
print(result)  

(a) は2つの変数 val1、val2 の値が整数と評価されるので、足し算されます。
(b) は両方とも文字列なので “+” は文字列結合となります。
(c)、(d) は型の変換の例で、整数を文字列にする場合には string() を、逆に文字列を整数にする場合は int() を用います。
(e) のように、整数 + 文字列の場合は型の異なる変数間の演算となるため実行時エラーとなります。

(2) ジョブフローのパラメータに123と書いた場合と “123” と書いた場合の動きの違いは?

それぞれ整数、文字列で評価されます。

| param_str = "123" |
| param_num = 456 |
print(type(param_str), param_str) -> # String 123 文字列で評価
print(type(param_num), param_num) # Integer 456 整数で評価
| param_str = "123" | | param_num = 456 | print(type(param_str), param_str) -> # String 123 文字列で評価 print(type(param_num), param_num) # Integer 456 整数で評価
| param_str = "123" |
| param_num = 456 |

print(type(param_str), param_str) -> # String 123 文字列で評価
print(type(param_num), param_num) # Integer 456  整数で評価

(3) 変数に型宣言はできないの?

できません。

・ジョブフローのパラメータ指定で入力値に制約を持たせたい場合には、フォーム機能の「フィールド種別」で限定することができます。
参考:「ジョブフローを実行するフォームの作成

・ジョブフロー中で整数を文字列に、文字列を数字に変換したい場合には string()、int() のような組み込み関数を用いて型変換を行ってください。

(4) 変数のスコープはどうなっているの?

・基本的にはジョブフロー内から参照できます。(ジョブフロースコープ)
・{} で囲まれた単純ブロックで定義された変数やループ変数は {} 内に限定されます。 (ブロックスコープ)

[a = 10] ->
print(a) -> # 変数 a はジョブフロースコープ
{ a = "hello" | # この行の変数 a はブロックスコープ {} 内でのみ参照できる
print(a)
} ->
print(a) -> # {} 外なので変数 a はジョブフロースコープ
[
a = 10,
b = 10
] ->
print("Before Loop: ", a, b) ->
# for 文のループ変数 a はブロック {} でのみ参照可能。b はジョブフロースコープ
{ for a in b |
print(a, b) 
} ->
print("After Loop: ", a, b) # {} 外なので変数 a、b はジョブフロースコープ
[a = 10] -> print(a) -> # 変数 a はジョブフロースコープ { a = "hello" | # この行の変数 a はブロックスコープ {} 内でのみ参照できる print(a) } -> print(a) -> # {} 外なので変数 a はジョブフロースコープ [ a = 10, b = 10 ] -> print("Before Loop: ", a, b) -> # for 文のループ変数 a はブロック {} でのみ参照可能。b はジョブフロースコープ { for a in b | print(a, b)  } -> print("After Loop: ", a, b) # {} 外なので変数 a、b はジョブフロースコープ
[a = 10] -> 
print(a) -> # 変数 a はジョブフロースコープ
{ a = "hello" |  # この行の変数 a はブロックスコープ {} 内でのみ参照できる
    print(a)
} ->     
print(a) ->  # {} 外なので変数 a はジョブフロースコープ

[
    a = 10,
    b = 10
] ->
print("Before Loop: ", a, b) ->

# for 文のループ変数 a はブロック {} でのみ参照可能。b はジョブフロースコープ
{ for a in b |
    print(a, b) 
} ->    
print("After Loop: ", a, b) # {} 外なので変数 a、b はジョブフロースコープ  

実行結果

10
hello # ブロックスコープで定義した a の値
10 # ジョブフロースコープで定義した a の値
Before Loop: 10 10 # ジョブフロースコープの a,b
0 10 
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
After Loop: 10 10  # ループを抜け、ジョブフロースコープへ
10 hello # ブロックスコープで定義した a の値 10 # ジョブフロースコープで定義した a の値 Before Loop: 10 10 # ジョブフロースコープの a,b 0 10  1 10 2 10 3 10 4 10 5 10 6 10 7 10 8 10 9 10 After Loop: 10 10  # ループを抜け、ジョブフロースコープへ
10
hello                # ブロックスコープで定義した a の値
10                   # ジョブフロースコープで定義した a の値
Before Loop:  10 10  # ジョブフロースコープの a,b 
0 10              
1 10
2 10
3 10
4 10
5 10
6 10
7 10
8 10
9 10
After Loop:  10 10  # ループを抜け、ジョブフロースコープへ

また、バージョン1.6系では while、if、try ブロックなどで新規代入された変数をブロック外で参照することはできません。

{ if true |
[a = 10] # ブロック内でのみ参照可能
} ->
print(a) # Variable "a" is not defined
{ if true | [a = 10] # ブロック内でのみ参照可能 } -> print(a) # Variable "a" is not defined
{ if true | 
    [a = 10] # ブロック内でのみ参照可能
} ->     
print(a)  # Variable "a" is not defined

(5) 配列要素を文字列中に展開する方法はあるか?

配列要素を直接文字列の中に埋め込むことはできないため、ブロックスコープか “%” 演算子を使用して表示します。

| array = ["a", "b", "c"] |
# print は複数の値を引数にできるため、引数として個別に指定する
print("2nd element:", array[1]) ->
# 要素に $ をつけると、配列 array と文字列 "[1]" と解釈してしまう
print("2nd element: $array[1]") ->
{ elem = array[1] |
print("2nd element: $elem") # ブロックスコープを使用する例
} ->
print("2nd element: %elem" % {elem=array[1]}) # "%" 演算子を使用する例
| array = ["a", "b", "c"] | # print は複数の値を引数にできるため、引数として個別に指定する print("2nd element:", array[1]) -> # 要素に $ をつけると、配列 array と文字列 "[1]" と解釈してしまう print("2nd element: $array[1]") -> { elem = array[1] | print("2nd element: $elem") # ブロックスコープを使用する例 } -> print("2nd element: %elem" % {elem=array[1]}) # "%" 演算子を使用する例
| array = ["a", "b", "c"] |

# print は複数の値を引数にできるため、引数として個別に指定する 
print("2nd element:", array[1]) ->

# 要素に $ をつけると、配列 array と文字列 "[1]" と解釈してしまう                   
print("2nd element: $array[1]") ->                   
{ elem = array[1] |
    print("2nd element: $elem") # ブロックスコープを使用する例                    
} ->  
print("2nd element: %elem" % {elem=array[1]}) # "%" 演算子を使用する例

実行結果

2nd element: b
2nd element: ['a', 'b', 'c'][1]
2nd element: b
2nd element: b
2nd element: b 2nd element: ['a', 'b', 'c'][1] 2nd element: b 2nd element: b
2nd element: b
2nd element: ['a', 'b', 'c'][1]
2nd element: b
2nd element: b

(6) プレイスホルダーに複数の辞書変数から置換する方法は?

文字列 % 辞書変数の “%” は演算子であり、文字列に近い方から適用されます。

[
dict1 = {"k1": "v1", "k2": "v2", "k3": "v3"},
dict2 = {"k4": "v4", "k5": "v5", "k3": "ZZ"}
] ->
# (a) dict1 で k1 を入れ替えた後、dict2 で k5 を入れ替え
[message = "%k1 と %k5" % dict1 % dict2] ->
print(message) -> # v1 と v5
# (b) dict1、dict2で同じキー: 先に dict1 で2つの k3 が入れ替わってしまう
[message = "%k3 と %k3" % dict1 % dict2] ->
print(message) # v3 と v3
[ dict1 = {"k1": "v1", "k2": "v2", "k3": "v3"}, dict2 = {"k4": "v4", "k5": "v5", "k3": "ZZ"} ] -> # (a) dict1 で k1 を入れ替えた後、dict2 で k5 を入れ替え [message = "%k1 と %k5" % dict1 % dict2] -> print(message) -> # v1 と v5 # (b) dict1、dict2で同じキー: 先に dict1 で2つの k3 が入れ替わってしまう [message = "%k3 と %k3" % dict1 % dict2] -> print(message) # v3 と v3
[
    dict1 = {"k1": "v1", "k2": "v2", "k3": "v3"},
    dict2 = {"k4": "v4", "k5": "v5", "k3": "ZZ"}
] ->

# (a) dict1 で k1 を入れ替えた後、dict2 で k5 を入れ替え
[message = "%k1 と %k5" % dict1 % dict2] ->
print(message) ->   # v1 と v5

# (b) dict1、dict2で同じキー: 先に dict1 で2つの k3 が入れ替わってしまう
[message = "%k3 と %k3" % dict1 % dict2] -> 
print(message)      # v3 と v3

(a) の場合、最初に dict1 の “%k1” が置換されます。後ろのキー “%k5” は dict1 にキーが無いため、置換されません。
2つ目の % 演算子で dict2 のキーで “%k5” が置換されます。

つまり、以下のように文字列が置換されて行きます。

"%k1 と %k5" % dict1 % dict2
"v1 と %k5" % dict2
"v1 と v5"
"%k1 と %k5" % dict1 % dict2 "v1 と %k5" % dict2 "v1 と v5"
"%k1 と %k5" % dict1 % dict2
"v1 と %k5" % dict2
"v1 と v5"

(b) では dict1、dict2 ともに k3 というキーを持ちます。これも (a) と同じルールで置換していくと以下のようになります。

"%k3 と %k3" % dict1 % dict2
"v3 と v3" % dict2 # 両方ともdict1で置換され、文字列中にキーが残らない
"v3 と v3"
"%k3 と %k3" % dict1 % dict2 "v3 と v3" % dict2 # 両方ともdict1で置換され、文字列中にキーが残らない "v3 と v3"
"%k3 と %k3" % dict1 % dict2
"v3 と v3" % dict2 # 両方ともdict1で置換され、文字列中にキーが残らない
"v3 と v3"

このようにして、複数の辞書変数を用いて文字列置換を行うことができます。

TOP