반응형
<출처 : http://javaora.tistory.com/entry/Learning-the-JavaFX-Script-Programming-Language-Lesson-7-Expressions >

목차
- 블록구문(Block Expression)
- if문(The if Expression)
- Range구문(Range Expression)
- for문(The for Expression)
- while문(The while Expression)
- break & continue구문(The break and continue Expression)
- 예외처리구문(The throw, try, catch and finally Expression)


* 블록구문

블록구문은 중괄호로 둘러싸인 선언문과 구문들의 집합이다. 블록구문의 값은 가장 마지막 구문의 값이다. 만일 블록구문에 어떠한 (var나 def 같은) 구문도 포함되어 있지 않다면, 그 블록구문은 Void 타입니다. 

var nums = [5, 7, 3, 9];
var total = {
var sum = 0; 
for (a in nums) { 
sum += a // num의 값을 모두 더한다.
}; 
sum; // 합계인 sum을 리턴한다.
println("Total is {total}.");

Total is 24.

위 예제에서 total 다음에 나오는 중괄호 부분이 블럭구문이다.


* if문

if문은 그동안 자바나 다른 언어를 통해 한번쯤 보았을 익숙한 구문이다. if 다음에 조건식을 입력하고 이것이 참일때 아래 구문이 실행된다. 첫번째 조건이 참이 아닐 경우 다른조건을 줄때는 else-if 를, 조건이외의 경우에는 else 를 사용하는 방식 또한 동일하다.

def age = 8;
var ticketPrice;
if (age < 5 ) {
     ticketPrice = 0; // age가 5보다 작을 경우
} else if (age < 12 or age > 65) {
     ticketPrice = 5;  // age가 12보다 작거나 65보다 큰 경우
} else {
     ticketPrice = 10;  // 위 조건을 제외한 모든 경우
}
println("Age: {age} Ticket Price: {ticketPrice} dollars.");

Age: 8 Ticket Price: 5 dollars.

위 코드는 아래와 같이 간결한 조건의 표현으로 정리 될 수 있다.

ticketPrice = if (age < 5) 0 else if (age > 5 and age < 12) 5 else 10;


* Range문

시퀀스 레슨에서 연이어지는 숫자의 시퀀스는 짧은 방식으로 표기하는 것을 배웠었다.

var num = [0..5];

기술적으로 말하자면, 위 [0..5] 와 같은 방식을 Range문 이라 한다. 위 코드에선 숫자사이의 간격(interval)은 1 이다, 하지만 step 이라는 키워드를 사용하여 이를 다른 간격만큼 증가하도록 조절 할 수 있다. 가령 1 에서 10 사이의 홀수(odd number)인 시퀀스를 만드는 방법은 아래와 같다.

var nums = [1..10 step 2];
println(nums);

출력한 결과는 다음과 같다.

[ 1, 3, 5, 7, 9 ]

감소하는 range 문을 만들기 위해선 첫번째 값이 두번째 값보다 커야 하며 step 키워드 다음에 나오는 간격(interval)은 음수(negative)여야 한다.

var nums = [10..1 step -1];
println(nums);

결과는 다음과 같다.

[ 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 ]

만일 감소하는 방식의 range문을 사용하면서 간격값으로 음수를 사용하지 않으면 컴파일시 다음과 같은 에러가 발생한다.

D:\workspace>javafxc range.fx
range.fx:1: warning: empty sequence range literal, probably not what you meant.
var nums = [10..1 step 1];
^
1 warning

D:\workspace>javafx range
[ ]

만일 step 키워드 와 증감값(interval)을 정확히 사용하지 않는다면 위와 같이 빈 시퀀스(empty sequence)를 받게 될것이다.


* for문

또 다른 시퀀스와 관련된 표현으로는 for문이 있다. for문은 시퀀스 아이템을 통한 루프 기능을 제공한다.

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

for (day in days) {
     println(day);
}

결과는 다음과 같다.

Mon
Tue
Wed
Thu
Fri
Sat
Sun

위 코드에서 보듯이 for문은 for로 시작하며, 조건의 내용을 살펴보면 days는 시퀀스의 이름을 day 는 시퀀스 만큼 돌아가는 루프에서 현재 아이텀을 의미한다.

여기서 day 변수는 따로이 선언할 필요는 없으며, 그 범위는 해당 루프로 한정된다.

위 예에서 for문은 별도의 리턴 값이 없었지만, for문은 시퀀스를 리턴시킬 수 있다. 아래의 두가지 예를 보면 하나의 시퀀스를 통해 또 다른 시퀀스를 만들어 내는 것을 볼 수 있다.

// 결과 시퀀스는 본래 시퀀스 값의 제곱값들로 이루어진 시퀀스를 리턴받는다.
var squares = for (i in [1..10]) i*i;

// 결과 시퀀스는 ["MON", "TUE", "WED", and so on...] 와 같이 대문자로 이루어진다.
var capitalDays = for (day in days) day.toUpperCase();

위 예제에서 사용된 toUpperCase() 는  String 객체의 함수로 API 문서를 통해 확인 해볼 수 있다.


* while문

또 다른 루프문으로는 while문이 있다. while문은 for와는 달리 시퀀스의 아이템들로 작동하지 않으며, 주어진 조건이 false 일때 까지 루프를 돈다. while문의 리턴 타입은 Void 이다.


var count = 0;
while (count < 10) {
    println("count == {count}");
    count++;
}

결과는 아래와 같다.

count == 0
count == 1
count == 2
count == 3
count == 4
count == 5
count == 6
count == 7
count == 8
count == 9

위 예제 코드를 보면 변수 count 를 선언하고 값으로 0을 넣은 후 조건이 만족하지 않을 때까지 루프가 돌게 된다. 해당 조건은 count가 10보다 작은 동안이며, 값이 true인 경우 count의 값을 프린트하고  count 값을 1 증가 시킨다. 그리고 다시 조건을 확인하고 그 값이 false 일 때까지 반복한다.


* break 와 continue구문

break 와 continue구문은 루프문들과 관련이 있다. 이 두 구문들은 루프의 반복작업에 영향을 미친다. break 는 전체 루프를 종료시키고, 그에 반해 continue 는 이번 루프만(이번 반복작업만) 건너 뛰고 진행된다. break 와 continue 의 리턴 타입은 Void 이다.

for (i in [0..10]) {
     if (i > 5) { // i 가 5보다 크면 for문 전체를 종료한다.
          break;
     }

     if (i mod 2 == 0) { // i 가 짝수이면 건너 뛴다.
          continue;
     }

     println(i); // 위 continue문을 통해 결과적으로 5이하의 홀수만 프린트 한다.
}

결과는 아래와 같다.

if (i mod 2 == 0) {
continue;
}



* 예외처리구문(The throw, try, catch and finally Expression)

프로그램 구동 중에 어떤 문제가 발생하는 경우 우리는 이를 Exception이라 한다.(일반적인 의미의 Error라 보면 된다.) 가령 프로그램상에서 특정 파일을 찾아 읽는 코드가 있는데 해당 path에 해당 파일이 존재하지 않는 경우 Exception이 발생된다.

아래 예는 함수에서 Exception을 던지는 것을 정의하는 모습니다.

import java.lang.Exception;

foo();

println("The script is now executing as expected... ");

function foo() {
     var somethingWeird = false;

     if(somethingWeird){
          throw new Exception("Something weird just happened!");
     } else {
          println("We made it through the function.");
     }
}

위 스크립트를 실행하면 아래와 같은 결과가 나온다.

We made it through the function.
The script is now executing as expected...


하지만 somethingWeird 값이 true 로 바뀐다면 다음과 같은 Exception이 발생할 것이며, 충돌로 프로그램에 악영향을 끼친다.

Exception in thread "main" java.lang.Exception: Something weird just happened!
at exceptions.foo(exceptions.fx:10)
at exceptions.javafx$run$(exceptions.fx:3)


이와 같은 충돌을 방지하여면 foo() 함수가 호출되는 부분에 try/catch 구문으로 감싸주는 것이 필요하다.

try {
     foo();
} catch (e: Exception) {
     println("{e.getMessage()} (but we caught it)");
}

이렇게 try/catch문을 사용하면 해당 함수 호출시 Exception이 발생하면 catch 부분에서 이를 잡아내서 그 내부 구문을 실행한다. 이제 프로그램을 다시 실행하면 아래와 같은 결과가 나온다.

Something weird just happened! (but we caught it)
The script is now executing as expected...


finally 구문은 try/catch 다음에 꼭 실행되는 부분으로 이부분을 통해 자원해제등을 수행하거나 그외 필요한 마무리 작업을 기술한다.

try {
     foo();
} catch (e: Exception) {
     println("{e.getMessage()} (but we caught it)");
} finally {
     println("We are now in the finally expression...");
}

결과는 다음과 같다.

Something weird just happened! (but we caught it)
We are now in the finally expression...
The script is now executing as expected...

반응형
<출처 : http://javaora.tistory.com/entry/Learning-the-JavaFX-Script-Programming-Language-Lesson-6-Operators >

연산자(Operator)는 한/두개의 피연산자로 특정 연산작업을 수행하고 결과를 되돌리는(return) 특별한 기호다. 

목차
- 할당 연산자(Assignment Operators)
- 수리 연산자(Arithmetic Operators)
- 단항 연산자(Unary Operators)
- 비교 & 관계 연산자(Equality and Relational Operators)
- 조건 연산자(Conditional Operators)
- 형 비교 연산자(Type Comparison Operators)


* 할당 연산자

할당연산자 "=" 은 앞으로 보게될 가장 일반적으로 사용되어지는 연산자이다. 이 연산자는 연산자 좌측 변수에 우측 피연산자의 값을 할당한다.

result = num1 + num2;
days = ["Mon","Tue","Wed","Thu","Fri"];


* 수리 연산자

수리연산자는 4칙연산(+, -, *, /)을 수행하며, "mod" 연산자는 나눗셈을 하고 남은 값(remainder)을 결과로 리턴한다.

var result = 1 + 2; // result is now 3
println(result);

result = result - 1; // result is now 2
println(result);

result = result * 2; // result is now 4
println(result);

result = result / 2; // result is now 2
println(result);

result = result + 8; // result is now 10
println(result);

result = result mod 7; // result is now 3
println(result);

더불어 산술연산자와 할당연산자를 합친 복합할당자(compound assignment) 를 사용 할 수도 있다. 예를들면, result += 1; 은 result = result + 1 과 동일한 result 에 1을 더한 값을 다시 result 에 할당하는 작업을 수행한다. 단 "mod" 연산자는 복합할당자 형식으로 사용 할 수 없다. 예를 들어, result 를 2로 나눈 나머지 값을 다시 result 에 할당하기 위해선 result = result mod 2; 와 같이 작성해야만 한다.

var result = 0;
result += 1;
println(result); // result is now 1

result -= 1;
println(result); // result is now 0

result = 2;
result *= 5; // result is now 10
println(result);

result /= 2; // result is now 5
println(result);


* 단항 연산자

대부분의 연산자는 두개의 피연산자를 필요로 한다. 단항연산자는 하나의 피연산자를 사용하여 값을 증가(incrementing)와 감소(decrementing) 시키거나 음수(negaring a number)화 시키거나 boolean 값을 역으로 바꾸는 연산작업을 수행한다.

-   : Unary minus operator; negates a number
++  : Increment operator; increments a value by 1
--  : Decrement operator; decrements a value by 1
not : Logical complement operator; inverts the value of a boolean

var result = 1; // result is now 1

result--;  // result is now 0
println(result);

result++; // result is now 1
println(result);

result = -result; // result is now -1
println(result);

var success = false;
println(success); // false
println(not success); // true

증가/감소 연산자는 피연산자의 전처리(before, prefix)와 후처리(after, postfix) 적용이 가능하다. result++; 와 ++result; 는 둘 다 result의 값을 1 증가시키는 역할을 한다. 전처리(++result)의 경우 값을 사용하는 시점에서 이미 1을 증가시킨 상태임에 비해 후처리(result++)의 경우 값을 사용하는 시점에서는 원래 증가전 값을 사용하며 사용한후 이를 1 증가시킨다. 설명은 복잡해 보이지만 실제 예를 보면 간단하게 이해 할 수 있다.

var result = 3;
result++;
println(result); // result is now 4
++result;
println(result); // result is now 5
println(++result); // result is now 6
println(result++); // this still prints prints 6!
println(result); // but the result is now 7


* 비교 & 관계 연산자

비교 관계 연산자는 하나의 연산자와 다른 연산자를 비교하여 값의 산술적 크기가 큰지, 작은지, 같은지, 같지 않은지를 비교하며, 비산술적인 형식(예를 들면 String)의 값이 같은지 같지않은지를 비교한다.

==	equal to
!=	not equal to
>	greater than
>=	greater than or equal to
<	less than
<=	less than or equal to
 
예를 보자.

def num1 = 1;
def num2 = 2;
def str1 = "A";
def str2 = "A";
def str3 = "B";

println(num1 == num2); // prints false
println(num1 != num2); // prints true
println(num1 > num2);  // prints false
println(num1 >= num2); // prints false
println(num1 < num2);  // prints true
println(num1 <= num2); // prints true

println(str1 == str2); // prints true
println(str1 != str2); // prints false
println(str1 == str3); // prints false
println(str1 != str3); // prints true


* 조건 연산자

조건 "and"와 조건 "or" 연산자는 주어진 2개의 boolean 표현의 조건연산을 수행한다. "and" 연산자는 "and" 연산자 좌측과 우측의 조건이 모두 true 일때만 수행되며, "or" 연산자는 좌측이든 우측이든 둘중 하나가 true 이면 수행된다. 

def username = "foo";
def password = "bar";

if ((username == "foo") and (password == "bar")) {
     println("Test 1: username AND password are correct");
}

if ((username == "") and (password == "bar")) {
     println("Test 2: username AND password is correct");
}

if ((username == "foo") or (password == "bar")) {
     println("Test 3: username OR password is correct");
}

if ((username == "") or (password == "bar")) {
     println("Test 4: username OR password is correct");
}

결과는 다음과 같다.

Test 1: username AND password are correct
Test 3: username OR password is correct
Test 4: username OR password is correct


* 형 비교 연산자

"instance of" 연산자는 객체의 특정타입을 비교한다. 이를 통해 특정 객체가 어떤 클래스를 통해 인스턴스화 되었는지 알수있다(비교 할 수 있다.)

def str1="Hello";
println(str1 instanceof String); // prints true
def num = 1031;
println(num instanceof java.lang.Integer); // prints true

지금은 잘 모르겠지만 이 연산자가 차후 클래스와 상속에 대해 배운다면 유용한 것임을 알게 될것이다.

반응형
<출처 : http://javaora.tistory.com/entry/Learning-the-JavaFX-Script-Programming-Language-Lesson-5-Sequences >

목차
- 사퀀스(Sequence) 만들기
- Boolean Expression 과 시퀀스 만들기
- 시퀀스 아이템(Item) 접근하기
- 시퀀스에 아이템 인서트 하기
- 시퀀스의 아이템 삭제하기
- 시퀀스의 아이템 거꾸로 정렬 하기
- 시퀀스 비교하기
- 시퀀스 슬라이스(Slice) 사용하기

* 사퀀스(Sequence) 만들기

JavaFX에서는 앞서 배운 5개의 기본적인 데이터 타입 외에 추가적으로 시퀀스(Sequence)라 불리우는 데이터 구조(data structure) 를 제공한다. 시퀀스는 순서가 있는 List 객체(Ordered List) 를 나타내며, 시퀀스의 내부의 각각의 객체를 아이템(item) 이라 한다. 시퀀스는 대괄호([], bracket)를 사용하여 선언하며, 각각의 아이템은 콤마(,)로 구분한다.

var weekDays = ["Mon","Tue","Wed","Thu","Fri"];

선언된 시퀀스는 weekDays라 명명된 변수에 할당된다. 개별 아이템이 String 으로 선언되어 있어 우리가 "String 형식의 시퀀스(sequence of strings)"를 생성하려는 의도를 컴파일러는 알게 된다. 만일 시퀀스가 Integer들로 선언되었다면 컴파일러는"Integer 형식의 시퀀스"가 우리가 원하는 것임을 알게 된다.

물론 명시적으로 시퀀스의 아이템 형(type)을 지정 할 수도 있다. 형 지정 방식은 선언하는 변수명 다음에 콜론(:) 과 함께 원하는 데이터타입을 적어주고, 끝에는 대괄호를 사용한다.

var weekDays: String[] = ["Mon","Tue","Wed","Thu","Fri"];

시퀀스는 또한 다른 시퀀스를 포함한 중첩된 시퀀스를 만들 수도 있다.

var days = [weekDays, ["Sat","Sun"]];

이렇게 중첩된 시퀀스의 경우 컴파일러는 자동으로 내포된 시퀀스들의 아이템을 꺼내어 등가의 중첩없는(혹은 평평한, flatten) 시퀀스로 만든다.(위 와 아래의 표현은 동일하다.)

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

또한 약식 표기법도 가능하다. 이는 순차적으로 증/감하는 숫자로 시퀀스를 구성하기 쉽게 해준다. 숫자 1 부터 100 까지로 구성되는 시퀀스를 생성하기 위한 방법은 아래와 같다.

var nums = [1..100];


* Boolean Expression 과 시퀀스 만들기

boolean expression 과 서술형 방식을 통해 기존의 시퀀스을 가지고 하위 서브셋(subset)을 구성하여 새로운 시퀀스를 선언 할 수도 있다.

아래 예에서 두번째 시퀀스는 첫번째 시퀀스에 기반을 두고 있으나 오직 숫자가 2보다 큰것만 포함하고 있다.

var nums = [1,2,3,4,5];
var numsGreaterThanTwo = nums[n | n > 2];
print();


결과 : [ 3, 4, 5 ]

var nums = [1,2,3,4,5];
var numsGreaterThanTwo = for (n in nums where n > 2) n ;
print();


결과 : [ 3, 4, 5 ]


* 시퀀스 아이템(Item) 접근하기

시퀀스의 아이템에 대한 접근은 인덱스(index)를 통해 접근하며, 인덱스의 시작은 0 이다. 사용방법은 먼저 시퀀스의 이름을 쓰고, 대괄호를 사용하며 그 안에 인덱스 값을 넣는다.

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

println(days[0]);
println(days[1]);
println(days[2]);
println(days[3]);
println(days[4]);
println(days[5]);
println(days[6]);

그 결과는 다음과 같다.

Mon
Tue
Wed
Thu
Fri
Sat
Sun

또한 시퀀스의 크기를 구하기 위해 sizeof 키워드를 사용하며, 사용방식은 sizeof 다음에 시퀀스의 변수명을 적어준다.

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];
println(sizeof days);

