C나 C++에서 Ruby로

Ruby에서 코드가 C 또는 C++와 어떻게 다른지 항목별로 설명하는 것은 상당히 큰 차이가 있기 때문에 어렵습니다. 이 어려움의 원인 중 하나는 Ruby 런타임이 많은 일을 해 주기 때문입니다. Ruby는 C의 “숨겨진 메커니즘 없음” 원칙에서 가능한 한 멀리 있는 것 같습니다. Ruby의 요점은 런타임이 더 많은 작업을 수행하는 대신 인간의 작업을 더 쉽게 만드는 것입니다. 최적화를 위해 코드를 프로파일링 하지 않는 한, Ruby를 사용할 때 “컴파일러를 행복하게 유지”하는 데 조금도 신경을 쓸 필요가 없습니다.

즉, Ruby 코드가 “같은 일을 하는” C 또는 C++ 코드보다 훨씬 느리게 실행될 것으로 예상할 수 있습니다. 동시에 Ruby 프로그램을 얼마나 빨리 시작하고 실행할 수 있는지, 작성하는 데 몇 줄의 코드가 필요한지 빠르게 이해할 수 있습니다. Ruby는 C++보다 훨씬 간단합니다. Ruby는 여러분을 응석받이로 만들 것입니다.

Ruby는 정적으로 타입이 결정되지 않고 동적으로 결정됩니다. 런타임은 실행 시간에 가능한 한 많은 작업을 수행합니다. 예를 들어, Ruby 프로그램이 “링크”(즉, 로드 및 사용)할 모듈이나 미리 호출할 메서드를 알 필요가 없습니다.

다행스럽게도 Ruby와 C는 건강한 공생 관계를 가지고 있습니다. Ruby는 소위 “확장 모듈”을 지원합니다. 이들은 Ruby 프로그램에서 사용할 수 있지만(외부에서 볼 때 다른 Ruby 모듈처럼 보이고 작동함) C로 작성된 모듈입니다. 이런 식으로 Ruby 소프트웨어의 성능에 중요한 부분을 구획화하고 순수한 C로 만들 수 있습니다.

물론 Ruby 자체는 C로 작성되었습니다.

C와 비슷한 점

C처럼, Ruby에서도…

  • 원하는 경우 절차적으로 프로그래밍할 수 있습니다(그러나 내부에서는 여전히 객체 지향일 것입니다).
  • 대부분의 연산자는 동일합니다(복합 할당 및 비트 연산자 포함). 그러나 Ruby에는 ++ 또는 --가 없습니다.
  • __FILE____LINE__이 있습니다.
  • 특별한 const 키워드는 없지만 상수도 쓸 수 있습니다. 상수인지 아닌지는 명명 규칙으로 결정됩니다. 대문자로 시작하는 이름은 상수입니다.
  • 문자열은 큰따옴표로 묶습니다.
  • 문자열은 변경 가능합니다.
  • man 페이지와 마찬가지로 ri 명령을 사용하여 터미널 창에서 대부분의 문서를 읽을 수 있습니다.
  • 동일한 종류의 커맨드 라인 디버거를 사용할 수 있습니다.

C++와 비슷한 점

C++처럼, Ruby에서도…

  • 대부분 같은 연산자를 사용합니다(심지어 ::까지). <<는 종종 배열에 요소를 추가하는 데 사용됩니다. 하지만 주의할 것이 하나 있습니다. Ruby에서는 ->를 사용하지 않습니다. 항상 .입니다.
  • public, private, protected는 유사한 작업을 수행합니다.
  • 상속 구문은 동일하게 한 문자이지만 : 대신 <를 사용합니다.
  • C++에서 namespace가 사용되는 방식과 유사하게 코드를 “모듈”에 넣을 수 있습니다.
  • 예외도 비슷한 방식으로 작동하지만 순수 예외를 보호하기 위해 키워드 이름이 변경되었습니다.

C와 다른 점

