콘텐츠로 이동

TBEL 언어 가이드

이 가이드는 TBEL 문법, 데이터 유형, 컬렉션, 흐름 제어 구문을 다룹니다. 내장 유틸리티 함수 전체 목록은 헬퍼 함수 레퍼런스를 참고하세요.

TBEL은 MVEL을 바탕으로 합니다. 몇 가지 문법 규칙이 JavaScript와 다릅니다.

  • foreach를 씁니다(for...of / for...in 대신). 전통적인 for 반복문도 지원합니다.
  • 명시적인 if 문 밖에서 삼항 식을 쓸 때는 괄호로 감싸야 합니다.
  • 여러 문장은 세미콜론으로 구분합니다. 마지막 문장 뒤의 세미콜론은 생략할 수 있습니다.

컨텍스트 객체의 속성에 바로 접근합니다.

msg.temperature
return (msg.temperature > 10 && msg.temperature < 20) ||
(msg.humidity > 10 && msg.humidity < 60);

표준 연산자 우선순위가 적용됩니다. 실행 순서는 괄호로 정합니다.

문장은 세미콜론으로 구분합니다. 마지막 문장의 값이 스크립트의 반환 값입니다.

var a = 2;
var b = 3;
a + b; // returns 5

TBEL은 호환되는 유형을 자동으로 변환합니다.

"123" == 123; // true

맵은 인라인으로 만들며, 메모리 추적 기능이 내장된 자체 구현을 씁니다.

var map = {"temperature": 42, "nested": "508"};
map.temperature // dot notation
map.get("temperature") // method call
map["temperature"] // bracket notation

안전 탐색 연산자를 쓰면 없는 키에서 NullPointerException이 나지 않습니다.

if (map.?nonExistingKey.smth > 10) { }

명시적인 entrySet():

foreach (element : map.entrySet()) {
element.getKey(); // or element.key
element.getValue(); // or element.value
}

암묵적(값을 반복):

foreach (value : map) {
// process each value
}
map.temperature = 0; // set value
map.put("humidity", 73); // add entry
map.putIfAbsent("temperature1", 73); // add if missing
map.replace("temperature", 56); // replace value
map.replace("temperature", 56, 42); // conditional replace
map.remove("temperature"); // remove entry
var keys = map.keys(); // get all keys
var values = map.values(); // get all values
var size = map.size(); // entry count
var memorySize = map.memorySize(); // memory in bytes
map.sortByKey(); // sort by key in-place
var sorted = map.sortByValue(); // sort by value in-place
map.putAll({"test": 12, "input": {"http": 130}}); // merge another map
isMap(map); // type check → true
var original = {};
original.humidity = 73;
var unmodifiable = original.toUnmodifiable();
unmodifiable.put("temperature1", 96); // throws error: Map is unmodifiable

리스트는 메모리 추적 기능이 있는 자체 구현을 씁니다. 인라인 생성만 허용합니다.

var list = ["A", "B", "C"];
list[0]; // "A"
list.size(); // 3
foreach (item : list) {
var smth = item;
}
for (var i = 0; i < list.size; i++) {
var smth = list[i];
}
list.add(3, "sensor"); // insert at index
list.push("sensor"); // append to end
list.unshift("r"); // prepend to start
list.addAll(["sensor", 4, 67]); // append all elements
list.addAll(2, ["x", "y"]); // insert all at index
var removed = list.remove(2); // remove by index
list.remove("C"); // remove by value
var first = list.shift(); // remove and return first
var last = list.pop(); // remove and return last
var spliced = list.splice(3); // remove from index to end
list.splice(2, 2); // remove 2 elements at index 2
list.splice(1, 4, "start", 5, "end"); // remove 4, insert replacements
list.set(3, "65"); // replace at index
list[1] = "98"; // bracket assignment
list.sort(); // ascending sort (default)
list.sort(true); // ascending
list.sort(false); // descending
list.reverse(); // reverse in-place
list.fill(67); // fill entire list
list.fill(4, 1); // fill from index 1
list.fill(2, 1, 4); // fill range [1, 4)

다음 연산은 원본을 바꾸지 않고 새 리스트를 돌려줍니다.

var sorted = list.toSorted(); // new sorted list (ascending)
var sortedDesc = list.toSorted(false); // new sorted list (descending)
var reversed = list.toReversed(); // new reversed list
var sliced = list.slice(0, 2); // new sublist [0, 2)
var replaced = list.with(1, 69); // new list with index 1 replaced
var merged = list.concat(otherList); // new concatenated list
var str = list.join(); // join elements into string
var spliced = list.toSpliced(1, 0, "Feb"); // new list with splice applied
var length = list.length();
var memorySize = list.memorySize();
var idx = list.indexOf("B", 1); // first index of "B" starting from 1
list.validateClazzInArrayIsOnlyNumber(); // validate numeric content
isList(list); // type check → true
var original = [];
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: List is unmodifiable