위 코드의 실행결과는 7 이다.


* 시퀀스에 아이템 인서트 하기

insert 키워드는 특정 값을 into 키워드 다음의 시퀀스로 값을 끼워넣는 역할을 한다. 이때 before 와 after 키워드를 사용하여 특정 위치를 지정 할 수 있다.
Note : 사실 시퀀스는 불변형(immutable)이다. 이는 한번 생성되면 그 값이 변하지 않는다는 뜻이다. 그래서 만약 시퀀스에 insert나 delete 작업이 이루어진다면, 새로이 시퀀스를 생성하고 주어진 작업을 처리하고 이를 변수에 재 할당하는 작업이 이루어진다.
var days = ["Mon"];
insert "Tue" into days;
insert "Fri" into days;
insert "Sat" into days;
insert "Sun" into days;

print(days);

이를 실행하면 아래와 같은 결과가 나온다.

[ "Mon", "Tue", "Fri", "Sat", "Sun" ]

before 키워드를 이용하여 insert 될 element의 위치를 지정해보자.

insert "Thu" before days[2];
print(days);

이를 실행하면 아래와 같은 결과가 나온다.

[ "Mon""Tue", "Thu", "Fri""Sat""Sun" ]

after 키워드를 이용하여 insert 될 element의 위치를 지정해보자.

