Module: Rus3::Procedure::List

Includes:
EmptyList, Predicate, Utils
Included in:
Evaluator::Environment, Vector
Defined in:
lib/rus3/procedure/list.rb

Overview

The module holds list operation proceduress of Scheme. Most of those procedures are defined in R(n)RS (the specification of Scheme language).

- R5RS 6.3.2 Pairs and lists
- R7RS 6.4   Pairs and lists

Constant Summary

Constants included from EmptyList

EmptyList::EMPTY_LIST

Instance Method Summary collapse

Methods included from EmptyList

#null?

Methods included from Predicate

#boolean?, #char?, #char_alphabetic?, #char_ci_eq?, #char_ci_ge?, #char_ci_gt?, #char_ci_le?, #char_ci_lt?, #char_eq?, #char_ge?, #char_gt?, #char_le?, #char_lower_case?, #char_lt?, #char_numeric?, #char_upper_case?, #char_whitespace?, #complex?, #eq?, #eqv?, #even?, #input_port?, #integer?, #list?, #negative?, #number?, #odd?, #output_port?, #pair?, #port?, #positive?, #procedure?, #rational?, #real?, #string?, #string_ci_eq?, #string_ci_ge?, #string_ci_gt?, #string_ci_le?, #string_ci_lt?, #string_eq?, #string_ge?, #string_gt?, #string_le?, #string_lt?, #symbol?, #vector?, #zero?

Methods included from Utils

#check_list, #check_pair, #check_upper_limit, #check_vector

Instance Method Details

#append(*lists) ⇒ Object

Concatenates given lists into a single list. Each argument must be a proper list, otherwise raises ListRequiredError.

- library procedure (R5RS): (append list ...)
- procedure (R7RS): (append list ...)


184
185
186
187
188
189
# File 'lib/rus3/procedure/list.rb', line 184

def append(*lists)
  lists.each { |lst|
    check_list(lst)
  }
  [].concat(*lists)
end

#caar(pair) ⇒ Object

Retrieves the CAR part of the CAR part of the given pair.

- library procedure (R5RS): (caar pair)
- procedure (R7RS): (caar pair)


121
122
123
# File 'lib/rus3/procedure/list.rb', line 121

def caar(pair)
  car(car(pair))
end

#cadr(pair) ⇒ Object

Retrieves the CAR part of the CDR part of the given pair.

- library procedure (R5RS): (cadr pair)
- procedure (R7RS): (cadr pair)


130
131
132
# File 'lib/rus3/procedure/list.rb', line 130

def cadr(pair)
  car(cdr(pair))
end

#car(pair) ⇒ Object

Returns the CAR part of the argument. If the arguemnt is not a pair, raises PairRequiredError.

- procedure (R5RS): (car pair)


43
44
45
46
47
48
49
50
51
52
53
# File 'lib/rus3/procedure/list.rb', line 43

def car(pair)
  case pair
  when Rus3::Pair
    pair.car
  when Array
    raise Rus3::PairOrListRequiredError, pair if pair.empty?
    pair[0]
  else
    raise Rus3::PairOrListRequiredError, pair
  end
end

#cdar(pair) ⇒ Object

Retrieves the CDR part of the CAR part of the given pair.

- library procedure (R5RS): (cdar pair)
- procedure (R7RS): (cdar pair)


139
140
141
# File 'lib/rus3/procedure/list.rb', line 139

def cdar(pair)
  cdr(car(pair))
end

#cddr(pair) ⇒ Object

Retrieves the CDR part of the CDR part of the given pair.

- libbrary procedure (R5RS): (cddr pair)
- procedure (R7RS): (cddr pair)


148
149
150
# File 'lib/rus3/procedure/list.rb', line 148

def cddr(pair)
  cdr(cdr(pair))
end

#cdr(pair) ⇒ Object

Returns the CDR part of the argument. If the arguemnt is not a pair, raises PairRequiredError.

- procedure (R5RS): (cdr pair)


60
61
62
63
64
65
66
67
68
69
70
# File 'lib/rus3/procedure/list.rb', line 60

def cdr(pair)
  case pair
  when Rus3::Pair
    pair.cdr
  when Array
    raise Rus3::PairOrListRequiredError, pair if pair.empty?
    pair[1..-1]
  else
    raise Rus3::PairOrListRequiredError, pair
  end
