# Chapter6. 표준 타입

## 6.1 숫자

* 루비는 정수, 부동소수점, 유리수, 복소수 등을 지원한다.
* 정수의 길이는 정해지지 않는다.
  * 최대 길이는 사용하는 시스템의 메모리 크기에 의해 결정된다.
  * 특정 범위의 정수는 `Fixnum` 객체로, 매우 큰 정수는 `Bignum` 객체로 저장된다.
  * 값의 변화에 따라 수시로 변경된다.

### 숫자는 어떻게 상호 작용하는가?

* 두 숫자가 서로 다른 클래스라면 좀 더 일반적인 클래스로 숫자가 변환된다.

```ruby
1 + 2 # => 3
1 + 2.0 # => 3.0
1.0 + Complex(1,2) # => (2.0 + 2i)
```

### 숫자를  사용한 반복

* 정수는 몇 가지 유용한 반복자를 지원한다.

```ruby
3.times { print "haha "}
1.upto(5) { ~~ }
99.downto(50) { ~~ }
50.step(80, 5) { ~~ }
```

* 다른 반복자들과 마찬가지로 블록을 넘기지 않으면 `Enumerator` 객체를 반환한다.

## 6.2 문자열

* 루비 문자열은 문자열의 시퀀스다. 보통 출력 가능한 문자를 저장하지만, 반드시 그래야만 하는 것은 아니다.
* 문자열에는 이진(binary) 데이터를 저장할 수 있다.
* 문자열은 `String` 클래스의 객체다. 문자열은 주로 문자열 리터럴을 통해 생성된다.
* 문자열 리터럴은 구분 문자(`delemiter`) 사이에 문자 시퀀스를 쓰는 것이다.
  * 이진데이터는 다른 문자처럼 프로그램의 소스 안에 표현하기가 어렵기 때문에 문자열 리터럴에는 이스케이프 시퀀스를 함께 사용할 수 있도록 했다.
  * 문자열 리터럴 각각은 프로그램이 컴파일 될 때 해당 이진 값으로 변환된다.
* 작은 따옴표와 큰 따옴표 둘 다 사용할 수 있지만, 큰 따옴표가 지원하는 기능이 더 많다.
* 따옴표가 아닌 `%q/문자열/`, `%Q!문자열!`, `Q{문자열}` 등의 스트링 리터럴로도 문자열을 만들 수 있다.
* 또한 `here` 도큐먼트로도 만들 수 있다.
  * `<<~END_OF_STRING`으로 시작해서 `END_OF_STRING`로 끝내면 된다

```ruby
class Test
  attr_accessor :str
  def initialize(a)
    @str = <<~END_OF_STRING
      Input value: #{a}
    END_OF_STRING
  end
end

a = Test.new(123)
puts a.str

s2 = <<~END_OF_STRING
The Body of string is here!!!
  END_OF_STRING
```

### 문자열 다루기

* `String` 클래스는 루비 전체 내장 클래스 중에서 가장 크다. 100개 이상의 표준 메서드가 정의되어 있다. 따라서 나중에 공부하도록 하자...

## 6.3 범위

* 범위는 주로 시퀀스, 조건, 간격을 구현하는데 사용된다.
  * 루비는 이 범위 부분에서도 막강한 기능을 자랑함.

### 범위로 시퀀스 표현하기

* 범위의 가장 자연스러운 사용법은 시퀀스를 표현하는 것이다.
* 시퀀스는 시작값, 종료값을 비롯해 차례로 값을 만들어 내는 방법으로 이루어진다.
* 루비에서 시퀀스는 `..` 과 `...` 범위 연산자를 이용해 만든다.
  * `..`: 양쪽 경계 모두 포함
  * `...`: `[)` - 왼쪽 포함, 오른쪽 경계 미포함
* 범위는 `to_a` 메서드를 사용해 배열로 변환하거나 `to_enum` 메서드를 사용해 `Enumerator` 객체로 변환할 수 있다.

```ruby
(1..10).to_a # => 배열
(1..5).to_enum # => Enumerator
```

* 지금까지 본 것은 우리가 루비의 내장 클래스였고, 우리가 직접 구현한 클래스에서 범위연산자를 사용하기 위해서는 어떻게 해야할까?
  * 이를 위해서는 객체가 ***순서대로 다음 객체*** 를 반환하는 `succ` 메서드를 구현해야하고
  * `<=>`를 이용해서 비교 가능해야 한다. (즉 `Comparable` 모듈을 `include` 해야함)

### 범위로 조건 표현하기

* 범위를 시퀀스로 사용하기도 하지만 조건절에 사용할 수도 있다.
* 아래의 예시는 표준입력으로 입력을 했을 때 `start`가 출력의 토글 스위치가 된다. `start`가 들어온 순간부터 입력이 에코잉됨

```ruby
while line = gets
  puts line if line =~ /start/ .. line =~ /end/
end
```

### 범위로 간격 표현하기

* 범위의 마지막 용도는 어떤 값이 범위에 포함되는지 따지는 인터벌 테스트다.
* 이를 위해 `case` 문에서 사용하는 동등 연산자 `===`를 이용한다.

```ruby
(1..10) === 5 # => true
(1..10) === 15 # => false
(1..10) === 3.141592 # => true
('a'..'z')  === 'c' # => true
```

* 간격 테스트는 `case` 문에서 자주 사용된다.
  * `case`에서는 `...`를 사용하는 것이 좋다.

```ruby
case car_age
when 0...1
  puts "Mmm Its new!"
when 1...3
  puts "Mmm zz"
else
  puts "aaa"
end
```
