IDL 8.4에 등장한 Static Method, 그리고 문자열 치환

IDL이 8.0 버전을 넘어서면서부터 IDL을 만드는 개발자들(IDL로 만드는 개발자들 말구요)이 IDL의 문법 틀을 개편하는데 두려움이 없는 것 같다는 생각을 했는데, 이번 8.4버전 출시에도 역시 같은 생각입니다. 30년 넘게 사용되어 온 전통의 IDL 문법을 고친다는 것이 정말 만만한 일은 아닐텐데, 이런 일을 감행하고 있네요(물론 “거~~의 모든 과거의 코드들은 IDL 8.4에서도 잘 실행될 것입니다).

일반 사용자들에게, “자 봐라, IDL 8.4의 이 놀라운 기능을!” 하고 외칠만한 것은 사실 잘 안보입니다. 왜냐하면 그래픽스와 관련된 새로운 기능이 없거든요(New Graphics의 하단의 버튼들 모음인 Tool Bar를 없애는 옵션이 새로 등장했습니다. 조용히 제공된 기능이지만 유용합니다. 다음 글에서 보여 드리지요). 그런데, 문법적으로는 본격적인 객체지향 언어로 변화를 위해 뭔가 문법이 자꾸 추가되고 있습니다. 다시 말씀드리지만 과거의 문법을 그대로 쓰시는 거는 아무런 문제가 없습니다.  거기에 새로운 문법이 추가되고 있는 것인데, 좀 신비로운 느낌의 문법이 등장했습니다.

IDL> a=indgen(10)
IDL> a.total()         ;이거 새로 등장한 겁니다.
45.000000
IDL> total(a)           ;예전부터 사용되던 방식은 이거구요.
45.000000

제 개인적인 생각으로는 어떤 게 더 나은 방법이라는 판단이 서지 않습니다. 새로운 기능이라고 무조건 더 좋다고 하면 안되는 거고, 개발자의 스타일에 따라 새로운 방식을 더 선호하거나 기존의 방식을 그대로 고수하거나 할 수 있다고 저는 생각합니다. 이제 두가지 다 유효한 방식이 된 거죠. Python이나 Java 를 사용하던 프로그래머들에게는 새로운 방식의 문법이 더 마음 편할 거라고 생각합니다. Exelis VIS의 기술진이 구체적인 답변을 하지는 않지만, 문법이 Python을 닮아 가고 있다는 질문에 No를 하지는 않았습니다.

이런 방식을 Static Method라고 하는데요, 객체지향 프로그래밍에서, 변수는 죄다 객체고, 객체는 데이터와 기능(method)를 가지는 특성이 있습니다. 즉, 객체라는 말을 사용하지는 않지만, 변수 a를 마치 객체인 것처럼 사용하겠다는 것이고, 이러한 변수들에 기본으로 따라 붙는 기능(method – 기존 사용자들은 그냥 함수라고 이해해도 똑같습니다)을 제공하는 것입니다. 에잇, 정신 사나와… 라고 생각하신다면 그냥 함수를 쓰시면 됩니다. 저도 대부분의 상황에서 그럴 거예요.  하지만, 이렇게 static method 형태로 기술하는 것이 논리적으로 읽기 더 편하다는 저희 회사의 개발자들도 있구요, 좀 더 재미난 기능으로 확장될 가능성이 다분하기 때문에, 저는 즐거운 마음으로 지켜보는 중입니다. 예를 들면, 써드파티 업체이지만, IDL에서 Python 기능을 호출하여 쓸수 있는 IDL-Python Bridge를 무상배포하고 있고요, IDL에서 Java의 클래스를 호출하여 IDL 클래스인 것처럼 사용하는 IDL-Java import Bridge는 오래전부터 제공되고 발전되는 기능입니다. 이들 언어들과의 어떤 시대적 밸런스를 맞추어야 될 필요가 있다고 판단한 건 아닐까 하는 생각도 듭니다.

IDL 8.4의 도움말에서 What’s New in IDL 8.4를 둘러보시면 꽤 다양한 Static Method를 보실 수 있습니다. 대부분은 예전부터 IDL의 함수로 제공되는 기능들입니다.

IDL 8.4에서 새로 제공되는 Static Method 도움말

IDL 8.4에서 새로 제공되는 Static Method 도움말

아마도 좀 더 사용하다 보면, “오… 이건 이렇게 해 놓으니 더 편하겠군” 하는 것이 좀 더 보이겠지만, 현재는 하나의 메쏘드가 눈에 띄네요. 개인적으로 그렇다는 겁니다. 제게는 Replace 메쏘드가 눈에 띕니다. IDL에서 그동안 기본 제공했던 기능이 아니거든요. 이름 그대로 다음과 같이 문자열을 치환하는 일을 합니다.

IDL> x=’123/456′
IDL> x.replace(‘/’, ‘:’)
123:456

문자열에서 ‘/’로 된 부분을 ‘:’으로 치환하라는 거죠. 이 기능은 파일, 문자열, 데이터스트림 등을 다룰 때 종종 사용됩니다. 꼭 하나의 글자만 적용되는 것은 아닙니다. 다음과 같은 게 가능하죠.

