본문 바로가기
프로그래밍언어론

[프로그래밍언어론] 28. 프로그래밍 언어 패러다임(PL Paradigm)

by 파스텔코랄 2023. 11. 6.

프로그래밍 언어 패러다임(PL Paradigm)

  • 프로그래밍 언어가 따르는 원칙과 전략
    • 예) 절차적, 명령적, OOP, 기능적, 논리 등
  • 하나의 프로그래밍 언어는 여러 패러다임을 따를 수 있다.
    • Java - 명령형 및 객체 지향

 


 

언어 패러다임(Language Paradigms)

  • 프로그래밍 언어를 그룹화하거나 분류하는 방법은 매우 다양하다.
  • 명령형(Imperative)
    • 절차적(procedural) - Fortran, Pascal, Basic, C
    • 객체 지향(object-oriented) - Smalltalk, C++, Java
    • 스크립팅 언어(scripting languages) - Perl, Python, JavaScript
  • 선언형(Declarative)
    • 함수형(functional) 프로그래밍 - Scheme, ML, Haskel
    • 논리형(logic) 프로그래밍 - Prolog, Datalog

 



명령형 언어(Imperative Languages)

  • 명령형 : 권위 있는 명령(command or statements)을 제공
  • 할당(assignments)을 사용하여 프로그램 상태를 변경
  • 프로그램이 '떻게 작동하는지(알고리즘)에 중점
  • 낮은 수준 : 기계어 코드(명령어)는 프로그램 상태(예: 레지스터/메모리)를 수정
  • 상위 수준 : 프로그램 상태는 변수로 설명, 명령문은 기계 명령어


선언형 언어(Declarative Languages)

  • 선언형 언어는 종종 비명령형 언어로 정의
  • 어떻게 하는 것이 아니라 무엇을 해야 하는지, 또는 프로그램이 무엇이 되어야 하는지를 설명
  • 프로그램은 컴퓨터가 수행해야 할 명령을 제공하는 것이 아니라 원하는 결과를 설명
  • 함수형(functional) 언어와 논리형(logic) 언어
  • 그러나 함수형(functional) 언어와 논리형(logic) 언어 사이에는 명확한 구분이 없다.

 


 

예제: 유클리드 알고리즘

명령형(Imperative) : C++
명령형 : main()에서 시작, 프로그램을 단계별로 따라갈 수 있다.
int gcd(int a, int b) {
    if (b == 0)
        return a;
    else
        return gcd(b, a%b);
}
int main() {
    cout << gcd(10, 5);
    return 0;
}
명령형(Imperative), OOP : Java
명령형 : main() 부분을 사용하여 프로그램을 단계별로 따라갈 수도 있다.
OOP : 프로그램은 GCD 클래스를 정의하고 내부에 해당 정보를 숨기고 클래스에 대한 작업을 제공한다.
public class GCD {
    private int a, b;
    public GCD(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int compute() {
        return a >= b ? gcd(a, b) : gcd(b, a);
    }
    private int gcd(int a, int b) {
        if (b==0);
            return a;
        else
            return gcd(b, a%b);
    }
    public static void main(String[] args) {
        System.out.println(new GCD(12, 4).compute());
    }
}
선언형(Declarative), 함수형(functional) : Scheme
선언형 : 단순히 gcd 함수가 무엇인지 정의
명령형 : 그래도 화면에 무언가를 인쇄하라는 명령이 있다.
(define (gcd a b)
    (if (equal? b 0)
        a
        (gcd b (modulo a b))))
(display (gcd 12 4))
선언형(Declarative), 함수형(functional) : Scala
선언형 : gcd 함수가 무엇인지 정의
또한 객체 GCD, main() 메소드와 같은 Java와 유사한 기능도 포함
object GCD {
    def main(args: Array[String]) : Unit = {
        print(gcd(12, 4))
    }
    def gcd(a: Int, b: Int): Int =
        if(a%b == 0)
            b
        else
            gcd(b, a%b)
}
선언형(Declarative), 논리형(Logic) : Prolog
선언형 : gcd에 대한 사실과 규칙을 설명
사실과 규칙을 바탕으로 질문(또는 질의)을 할 수 있다.
gcd(A, B, G) :- A =B; B = 0, G = A.
gcd(A, B, G) :- A =0, G = B.
gcd(A, B, G) :- A > B, C is A mod B, gcd(C, B, G).
gcd(A, B, G) :- A < B, C is B mod A, gcd(C, A, G).

?- gcd(12, 4, G).
G = 4 .
?- gcd(12, 6, G).
G = 6 .

 



우리는 왜 패러다임에 관심을 갖는가?

  • 특정 패러다임을 따르는 프로그래밍 언어는 종종 공통된 특성을 공유한다.
    • 패러다임을 이해하면 각 언어의 특징도 더 쉽게 이해할 수 있다.
  • 우리가 아는 대부분의 프로그래밍 언어는 명령형(Imperative) + OOP인데 왜 다른 언어가 필요한가?
    • 프로그래밍 언어 역시 소프트웨어이며 지속적으로 발전하고 있다.
    • 다른 패러다임에서 유용하다고 간주되는 일부 기능은 향후 채택될 수 있다.



새로운 패러다임 기능의 예

  • Java 8에서는 람다 표현식과 스트림이 도입되었다.
  • 동일한 기능 구현을 위해 다양한 옵션을 선택할 수 있다.
  • 이 예에서는 명령형, 명령형 + 함수형, 함수형 특징을 사용하여 Java에서 단어 수를 계산하는 방법을 보여준다.
String[] arr = { "SeoulTech", "PL", "theory", "course" };
List words = Arrays.asList(arr);

// 명령형(Imperative)
for (Strings: words)
    if (count.containsKey(s))
        count.put(s, count.get(s) + 1);
    else
        count.put(s, 1);

// 명령형(Imperative) + 함수형(Functional)
for (Strings: words)
    count2.compute(s,(k, v) -> (v == null) ? 1 : v + 1);

// 함수형(Functional)
words.forEach(
    s -> count.compute(s,(k, v) -> (v == null) ? 1 : v + 1));

 

댓글