end

#cons(obj1, obj2) ⇒ Object

Constructs a Pair object with arguments.

- procedure (R5RS): (cons obj1 obj2)


23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rus3/procedure/list.rb', line 23

def cons(obj1, obj2)
  case obj2
  when Rus3::Pair
    if null?(obj2.cdr)    # (foo . ())
      [obj1, obj2.car]
    else
      Rus3::Pair.new(obj1, obj2)
    end
  when Array
    [obj1].concat(obj2)
  else
    Rus3::Pair.new(obj1, obj2)
  end
end

#length(lst) ⇒ Object

Returns the length of the arguemnt. If the argument is not a proper list, raises ListRequiredError.

- library procedure (R5RS): (length list)
- procedure (R7RS): (length list)


173
174
175
176
# File 'lib/rus3/procedure/list.rb', line 173

def length(lst)
  check_list(lst)
  lst.size
end

#list(*objs) ⇒ Object

Constructs a list from arguments in its order.

- library procedure (R5RS): (list obj ...)


163
164
165
# File 'lib/rus3/procedure/list.rb', line 163

def list(*objs)
  Array[*objs]
end

#list_ref(lst, k) ⇒ Object

Returns kth element of the argument. k must be less than the length of the list, otherwise, raises ExceedUppeerLimitError.

- library procedure (R5RS): (list-ref list k)
- procedure (R7RS): (list-ref list k)


223
224
225
226
227
228
# File 'lib/rus3/procedure/list.rb', line 223

def list_ref(lst, k)
  check_list(lst)
  check_upper_limit(k, length(lst))

  lst[k]
end

#list_tail(lst, k) ⇒ Object

Returns the sublist of the arguemnt by omitting the first k elements. The 2nd argument, k must be in 0..length(lst), otherwise raises ExceedUppeerLimitError.

This implementation logic comes from R5RS 6.3.2.

- library procedure (R5RS): (list-tail list k)
- procedure (R7RS): (list-tail list k)


210
211
212
213
214
215
# File 'lib/rus3/procedure/list.rb', line 210

def list_tail(lst, k)
  check_list(lst)
  check_upper_limit(k, length(lst)+1)

  lst.drop(k)
end

#reverse(lst) ⇒ Object

Returns a list of the same elements in reverse order.

- library procedure (R5RS): (reverse list)
- procedure (R7RS): (reverse list)


196
197
198
199
# File 'lib/rus3/procedure/list.rb', line 196

def reverse(lst)
  check_list(lst)
  lst.sort {|a, b| b <=> a}
end

#set_car!(pair, obj) ⇒ Object

Replaces the CAR part with the 2nd argument and returns UNDEF. If the 1st arguemnt is not a pair, raises PairRequiredError.

- procedure (R5RS): (set-car! pair obj)


77
78
79
80
81
82
83
84
85
86
87
# File 'lib/rus3/procedure/list.rb', line 77

def set_car!(pair, obj)
  case pair
  when Rus3::Pair
    pair.set_car!(obj)
  when Array
    pair[0] = obj
  else
    raise Rus3::PairOrListRequiredError, pair
  end
  Rus3::UNDEF
end

#set_cdr!(pair, obj) ⇒ Object

Replaces the CDR part with the 2nd argument and returns UNDEF. If the 1st arguemnt is not a pair, raises PairRequiredError.

- procedure (R5RS): (set-cdr! pair obj)


94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/rus3/procedure/list.rb', line 94

def set_cdr!(pair, obj)
  case pair
  when Rus3::Pair
    pair.set_cdr!(obj)
  when Array
    case obj
    when Array
      pair.slice!(1, pair.size - 1)
      pair.concat(obj)
    else
      # If `obj` was not a proper list of Scheme, the result of
      # `set_cdr!` would be a Pair instance.  However, in this
      # case, the given `pair` is an Array instance, there is no
      # way to replace it with a new Pair instance.
      raise UnsupportedFeatureError.new("set_cdr!", obj)
    end
  else
    raise Rus3::PairOrListRequiredError, pair
  end
  Rus3::UNDEF
end