C와는 다르게, Ruby에서는…

  • 코드를 컴파일할 필요가 없습니다. 직접 실행하면 됩니다.
  • 객체는 강 타입입니다(변수 이름 자체에는 타입이 전혀 없음).
  • 매크로나 전처리기가 없습니다. 캐스팅이 없습니다. 포인터도 없습니다(포인터 연산도 없습니다). typedef, sizeof, enum도 없습니다.
  • 헤더 파일이 없습니다. 메인 소스 코드 파일에서 함수(일반적으로 “메서드”라고 함)와 클래스를 정의하기만 하면 됩니다.
  • #define이 없습니다. 대신 상수를 사용하세요.
  • 모든 변수는 힙에 저장됩니다. 또한, 가비지 컬렉터가 처리하므로 직접 해제할 필요가 없습니다.
  • 메서드(예: 함수)에 대한 인수는 값으로 전달되며 그 값은 항상 객체 참조입니다.
  • #include <foo> 또는 #include "foo" 대신 require 'foo'를 사용합니다.
  • 어셈블리를 사용할 수 없습니다.
  • 줄 끝에 세미콜론이 없습니다.
  • ifwhile 조건 표현식을 괄호 없이 적습니다.
  • 메서드(예: 함수) 호출에 대한 괄호는 종종 생략 가능합니다.
  • 일반적으로 중괄호를 사용하지 않습니다. end 키워드로 여러 줄 구성(while 루프 등)을 끝냅니다.
  • do 키워드는 소위 “블록”을 위한 것입니다. C와 같은 “do 문”이 없습니다.
  • “블록”이라는 용어는 다른 의미를 가집니다. 실행하는 동안 메서드 본문이 블록을 호출할 수 있도록 메서드 호출과 연결하는 코드 블록을 가리킵니다.
  • 변수 선언이 없습니다. 필요할 때 즉시 새 이름을 지정하기만 하면 됩니다.
  • 참 거짓을 확인할 때 falsenil만 거짓 값으로 평가됩니다. 다른 모든 것은 참입니다(0, 0.0, "0" 포함).
  • char가 없습니다. 단지 한 글자로 된 문자열입니다.
  • 문자열은 null 바이트로 끝나지 않습니다.
  • 배열 리터럴은 중괄호 대신 대괄호 안에 들어갑니다.
  • 배열에 더 많은 요소를 넣으면 배열이 자동으로 커집니다.
  • 두 개의 배열을 더하면 포인터 연산을 수행하는 대신 새롭고 더 큰 배열(물론 힙에 할당됨)을 반환합니다.
  • 대부분의 경우 모든 것이 표현식입니다(즉, while 문은 실제로 rvalue로 평가됩니다).

C++와 다른 점

C++와는 다르게, Ruby에서는…

  • 명시적인 참조가 없습니다. 즉, Ruby에서 모든 변수는 일부 객체에 대해 자동으로 역참조된 이름일 뿐입니다.
  • 객체는 강 타입이지만 동적 타입이 지정됩니다. 런타임은 실행 시간에 해당 메서드 호출이 실제로 작동하는지 확인합니다.
  • “생성자”는 클래스 이름 대신 initialize라고 합니다.
  • 모든 메서드는 항상 가상입니다.
  • “클래스”(정적) 변수 이름은 항상 @@로 시작합니다(예: @@total_widgets).
  • 멤버 변수에 직접 접근하지 않습니다. 공용 멤버 변수(Ruby에서 attributes로 부름)에 대한 모든 액세스는 메서드를 통해 이루어집니다.
  • this가 아니라 self입니다.
  • 일부 메서드는 ‘?’ 또는 ‘!’로 끝납니다. 실제로 메서드 이름의 일부분입니다.
  • 그 자체로는 다중 상속이 없습니다. Ruby에는 “믹스인”이 있습니다(즉, 모듈의 모든 인스턴스 메서드를 “상속”할 수 있음).
  • 일부 대소문자 규칙이 적용됩니다(예: 클래스 이름은 대문자로 시작하고 변수는 소문자로 시작).
  • 메서드 호출에 대한 괄호는 일반적으로 생략 가능합니다.
  • 언제든지 클래스를 다시 열고 메서드를 더 추가할 수 있습니다.
  • C++ 템플릿이 필요하지 않습니다(주어진 변수에 모든 종류의 객체를 할당할 수 있고 타입은 어쨌든 런타임에 파악되기 때문입니다). 캐스팅도 없습니다.
  • 이터레이션은 약간 다르게 수행됩니다. Ruby에서는 별도의 이터레이터 객체(vector<T>::const_iterator iter 등)를 사용하지 않습니다. 대신 연속적인 요소를 전달하는 코드 블록을 취하는 컨테이너 객체의 이터레이터 메서드(each 등)를 사용합니다.
  • 컨테이너 타입은 ArrayHash 두 가지뿐입니다.
  • 타입 변환이 없습니다. 그러나 Ruby를 사용하면 필요하지 않다는 것을 알게 될 것입니다.
  • 멀티스레딩은 내장되어 있지만 Ruby 1.8부터는 네이티브 스레드와 달리 “그린 스레드”(인터프리터 내에서만 구현됨)입니다.
  • 단위 테스트 라이브러리는 Ruby와 함께 표준으로 제공됩니다.