IDL> y=’188 345.9 NaN 175.3 NaN 344.7’
IDL> y.replace(‘NaN’, ‘-999.0’)
188 345.9 -999.0 175.3 -999.0 344.7

-999 또는 어떤 특정한 수와 NaN의 변환 문제는 당분간은 계속될 겁니다. 이렇게 어떤 특정 값에 해당하는 문자열을 다른 특정값으로 대체하는 데 아주 유용한 기능입니다.

그렇다면 기존의 IDL 버전에서는 이 문제를 어떻게 해결했을까요? 여러가지 방법이 있겠지만 저는 다음과 같은 방식을 사용했습니다.

IDL> strjoin(strsplit(x, ‘/’, /extract), ‘:’)
123:456

IDL> strjoin(strsplit(y, ‘NaN’, /extract), ‘-999.0’)
188 345.9 -999.0 175.3 -999.0 344.7

자, 일단 같은 기능을 구현하는데 아무 문제 없지요? strsplit은 문자열을 지정한 구분자, 예를 들면 ‘/’를 기준으로 분리하라는 의미입니다. 분리된 문자열(예, ‘123’ 과 ‘456’)은 배열로 관리되구요. 이걸 다시 strjoin 함수를 이용하여 지정한 문자를 사이에 끼워 연결하는 겁니다. 그러면 최종적으로는 strsplit에서 사용한 구분자가 strjoin에서 사용한 구분자로 대체되는 효과가 납니다.

사실 이 방식은 정규표현식(regular expression)이라는 문법을 STRSPLIT 함수가 받아들일 수 있기 때문에 훨씬 유연한 기능을 제공합니다. 속도는 재보지는 않았지만 replace 메쏘드가 더 빠를 거예요. 아무래도 strsplit이 더 유연성이 있기 때문에 시간이 조금이라도 더 걸릴 겁니다.  그렇지만 유연성은 매우 중요한 거지요. 다음 예제를 보세요.

IDL> z=’10….9..8.7….6…5…..4…3….2……….1..0′
IDL> z.replace(‘.’, ‘,’)
10,,,,9,,8,7,,,,6,,,5,,,,,4,,,3,,,,2,,,,,,,,,,1,,0

IDL> strjoin(strsplit(z, ‘\.+’, /REGEX, /EXTRACT), ‘,’)
10,9,8,7,6,5,4,3,2,1,0

z 문자열처럼 통신데이터를 받다 보면, 뭔가 의미없는 신호들이 쭉 들어오다가 의미 있는 신호가 하나 들어오고 하는 과정이 반복됩니다. 이 때 의미 없는 신호가 얼마나 반복될지는 예상할 수 없는 경우가  종종 있습니다. z 문자열에서 …. 은 대기신호인데, 이러한 대기신호를 그냥 일축해서 comma 하나로 바꿔버리고 싶을 때, 아직 replace() 메쏘드는 그런 기능을 구현할 수 없습니다. 고정된 문자열을 지정해 줘야 이를 치환하거든요. 하지만 strsplit은 정규표현식을 받아 들입니다. ‘\,+’ 는 비교적 심플한 정규표현식인데, 역슬래시는 그 뒤에 오는 특수문자를 그 특수문자 그대로 해석하라는 거예요. 그래서 \. 는 그냥 점입니다. + 기호는 앞의 문자가 하나 또는 여러개가 쭉 이어져서 등장하는 것을 의미합니다. 즉 ‘\.+’는 점이 하나 또는 그 이상 많이 나오는데 이걸 모두 묶어 한 덩어리로 매칭시키는 것을 의미합니다. 이렇게 해서 하나 또는 그 이상의 연속적인 점을 구분자로 하여 값을 분리하고, 이를 comma로 연결하면 마지막줄과 같은 결과를 얻을 수 있게 됩니다.

아마도, 다음 어느 버전 쯤에서는 replace() 메쏘드에도 정규식을 쓸 수 있도록 기능이 업데이트 될 거예요. 일단 저는 “새버전에 바란다”에서 요구할 겁니다(제 요구를 들어준 적은 10년간 한번도 없었긴 합니다 ㅎㅎ). 그렇지만 지금 당장은 유연성은 과거의 방법이 더 좋네요. 단순 문자열 치환에는 replace 메쏘드가 훨씬 편하게 보입니다.

새로운 문법이 계속 등장하고 이중 최소한 일부는 유용하다고 느껴져서 계속 사용되고 발전되고 그럴 겁니다. 하나 딱 드는 걱정은, IDL 8.4는 과거의 모든 IDL 프로그램을 해석하고 실행할 수 있는데, 새로운 기능을 사용한 코드는 과거의 IDL, 심지어 바로 앞버전인 8.3에서도 실행이 안될 수 있는 딱 한가지의 단점이 느껴집니다. 그런데 왜 여태 IDL은 strreplace() 라는 함수를 만들어 놓지 않았던 걸까요?