insert "Wed" after days[1];
print(days);

이를 실행하면 아래와 같은 결과가 나온다.

[ "Mon""Tue", "Wed", "Thu", "Fri""Sat""Sun" ]


* 시퀀스의 아이템 삭제하기

delete 와 from 키워드를 이용하여 시퀀스로 부터 쉽게 삭제가 가능하다.

delete "Sun" from  days;
print(days);

이를 실행하면 아래와 같은 결과가 나온다.

[ "Mon""Tue", "Wed", "Thu", "Fri""Sat" ]

또한 인덱스를 이용한 삭제도 가능하다.

delete days[0];
print(days);

이를 실행하면 아래와 같은 결과가 나온다.

[ "Tue", "Wed", "Thu", "Fri""Sat" ]

시퀀스의 모든 아이템을 삭제하려면 delete 키워드 다음에 시퀀스 변수명을 넣으면 된다.

delete days; // Delete all data

주의할 것은 delete 키워드는 단지 시퀀스 변수 내의 아이템을 삭제하는 것이지 변수 자체를 삭제하는 것은 아니다.

* 시퀀스의 아이템 거꾸로 정렬 하기

시퀀스의 순서를 쉽게 바꿀 수 있다.

var nums = [1..5];
reverse nums; // returns [5, 4, 3, 2, 1]