세트는 중복을 허용하지 않는 순서 있는 컬렉션입니다.

var set1 = toSet(["B", "A", "C", "A"]); // from list (3 elements — "A" deduplicated)
var set2 = createSet(); // empty set
var set3 = createSet(["A", "B", "C"]); // from list
var set4 = newSet(); // empty set
foreach (item : set) {
// process item
}
var arr = set.toArray();
for (var i = 0; i < set.size; i++) {
var item = arr[i];
}
set.add(35); // add single element (returns true if new)
set.addAll(otherSet); // merge another set
set.remove(4); // remove element
set.clear(); // remove all elements
set.contains("A"); // membership check → true/false
set.size(); // element count
set.toArray(); // convert to array
set.toList(); // convert to list
set.clone(); // shallow copy
isSet(set); // type check → true
set.sort(); // ascending in-place
set.sort(true); // ascending in-place
set.sort(false); // descending in-place
var sorted = set.toSorted(); // new sorted set (ascending)
var sortedDesc = set.toSorted(false); // new sorted set (descending)
var original = createSet();
original.add(0x67);
var unmodifiable = original.toUnmodifiable();
unmodifiable.add(0x35); // throws error: Set is unmodifiable

TBEL은 기본형에만 배열을 지원합니다. 문자열 인덱싱은 문자를 돌려주고, 문자열 배열은 자동으로 리스트로 바뀝니다.

var array = new int[3];
array[0] = 1;
array[1] = 2;
array[2] = 3;
var str = "My String";
var ch = str[0]; // 'M'
isArray(array); // true

사용자 지정 함수 예:

function sum(list) {
var result = 0;
for (var i = 0; i < list.length; i++) {
result += list[i];
}
return result;
}
var total = sum(array); // 6

작은따옴표나 큰따옴표:

"This is a string literal"
'This is also string literal'

이스케이프 시퀀스: \\, \n, \r, \u#### (유니코드), \### (8진수).

125 // decimal integer
0353 // octal
0xAFF0 // hexadecimal
10.503 // double
94.92d // explicit double
14.5f // float
104.39484B // BigDecimal
8.4I // BigInteger
true
false
null
nil // alias for null

TBEL에서는 java.util과 java.lang의 Java 클래스를 제한적으로 쓸 수 있습니다.

var foo = Math.sqrt(4); // 2.0

Integer.toString()으로 숫자를 16진수, 8진수, 2진수로 바꿉니다.

var b16 = Integer.toString(0x1A, 16); // "1a"
var b10 = Integer.toString(0x1A, 10); // "26"
var b8 = Integer.toString(0x1A, 8); // "32"
var b2 = Integer.toString(0x1A, 2); // "11010"

음수:

var i16 = Integer.toString(-255, 16); // "-ff"
var i10 = Integer.toString(-255, 10); // "-255"
var i8 = Integer.toString(-255, 8); // "-377"
var i2 = Integer.toString(-255, 2); // "-11111111"

float와 double의 16진수 문자열:

var f0 = 7823764.8374;
var f16 = Float.toHexString(f0); // "0x1.dd8654p22"
var dd0 = 99993219.156013e-002;
var dd16 = Double.toHexString(dd0); // "0x1.e83f862142b5bp19"

long 변환:

var l16 = Long.toString(9223372036854775807, 16); // "7fffffffffffffff"
var l10 = Long.toString(9223372036854775807, 10); // "9223372036854775807"
var l8 = Long.toString(9223372036854775807, 8); // "777777777777777777777"
var l2 = Long.toString(9223372036854775807, 2); // "111...111" (63 ones)

Java 클래스의 새 인스턴스를 만들 수 없습니다.

java.util.Collections.reverse(list); // allowed — static method call
list = new java.util.ArrayList(); // NOT allowed — constructor call
var metadataStr = JSON.stringify(metadata);
var metadata = JSON.parse(metadataStr);
if (temperature > 0) {
return "Greater than zero!";
} else if (temperature == -1) {
return "Minus one!";
} else {
return "Something else!";
}
temperature > 0 ? "Yes" : "No";
var numbers = [1, 2, 3];
var sum = 0;
foreach (n : numbers) {
sum += n;
}

문자열은 문자 단위로 반복할 수 있습니다.

foreach (c : "ABCDEFGHIJKLMNOPQRSTUVWXYZ") {
// process each character
}
var sum = 0;
for (var i = 0; i < 100; i++) {
sum += i;
}
while (isTrue()) {
doSomething();
}
until (isFalse()) {
doSomething();
}
do {
x = something();
} while (x != null);
do {
x = something();
} until (x == null);