프로그래밍 언어의 단어와 문법 - 1 [프로그래밍]
⦁ 들어가기 앞서
안녕하세요. 저번 포스팅 때 8월부터 매 달 1~2편씩 프로그래밍에 대하여 개괄적으로 다뤄본다고 했는데 드디어 첫 포스팅을 올리게 되었습니다. 제 블로그의 포스팅을 보셨던 분들은 알겠지만 말투가 많이 달라 어색할 수도 있을 텐데, 이번 계획 의도가 프로그래밍을 배우시는데 잘 이해가 되지 않거나 학습에 도움을 주기 위한 목표를 갖고 있기 때문에 이 시리즈에 한정하여 말투를 조금 바꿔서 포스팅을 하고자 합니다.
필자가 주변 분들에게 프로그래밍을 접하면서 가장 어려웠던 점을 물어봤더니 대체로 "어떻게 짜야하는지 모르겠다" 나 프로그래밍 언어 자체를 어려웠다는 것이 가장 많더군요. 어쩌면 프로그래밍 언어에 대한 이해와 로직(logic)을 구성하는 것이 생소하다가 맞을지도 모르겠습니다. 이에 프로그래밍에 대해 좀 더 이해하기 수월하도록 하는데 목적을 두고자 합니다.
너무 전문적인 단어와 내용들은 빼고 학술적인 내용보다는 인문학을 다루듯이 전반적인 내용을 다뤄보고자 합니다. 이렇다 보니 프로그래밍을 깊게 배우려는 분들에게는 부족한 내용일 수 있을 수 있는데, 이 부분은 추후 언어별로 깊게 다뤄볼 계획입니다.
⦁ 프로그래밍이란
너무나 진부한 목차지만 여기에 대해 잠깐 짚고 넘어갔으면 합니다. 요즘은 워낙 IT가 우리 일상과 밀접한 존재이기도 하고, 현재 초등학교에서는 코딩 교육을 의무화하는 만큼 대부분의 사람들은 대략적으로 어떤 의미인지는 아실 거라 봅니다. 하지만 많은 분들이 코딩과 프로그래밍을 동의어로 생각하는 분들이 많죠. 무슨 차이가 있냐고요? 일단 프로그래밍에 대한 사전적 정의부터 봅시다.
위 글을 보면 알겠지만 프로그래밍이 코딩을 포함하여 전반적인 작업을 프로그래밍이라고 합니다. 반면에 코딩은 여러분들이 C, Java, Python 등의 언어를 통해 작성하는 행위에 좀 더 가깝습니다. 그래서 프로그램을 전반적으로 설계하는 사람을 프로그래머(Programmer), 그리고 요구에 맞게 변환해주는 사람을 코더(Coder)라고 하죠.
물론 프로그래머와 코더가 이분법적으로 딱 나뉘는 것은 아닙니다. 어디까지나 상대적인 개념이기도 하고 과거에는 코더가 할 수 있는 일은 매우 단순했지만 근래는 꼭 그런 것도 아니라 딱 잘라 말하기는 어렵네요. 다만 조금 비유를 하자면 '언어'를 배우는 사람과 '언어학'을 배우는 사람의 차이 정도랄까요?
위의 차이처럼 이 포스팅 또한 '언어'를 알려주려는 것이 아니라 '언어학'에 가까운, 좀 더 포괄적인 내용을 다루기 위해 프로그래밍 기초라고 했습니다.
⦁ 프로그래밍 언어도 언어다
보통 프로그래밍 언어 책을 구입하거나 수업을 통해 처음 접하면 목차가 다음과 같을 것입니다. 예로 들어 필자가 애용하는 Java 언어를 예로 들어보죠. 먼저 책을 펼치면 Java 언어에 대해 설명을 합니다. Java는 안드로이드 개발에도 사용되고, 많은 개발자들이 사용하는 언어며 객체지향 언어 .. 어쩌고 저쩌고... 이렇게 언어에 대한 개괄적 설명이 끝나면 다음 목차는 개발환경, 즉 코딩을 하기 위한 환경을 구성하는 방법에 대해 나올 것입니다. 이런 과정이 끝나면 여러분들이 가장 먼저 하는 코딩은 출력일 것입니다. 그 이후 한 목차씩 넘어가면서 언어의 기능에 대해 배우죠.
한마디로 여러분들이 배우는 프로그래밍 언어 책들은 대개 '기능'에 초점을 맞추어 목차가 구성됩니다. '입출력', '조건문', '반복문', '배열' 등과 같이 말이죠. 사실 이렇게 배우는 것이 코딩하는 면에서는 빠를지도 모르겠습니다. 하지만 반대로 기능적 요소로 배우다 보니 언어의 기능적 부분(예로 들어 메소드, 함수 등..)은 많이 알고 있으나 막상 어떤 문제가 주어졌을 때 로직을 짜려고 하면 어떻게 짜야할지 난관에 부딪히기도 하죠. 그래서 이러한 부분을 좀 더 쉽게 해소해드리기 위해 이번에는 조금은 다르게, 우리가 사용하는 일상 언어처럼 프로그래밍 언어도 크게 다르지 않다는 시각에서 접근해보려 합니다.
필자가 주변 코딩을 어려워하는 분들에게 자주 하는 말이 있습니다. "프로그래밍 언어와 일상언어와 별반 다를 게 없어!" 이런 말을 하면 대개 처음에는 수많은 물음표가 떨어지며 어이없어하죠. 하지만 제가 실제로도 영어나 한국어 등의 여러 언어와 프로그래밍 언어는 크게 다를 것이 없다고 느낍니다.
다행히도 프로그래밍 언어는 거의 대부분이 영어를 사용하고 있기 때문에 구조만 알면 쉽게 이해할 수 있을 것입니다. 그래서 우리는 오늘 단어와 문법에 대해 알아보고자 합니다.
[단어편]
한국어를 배웠을 때는 아주 어릴 때라 기억이 안 날 테니 영어와 연관 지어 설명하도록 하겠습니다.. 우리가 영어를 배울 때 대개 단어(vocabulary)부터 먼저 많이 외우도록 합니다. 이걸 프로그래밍 언어에서는 모든 기본 단위 문법이 됩니다. 예로 들어 C언어에서 출력하는 방법인 printf(), 자료형 char, int 등등.. 어떤 기능적 요소를 담고 있는 기본 문법 단위라고 생각하시면 됩니다. 단어는 크게 두 부류로 '키워드'와 '함수(메소드)'로 나뉩니다.
그리고 대개 프로그래밍 언어들의 단어들은 축약을 많이 합니다. 우리가 실생활에서도 단어가 길면 줄이려는 경향이 있듯, 프로그래밍 언어 또한 단어가 길어지면 코드를 작성하기에도 불편하고 가독성도 떨어지기 때문에 단어를 최대한 이해하기 쉬우면서 짧은 형태로 나타내려고 합니다. 예로 들어 아이스 아메리카노를 '아아'라고 부르듯, 또는 컴퓨터 활용능력을 '컴활'이라고 부르듯이 말이죠.
당장 위의 printf, char, int의 용어들도 모두 축약된 형태입니다. printf 는 print(출력)와 format(형식)의 합쳐진 단어고, char과 int는 character(문자)와 integer(정수)의 축약된 단어죠. 이렇게 어느 정도 축약된 단어들의 의미를 알게 되면 설령 다른 언어를 배우더라도 쉽게 기능을 익힐 수 있습니다. 만약 여러분들이 다른 사람의 소스코드를 볼 일이 있을경우 대강 어떤 역할을 하는지 감으로 알 수 있게 됩니다. 조금씩 차용하는 단어는 다르지만 어디까지나 영어에 대부분 국한되어있어 이해하기가 빠릅니다. 즉, 가장 먼저 알아햐 할 것은 '각 단어가 무엇을 의미하는지를 이해'해야 합니다.
'사과'라는 단어를 알아야 무엇이 사과인지를 알 테고 '먹는다'를 알아야 어떠한 행위를 하는지 알 수 있죠. 이렇게 각 단어별로 의미(기능)를 알게되면 합쳐서 "사과를 먹는다" 라는 문장을 쓸 수 있게 되듯이요. 프로그래밍 언어도 이와 다를 게 없죠.
그럼 키워드하고 함수의 차이는 무엇인지를 알아야 할겁니다.
키워드는 '특정 용도로 사용하기 위해 미리 지정된 명령어'를 의미합니다. 사전적으로 말하니 이해가 어려울 수 있겠지만 int, char, float, const, double, do, public, final 등이 키워드라 불리우죠. 한마디로 '어떤 상태를 정의하는 단어'라고 볼 수 있습니다.
대표적인 키워드 중 '자료형(타입)'에 대해 설명해보죠. 대부분의 언어들은 크게 3가지 갈래로 자료형(타입)이 나옵니다. '정수', '부동소수점', '문자' 이렇게 나뉘죠.
정수는 프로그래밍 언어마다 조금씩 차이는 있지만 대개 정수는 'int'와 'long' 이라는 단어로 표현됩니다. int는 Integer 의 줄임말이고, long은 Long Integer 의 줄임말이죠. (둘 의 차이는 표현 할 수 있는 수의 범위가 다르다는 점입니다. 이 부분에 대해서는 다음에 좀 더 구체적으로 다루기로 하죠.)
부동소수점은 무엇일까요? 쉽게 생각하면 소수점을 표시할 수 있는 자료형, 즉 정수가 아닌 유리수들을 표현하기 위한 자료형입니다. 대개 'float' 나 'double'이라는 단어로 표현되죠. float는 Floating point로 부동 소수점이라는 의미입니다. double은 뭘까요? 아까 정수와 비슷한 체계로 Double Floating Point 의 줄임말입니다. 대충 감이 오시나요? 왜 소수라 부르지 않고 부동 소수점이라고 부르는지 궁금하신 분은 아래 글을 참고하시면 될 것 같습니다.
마지막으로 char은 앞서 언급했듯 Character라는 의미입니다. 즉, 문자를 표현해준다는 의미죠. 이를 이용하여 변수들을 다음과 같이 생성해줄 수 있겠군요.
int a
double b
char c
앞서 말했던 '어떤 상태를 정의'한다는 것을 적용한다면 이럴겁니다.
a 라는 변수는 int(정수) 상태, 즉 int타입의 변수다.
b 라는 변수는 double(부동소수점) 타입의 변수다.
c 라는 변수는 char(문자)타입의 변수다.
이렇게 키워드들을 통해 변수나 함수 등에 대해 상태를 정의해줄 수 있습니다. 이러한 키워드들을 정확히 이해하지 못했을 때 생기는 문제 중 하나가 자료형을 다룰 때 발생합니다. 자바를 통해 다음의 예시를 보죠.
int integer = 65;
char character = 65;
System.out.println(integer);
System.out.println(character);
위 구문을 해석해보면 integer라는 변수는 int(정수)타입이며 65라는 값을 갖고(저장하고), character라는 변수는 char(문자)타입이며 65라는 값을 갖고있다. 이렇게 각기 다른 자료형에 65라는 숫자로 초기화를 했습니다. 이를 출력하면 둘 다 65가 출력될까요? 한 번 결과를 보죠.
보면 알 수 있듯이 int에는 65가 그대로 출력되지만 char에는 우리가 의도하는 것과는 달리 A라는 문자가 출력되죠. 앞서 말했던 것처럼 int는 'Integer(정수)'를 의미한다고 했고 char은 'Character(문자)'를 의미한다고 했습니다.
integer라는 변수에 담긴 65는 출력할 때 정수라고 정해줬기 때문에 65를 숫자로 읽어 65를 출력하지만, char의 경우 문자라고 보기 때문에 '65에 대응되는 문자'가 출력되는 것이죠. 그리고 65에 대응되는 문자는 A입니다. (왜 A가 65에 대응되는지 더 궁금하신 분은 아래 더보기를 통해 보시면 되겠습니다.)
컴퓨터는 우리가 사용하는 언어를 이해하지 못합니다. 그렇기 때문에 우리가 사용하는 문자를 컴퓨터가 이해할 수 있는 신호를 만들어야 하는데 각 문자에 대응하는 수에 대해서 사용자마다 다르면 당연히 못쓸 것입니다. 그렇기 때문에 일정한 규정을 두고 쓰는데 이렇게 정해진 규칙을 '문자 인코딩' 또는 줄여서 '인코딩'이라고 합니다. 인코딩 종류는 매우 많은데 대표적으로 Ascii(아스키코드), UTF-8 등이 있습니다. character라는 변수에 담긴 65는 char이라는 자료형, 즉 문자를 의미하기 때문에 65라는 수에 대응하는 'A'를 출력하게 되는 것입니다. Ascii 테이블은 아래 사진을 참고하시면 됩니다.
물론 그 반대도 가능합니다.
int integer = 'A';
char character = 'A';
System.out.println(integer);
System.out.println(character);
위와같이 하여 출력하더라도 integer라는 변수는 65를 출력하고, character라는 변수는 A를 출력하게 되있죠. 즉, char은 정확히 말하자면 '문자'자체를 저장하는 것이 아니라 '문자에 대응되는 수'를 저장한다는 것이 올바른 해석일 것입니다. 쉽게 설명하자면 이렇습니다.
감이 오실겁니다. 키워드는 어떤 상태를 정의한다는 것을 꼭 기억하셨으면 합니다.
그럼 단어 중 함수에 대해 알아보도록 하죠. 대개 함수는 프로그래밍 언어에선 '메소드'라고 부릅니다. 아까 위의 예제들에서 보았던 println() 같이 괄호가 붙은 것들이 함수죠. 어떠한 동작을 하기 위한 함수라고 생각하면 편하겠네요. 이는 이해하는데 어려움은 없을 겁니다. 함수의 경우 프로그래밍 언어에서 기본적으로 지원해주는 함수들이 있고, 사용자가 필요에 의해 새롭게 만들 수도 있습니다. 프로그램에서 기본적으로 지원해주는 함수들은 각기 다르지만 대게 비슷한 단어들을 쓰고 있기 때문에 여러분들이 다른 사람의 코드를 보더라도, 또는 아예 배우지 않은 언어로 짜여진 코드를 보더라도 어느정도 유추할 수 있습니다.
이렇게 메소드와 키워드들은 어떤 기능이나 상태를 정의하기 위한 가장 기본적 단위가 됩니다. 이러한 단어들을 보면서 각 단어들이 어떤 것을 의미 또는 수행하느냐를 잘 이해해야 여러분들이 의도하는 대로 짤 수 있게 되죠.
물론 이 말고도 수만가지의 단어들이 존재하기 때문에 이를 다 설명하기에는 부족할겁니다. 만약에 어떤 언어에 대해 필요한 기능을 찾아보려 한다면 구글에 '언어 이름 API(Application Programming Interface)'라고 검색하거나 수행하고자 하는 기능을 검색해보면 되겠죠. 반대로 키워드에 대해 궁금하다면 '언어 이름 keyword' 라고 검색해보면 어떤 의미인지 금방 찾을 수 있겠습니다.
예로 들어 파이썬의 정렬의 기능에 대해 찾아보고 싶다면 python sort라고 검색하면 되겠죠. 또한 java언어의 static 키워드에 대해 궁금하다면 java static 또는 java keyword라고 검색하면 되겠죠? 이렇게 단어의 경우 찾아보고 배워가면서 지식을 쌓아가다 보면 문법과 결합하여 좀 더 유연하고 다양한 문법을 구사할 수 있습니다. 그럼 문법을 보도록 하죠.
[문법편 - 수식]
어떠한 문장이 되기 위해서는 단어와 문법을 알아야 합니다. 우리가 영어를 배우다 보면 5 형식이니 뭐니 하면서 거기에 추가로 예외 구문까지 배워야 하기 때문에 엄청 어려워하실 겁니다. 하지만 다행히도 프로그래밍 언어는 매우 규칙적이고 예외 구문이 거의 없습니다. 컴퓨터가 인간처럼 상황에 따른 추론을 하는 감정적인 동물이 아니기 때문이죠. 엄격한 문법 때문에 대부분의 언어는 문법이 크게 다르지 않습니다. 다만, 사용하는 단어나 약간의 구조적 차이가 있을 뿐이죠. 마치 미국어 - 영국어 - 스페인어처럼 비슷하면서도 조금씩은 다르듯이요.
그래도 앞서 말했듯 문법구조가 엄청 다른 것이 아니기 때문에 C나 Java같이 많이 사용되는 언어 하나만 제대로 알고 가도 나머지 언어는 새로 접하더라도 쉽게 배울 수 있습니다. 마치 우리나라 사람이 일본어를 쉽게 습득할 수 있는 것과 비슷한 논리라고 보면 될 것 같습니다.
문법은 크게 두 가지 원리인 '수식'과 '절차'에 의거합니다. 그 중 오늘은 수식에 대해 알아보고 절차는 다음 포스팅에서 다루겠습니다.
수식은 수학에서 쓰는 수식과 별반 다를 게 없습니다. 예로 들어 10+20×5 를 보면 우리는 다음과 같이 계산할 겁니다. 먼저 20×5 를 한 뒤 10을 더하여 110이라는 정답을 도출해낼 것입니다. 이는 덧셈보다 곱셈이 우선순위가 더 높기 때문이죠. 반대로 (10+20)×5 로 괄호를 쳐주면 어떨까요? 그럼 괄호 안이 곱셈보다 우선순위를 갖죠? 10+20을 해준 다음 5를 곱하여 150이라는 정답을 얻을 수 있습니다.
만약 수식으로 𝑥=(10+20)×5 라고 하면 𝑥=150 이구나!라고 알 수 있죠.
프로그래밍 언어도 마찬가지입니다. 언어별로 약간의 차이는 있지만 거의 비슷하게 작동합니다. 아래 예시를 보죠.
int x = 10 + 20 * 2 - 10 / 5;
int y = (10 + 20) * (2 - 10) / 5;
첫 번째 수식 x 는 알다시피 곱셈과 나눗셈이 먼저 계산되기 때문에 48이라는 값을 얻을 수 있습니다. 결과적으로 x는 48이라는 값을 가리키고 있는 것이죠.
두 번째 수식 y 는 10+20과 2-10을 먼저 계산할 겁니다. 그럼 수식으로는 30×(-8)÷5 일 겁니다. -48이라는 값이 나오겠죠. 이 값은 y에 저장되어 y=-48이 됩니다. 이렇게 프로그래밍 또한 기본적인 수학 수식에서 벗어나지 않습니다. 다만 조금 다른 점이 있다면 ++(증가 연산자), --(감소 연산자), <=(≤), >=(≥) 같은 수식을 볼 수 있을 뿐이죠. 각 언어별로 큰 차이는 없지만 약간씩 차이는 있을 수 있습니다. 그렇기 때문에 만약 연산자를 다루려고 한다면 각 언어별 연산자 우선순위를 검색해서 살펴보시는 것이 좋습니다. 다만 대부분의 언어들의 '가장 높은 우선순위 연산자는 괄호'입니다.
괄호의 우선순위가 높다는 의미를 함수로 확장해볼까요? 수학에서 함수를 표현하는 방법 중 대표적인 방법은 f(x) 일 겁니다. f(x) = 2x 라고 한다면 x에 들어가는 값에 2를 곱해준다는 의미입니다. 또한 함수 안에 함수를 표현 할수도 있겠죠. g(f(x)) 처럼 말이죠. 즉, g함수를 계산하기 전에 f(x)함수부터 계산한 다음 그 값을 다시 g함수에 넣어 계산하여 최종 값을 얻을 겁니다.
프로그래밍 언어도 마찬가집니다. 메소드(함수)안에 메소드를 넣을 수 있죠. 예로들어 h(), g(), f() 메소드가 있고 h(g(f())) 처럼 표현하면 가장 안쪽 괄호, 즉 f()부터 실행할겁니다. 수학적으로 표현하자면 다음과 같겠죠. h(g(f(x))) = f →g→h
한 번 응용해보죠. 파이썬에서 다음과 같은 문장이 있다고 해봅시다.
print(','.join(map(str,sorted([2,1,4,int(input())]))) + ' is sorted!')
당장 보면 뭐지? 싶을 수도 있습니다. 당장은 함수 기능을 몰라도 됩니다. 중요한 것은 '수식'이라는 것이니깐요. 한 번 위에서 말했던 것처럼 차근차근해봅시다. 일단 괄호가 우선순위가 가장 높다고 했으니 가장 안쪽의 괄호부터 찾아보는 것이 중요할 것입니다.
1. input()
가장 안쪽에 있는 괄호는 input() 이군요. 이는 '입력을 받는 함수'입니다. 이 함수가 가장 먼저 실행하여 입력을 받는다고 보면 됩니다. 이때 input은 정수를 입력하더라도 문자열로 입력됩니다. 만약 3을 입력받았다면 숫자 3이 아니라 문자 3이 입력된다는 의미죠. 이왕 3이 나온 김에 쭉 설명하면서 3을 입력받았다는 가정하에 진행해보죠.
2. int(input())
그다음으로 input()을 감싸고 있는 괄호가 있죠? int(input()) 이죠. int() 함수는 문자열을 정수(integer)로 변환하여 반환해주는 함수입니다.
입력받은 다음 정수로 변환해준다는 의미죠. 즉 문자 '3'을 숫자 3으로 변환을 해줍니다.
3. [2,1,4,int(input())]
그다음의 괄호는 []인 대괄호입니다. 다른 언어에서는 배열이라는 말이 자주 쓰이는데, 파이썬에서는 리스트(list)라고 칭합니다. 해석하자면 리스트에 원소가 2, 1, 4, 그리고 아까 우리가 입력받아 정수로 변환했던 정수가 있다는 의미입니다. 우린 3을 입력했으니 [2, 1, 4, 3]라는 리스트가 되겠군요.
4. sorted([2,1,4,int(input())])
다음 함수는 sorted() 이군요. 단어 의미 그대로 정렬을 해주는 함수입니다. 우리가 3을 입력받아 정수로 바꿔 리스트의 한 원소로 넣어준 리스트인 [2, 1, 4, 3]을 '정렬하여 반환'해줍니다. 즉, [1, 2, 3, 4] 가 반환되겠죠.
5. map(str, sorted([2,1,4,int(input())]))
다음으로 감싸고 있는 것은 map() 함수입니다. map은 리스트의 요소들을 지정된 형식으로 변환해주는 함수입니다. 쉽게 말해서 map(지정 형식, 반복 가능한 객체(리스트, 튜플 등등..)) 이런 형식인데, str은 문자열(String)을 의미하니 우리가 입력받아 정렬까지 하면서 만들었던 리스트인 [1, 2, 3, 4] 의 '정수 요소들을 문자열로 바꿔 반환'해주는 것입니다.
적용해보면 3을 입력하고 int형으로 변환 뒤 리스트의 마지막 원소에 넣어 정렬을 하고 map함수를 거치고 나면 ['1', '2', '3', '4'] 가 나오겠군요. 다만 반환되는 형식이 리스트(list)가 아닌 iterator 객체(반복 가능한 객체)로 리스트보다 더 넓은 의미의 객체라는 정도로만 이해하시면 좋을 것 같습니다.
5. ','.join(map(str, sorted([2,1,4,int(input())])))
다음은 join() 괄호가 있군요. join은 리스트를 '특정 구분자로' 구분하여 문자열로 반환해주는 함수입니다. 쓰는 방법은 '원하는 기준'. join(반복 가능한 객체)입니다. 우리는 쉼표(,)로 리스트의 요소들을 구분하여 문자열로 반환해주도록 하죠. 그러면 ['1', '2', '3', '4'] 인 리스트는 쉼표로 구분되어 '하나의 문자열'인 '1,2,3,4' 가 나올 것입니다.
6. ','.join(map(str, sorted([2,1,4,int(input())]))) + ' is sorted!'
다음은 괄호가 아닌 + 연산이군요. 파이썬은 문자열끼리 + 연산자를 통해 붙여줄 수 있습니다. 즉 '1,2,3,4' 라는 문자열 뒤에 ' is sorted!' 을 붙여주는 겁니다. 그러면 '1,2,3,4 is sorted!' 라는 하나의 문자열로 합쳐지겠죠?
7. print(','.join(map(str, sorted([2,1,4,int(input())]))) + ' is sorted!')
마지막으로 print() 함수입니다. 말 그대로 출력을 해주는 것이죠. 이전 단계에서의 결과물은 '1,2,3,4 is sorted!' 였으므로 이 문자가 출력되겠습니다. 실제로 그런지 한 번 테스트해보죠.
잘 나오네요. 파이썬을 안 배우셨거나 잘 몰라서 기능들을 이해하지 못해도 괜찮습니다. 중요한 것은 '가장 안쪽의 함수부터 실행한다는 것'이 이 번 이야기의 포인트입니다. 보다시피 우리가 사용하는 수식을 그대로 프로그래밍 언어에서도 마찬가지로 가장 안쪽 괄호부터 차례대로 실행하게 됩니다.
좀 더 이해하기 쉽게 그림으로 설명하자면 다음과 같겠죠.
이는 다른 언어들도 마찬가지입니다. 함수 안에 함수, 그 안에 함수.. 이런식으로 함수안에 함수를 넣을 수 있습니다. 예로들어 Java로 구현할 수도 있습니다. Java로 구현하고싶은 걸 보고싶은 경우 아래 더 보기를 눌러주시면 됩니다.
(참고로 자바는 파이썬처럼 정렬 후 정렬된 배열을 반환해주는 메소드가 없기 때문에 따로 반환해줄 수 있는 메소드를 만들어줍니다.)
import java.util.Arrays;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
System.out.print(String.join("--", Arrays.toString(sort(new int[]{2,1,4,in.nextInt()})).replaceAll("\\[|\\]", "").split(", ")) + " is sorted!");
}
static int[] sort(int[] n) {
Arrays.sort(n);
return n;
}
}
조금 코드가 길긴 합니다. (자바의 단점이기도 하죠.) 우리가 중점적으로 볼 것은 System.out.print() 구문입니다. 각각 어떤 기능을 하나하나 설명해주면 글의 목적과 너무 벗어나기 때문에 일단 가장 먼저 실행되는 것을 찾는 것에 초점을 맞추도록 하죠. 위 각 기능을 이해 못해도 괜찮습니다. 여기도 마찬가지로 가장 안에 있는 함수인 in.nextInt()부터 시작합니다.
각 함수에 대한 설명은 다음과 같습니다.
nextInt()
입력한 값을 정수로 읽어 들이는 메소드입니다.
ex) 3 입력
sort()
정렬한 배열을 반환하기 위해 만든 사용자 정의 함수입니다. 정렬 자체는 Arrays.sort()이라는 함수에 의해 정렬됩니다.
ex) [2, 1, 4, 3] -> [1, 2, 3, 4]
Arrays.toString()
배열을 하나의 문자열로 만들어줍니다. 이때 각각의 요소들은 대괄호 안에 위치하게 됩니다.
ex) "[1, 2, 3, 4]"
replaceAll()
정규식을 인자로 받아 특정 문자를 사용자가 원하는 문자열로 바꿔주는 메소드입니다. 위의 예제에서는 "\\[|\\]" 은 "["와 "]" 을 의미하며 "", 즉 공백으로 바꿔준다는 의미입니다.
ex) "1, 2, 3, 4"
split()
문자열을 지정 구분자에 의해 분리하여 문자열 배열(String[])으로 반환해줍니다. 예제에서는 ", "을 기준으로 분리됩니다.
ex) ["1", "2", "3", "4"]
String.join()
배열 각 요소 사이에 지정 문자를 넣어 하나의 문자열로 만들어 줍니다. 예제에서는 "--" 을 넣어줍니다.
ex) "1--2--3--4"
System.out.print()
출력입니다. 결과적으로는 1--2--3--4 is sorted! 가 출력됩니다.
이렇듯
단어들을 수식과 같이 배치하여 하나의 문장을 만드는 것. 이는 알고리즘을 짜거나 구성하는데에 매우 필수적이면서도 기초적인 내용입니다. 특히 '재귀' 알고리즘을 이해하기 위해서는 이와 같은 호출 방법을 제대로 알고있어야 하죠. 재귀야 말로 자기 자신을 반복적으로 호출하는 것이니깐요.
이제 왜 수식이라 하는지 이해가 되나요? 일반적인 프로그래밍 언어는 대개 수학에서 쓰이는 수식과 비슷한 논리구조로 작동합니다. 이렇게 각 함수의 기능과 구조를 알고있다면 조금은 시간이 걸릴 수는 있어도 해석하는데 큰 도움이 될 수 있습니다.
오늘 두 가지를 설명했습니다. 단어와 수식.
단어는 어떠한 기능 또는 상태를 정의하는 최소한의 단위구조(문법)을 의미한다.
수식은 수학 수식과 거의 동일한 구조이며 함수 안에 함수를 호출하는 것은 h(g(f(x))) = f→g→h 로 표현할 수 있다.
위 두 가지는 알고리즘의 가장 기초적 토대이자 여러분이 알고리즘을 짜는데 많은 도움이 될겁니다. 각각의 단어들이 모여 하나의 연결된 문장으로 우리가 쓰는 언어와 크게 구조가 다르지 않습니다. 여러분들이 설령 다른 언어를 접하시더라도 단어와 수식에 대한 기본 이해만 있다면 자신이 필요한 함수들만 잘 검색해서 찾아보기만 해도 최소한 기본 코딩은 가능할 겁니다. 그렇기 때문에 배운 그대로 복사 붙여 넣기 하듯이 학습을 하기보다는 이 문법이 왜 그런지, 무슨 기능을 하는지를 익히는 것이 중요하죠.
다음 포스팅에서는 문법-2 인 '절차'에 대해 알아보고자 합니다. 만약 이해가 되지 않거나 해석하기 어려운 코드 등 기타 질문이 있다면 얼마든지 댓글 남겨주시면 답변드리겠습니다. 그럼 이쯤에서 글을 마치도록 하겠습니다.
'프로그래밍 기초' 카테고리의 다른 글
메모리 구조 [Memory Structure] (84) | 2021.01.31 |
---|---|
2진수의 수와 음수 표현법 [1의 보수와 2의 보수] (73) | 2021.01.01 |
프로그래밍 언어와 빌드 과정 [Build Process] (22) | 2020.11.27 |
객체지향(OOP)과 절차적 프로그래밍(PP) (32) | 2020.10.24 |
프로그래밍 언어의 단어와 문법 - 2 [프로그래밍] (4) | 2020.10.24 |