* 시퀀스 비교하기

시퀀스는 비교 가능하며, 동일한 시퀀스는 그 길이와 아이템과 순서가 동일한 것을 의미한다.

var seq1 = [1,2,3,4,5];
var seq2 = [1,2,3,4,5];
println(seq1 == seq2); // true

seq1 = [1,2,3,4,5];
seq2 = [1,2,3,4,5,6]; // 아이템이 한가지 증가했다. 순서는 바뀌지 않았다.
println(seq1 == seq2); // false

seq1 = [1,2,3,4,5];
seq2 = [1,3,2,4,5];  // 아이템은 동일하나 순서가 바뀌었다.
println(seq1 == seq2); // false


* 시퀀스 슬라이스(Slice) 사용하기

seq 키워드를 사용하여 시퀀스 내의 아이템을 분할 가능하다.

var days = ["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];

var weekend = days[5..6]; // ["Sat","Sun"] 인덱스 5 와 6 사이의 아이템을 가져온다.

var weekdays = days[0..<5];//["Mon","Tue","Wed","Thu","Fri"] 인덱스 0 과 4(=5보다 작은) 사이의
                                         // 아이템을 가져온다.

weekend = days[5..]; // ["Sat","Sun"] 인덱스 5 부터 끝까지의 아이템을 가져온다.

var days2 = days[0..<]; // ["Mon","Tue","Wed","Thu","Fri","Sat"] 인덱스 0부터 마지막보다 작은 사이의
                                  // 아이템을 가져온다.(마지막은 제외)

+ Recent posts