Class: RDF::List
- Inherits:
-
Object
- Object
- RDF::List
- Includes:
- Comparable, Enumerable, Value
- Defined in:
- lib/rdf/model/list.rb
Overview
An RDF list.
Constant Summary collapse
- UNSET =
Object.new.freeze
- NIL =
The canonical empty list.
RDF::List.new(subject: RDF.nil).freeze
Instance Attribute Summary collapse
-
#graph ⇒ RDF::Graph
readonly
The underlying graph storing the statements that constitute this list.
-
#subject ⇒ RDF::Resource
readonly
The subject term of this list.
Class Method Summary collapse
-
.[](*values) ⇒ RDF::List
Constructs a new list from the given ‘values`.
Instance Method Summary collapse
-
#&(other) ⇒ RDF::List
Returns the set intersection of this list and ‘other`.
-
#*(int_or_str) ⇒ RDF::List
Returns either a repeated list or a string concatenation of the elements in this list.
-
#+(other) ⇒ RDF::List
Returns the concatenation of this list and ‘other`.
-
#-(other) ⇒ RDF::List
Returns the difference between this list and ‘other`, removing any elements that appear in both lists.
-
#<<(value) ⇒ RDF::List
Appends an element to the tail of this list.
-
#<=>(other) ⇒ Integer
Compares this list to ‘other` for sorting purposes.
-
#[]=(*args) ⇒ Object
Element Assignment — Sets the element at ‘index`, or replaces a subarray from the `start` index for `length` elements, or replaces a subarray specified by the `range` of indices.
-
#at(index) ⇒ RDF::Term?
(also: #nth)
Returns the element at ‘index`.
-
#clear ⇒ RDF::List
Empties this list.
-
#each ⇒ Enumerator
Yields each element in this list.
-
#each_statement(&block) ⇒ Enumerator
(also: #to_rdf)
Yields each statement constituting this list.
-
#each_subject {|subject| ... } ⇒ Enumerator
Yields each subject term constituting this list.
-
#eighth ⇒ RDF::Term
Returns the eighth element in this list.
-
#empty? ⇒ Boolean
Returns ‘true` if this list is empty.
-
#eql?(other) ⇒ Integer
Compares this list to ‘other` using eql? on each component.
-
#fetch(index, default = UNSET) ⇒ RDF::Term?
Returns element at ‘index` with default.
-
#fifth ⇒ RDF::Term
Returns the fifth element in this list.
-
#first ⇒ RDF::Term
Returns the first element in this list.
-
#first_subject ⇒ RDF::Resource
Returns the first subject term constituting this list.
-
#fourth ⇒ RDF::Term
Returns the fourth element in this list.
-
#index(value) ⇒ Integer
Returns the index of the first element equal to ‘value`, or `nil` if no match was found.
-
#initialize(subject: nil, graph: nil, values: nil) {|list| ... } ⇒ List
constructor
Initializes a newly-constructed list.
-
#inspect ⇒ String
Returns a developer-friendly representation of this list.
-
#join(sep = $,) ⇒ String
Returns a string created by converting each element of this list into a string, separated by ‘sep`.
-
#last ⇒ RDF::Term
Returns the last element in this list.
-
#last_subject ⇒ RDF::Resource
Returns the last subject term constituting this list.
-
#length ⇒ Integer
(also: #size)
Returns the length of this list.
-
#list? ⇒ Boolean
Is this a List?.
-
#ninth ⇒ RDF::Term
Returns the ninth element in this list.
-
#rest ⇒ RDF::List
Returns a list containing all but the first element of this list.
- #rest_subject ⇒ RDF::Resource
-
#reverse ⇒ RDF::List
Returns the elements in this list in reversed order.
-
#second ⇒ RDF::Term
Returns the second element in this list.
-
#seventh ⇒ RDF::Term
Returns the seventh element in this list.
-
#shift ⇒ RDF::Term
Removes and returns the element at the head of this list.
-
#sixth ⇒ RDF::Term
Returns the sixth element in this list.
-
#slice(*args) ⇒ RDF::Term
(also: #[])
Returns a slice of a list.
-
#sort(&block) ⇒ RDF::List
Returns the elements in this list in sorted order.
-
#sort_by(&block) ⇒ RDF::List
Returns the elements in this list in sorted order.
-
#tail ⇒ RDF::List
Returns a list containing the last element of this list.
-
#tenth ⇒ RDF::Term
Returns the tenth element in this list.
-
#third ⇒ RDF::Term
Returns the third element in this list.
-
#to_a ⇒ Array
Returns the elements in this list as an array.
-
#to_s ⇒ String
Returns a string representation of this list.
-
#to_set ⇒ Set
Returns the elements in this list as a set.
-
#to_term ⇒ RDF::Resource
Returns the subject of the list.
-
#uniq ⇒ RDF::List
Returns a new list with the duplicates in this list removed.
-
#unshift(value) ⇒ RDF::List
Appends an element to the head of this list.
-
#valid? ⇒ Boolean
Validate the list ensuring that * rdf:rest values are all BNodes are nil * each subject has exactly one value for ‘rdf:first` and `rdf:rest`.
-
#|(other) ⇒ RDF::List
Returns the set union of this list and ‘other`.
Methods included from Value
#anonymous?, #canonicalize, #canonicalize!, #constant?, #graph?, #inspect!, #invalid?, #iri?, #literal?, #node?, #resource?, #statement?, #term?, #to_nquads, #to_ntriples, #type_error, #uri?, #validate!, #variable?
Methods included from Enumerable
#dump, #each_graph, #each_object, #each_predicate, #each_quad, #each_term, #each_triple, #enum_for, #enum_graph, #enum_object, #enum_predicate, #enum_quad, #enum_statement, #enum_subject, #enum_term, #enum_triple, #graph_names, #has_graph?, #has_object?, #has_predicate?, #has_quad?, #has_statement?, #has_subject?, #has_term?, #has_triple?, #invalid?, #method_missing, #objects, #predicates, #project_graph, #quads, #respond_to_missing?, #statements, #subjects, #supports?, #terms, #to_hash, #triples, #validate!
Methods included from Util::Aliasing::LateBound
Methods included from Countable
Constructor Details
#initialize(subject: nil, graph: nil, values: nil) {|list| ... } ⇒ List
Initializes a newly-constructed list.
Instantiates a new list based at ‘subject`, which should be an RDF::Node. List may be initialized using passed `values`.
If a ‘values` initializer is set with an empty list, `subject` will be used as the first element in the list. Otherwise, if the list is not empty, `subject` identifies the first element of the list to which `values` are prepended yielding a new `subject`. Otherwise, if there are no initial `values`, and `subject` does not identify an existing list in `graph`, the list remains identified by `subject`, but will be invalid.
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
# File 'lib/rdf/model/list.rb', line 59 def initialize(subject: nil, graph: nil, values: nil, &block) @subject = subject || RDF.nil @graph = graph || RDF::Graph.new is_empty = @graph.query(subject: subject, predicate: RDF.first).empty? if subject && is_empty # An empty list with explicit subject and value initializers @subject = RDF.nil first, *values = Array(values) if first || values.length > 0 # Intantiate the list from values, and insert the first value using subject. values.reverse_each {|value| self.unshift(value)} graph.insert RDF::Statement(subject, RDF.first, first || RDF.nil) graph.insert RDF::Statement(subject, RDF.rest, @subject) end @subject = subject else # Otherwise, prepend any values, which resets @subject Array(values).reverse_each {|value| self.unshift(value)} end if block_given? case block.arity when 1 then block.call(self) else instance_eval(&block) end end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class RDF::Enumerable
Instance Attribute Details
#graph ⇒ RDF::Graph (readonly)
Returns the underlying graph storing the statements that constitute this list.
140 141 142 |
# File 'lib/rdf/model/list.rb', line 140 def graph @graph end |
#subject ⇒ RDF::Resource (readonly)
Returns the subject term of this list.
136 137 138 |
# File 'lib/rdf/model/list.rb', line 136 def subject @subject end |
Class Method Details
.[](*values) ⇒ RDF::List
Constructs a new list from the given ‘values`.
The list will be identified by a new autogenerated blank node, and backed by an initially empty in-memory graph.
30 31 32 |
# File 'lib/rdf/model/list.rb', line 30 def self.[](*values) self.new(subject: nil, graph: nil, values: values) end |
Instance Method Details
#&(other) ⇒ RDF::List
Returns the set intersection of this list and ‘other`.
The resulting list contains the elements common to both lists, with no duplicates.
156 157 158 |
# File 'lib/rdf/model/list.rb', line 156 def &(other) RDF::List[*(to_a & other.to_a)] end |
#*(times) ⇒ RDF::List #*(sep) ⇒ RDF::List
Returns either a repeated list or a string concatenation of the elements in this list.
230 231 232 233 234 235 |
# File 'lib/rdf/model/list.rb', line 230 def *(int_or_str) case int_or_str when Integer then RDF::List[*(to_a * int_or_str)] else join(int_or_str.to_s) end end |
#+(other) ⇒ RDF::List
Returns the concatenation of this list and ‘other`.
187 188 189 |
# File 'lib/rdf/model/list.rb', line 187 def +(other) RDF::List[*(to_a + other.to_a)] end |
#-(other) ⇒ RDF::List
Returns the difference between this list and ‘other`, removing any elements that appear in both lists.
201 202 203 |
# File 'lib/rdf/model/list.rb', line 201 def -(other) RDF::List[*(to_a - other.to_a)] end |
#<<(value) ⇒ RDF::List
Appends an element to the tail of this list.
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/rdf/model/list.rb', line 405 def <<(value) value = normalize_value(value) if empty? @subject = new_subject = RDF::Node.new else old_subject, new_subject = last_subject, RDF::Node.new graph.delete([old_subject, RDF.rest, RDF.nil]) graph.insert([old_subject, RDF.rest, new_subject]) end graph.insert([new_subject, RDF.first, value.is_a?(RDF::List) ? value.subject : value]) graph.insert([new_subject, RDF.rest, RDF.nil]) self end |
#<=>(other) ⇒ Integer
Compares this list to ‘other` for sorting purposes.
447 448 449 |
# File 'lib/rdf/model/list.rb', line 447 def <=>(other) to_a <=> other.to_a # TODO: optimize this end |
#[]=(index, term) ⇒ RDF::Term #[]=(start, length, value) ⇒ RDF::Term, RDF::List #[]=(range, value) ⇒ RDF::Term, RDF::List
Element Assignment — Sets the element at ‘index`, or replaces a subarray from the `start` index for `length` elements, or replaces a subarray specified by the `range` of indices.
If indices are greater than the current capacity of the array, the array grows automatically. Elements are inserted into the array at ‘start` if length is zero.
Negative indices will count backward from the end of the array. For ‘start` and `range` cases the starting index is just before an element.
An ‘IndexError` is raised if a negative index points past the beginning of the array.
(see #unshift).
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 |
# File 'lib/rdf/model/list.rb', line 299 def []=(*args) start, length = 0, 0 ary = self.to_a value = case args.last when Array then args.last when RDF::List then args.last.to_a else [args.last] end ret = case args.length when 3 start, length = args[0], args[1] ary[start, length] = value when 2 case args.first when Integer raise ArgumentError, "Index form of []= takes a single term" if args.last.is_a?(Array) ary[args.first] = args.last.is_a?(RDF::List) ? args.last.subject : args.last when Range ary[args.first] = value else raise ArgumentError, "Index form of must use an integer or range" end else raise ArgumentError, "List []= takes one or two index values" end # Clear the list and create a new list using the existing subject subject = @subject unless ary.empty? || @subject == RDF.nil self.clear new_list = RDF::List.new(subject: subject, graph: @graph, values: ary) @subject = new_list.subject ret # Returns inserted values end |
#at(index) ⇒ RDF::Term? Also known as: nth
Returns the element at ‘index`.
563 564 565 566 |
# File 'lib/rdf/model/list.rb', line 563 def at(index) each.with_index { |v, i| return v if i == index } return nil end |
#clear ⇒ RDF::List
Empties this list
389 390 391 392 393 394 |
# File 'lib/rdf/model/list.rb', line 389 def clear until empty? shift end return self end |
#each ⇒ Enumerator
Yields each element in this list.
780 781 782 783 784 785 786 787 788 |
# File 'lib/rdf/model/list.rb', line 780 def each return to_enum unless block_given? each_subject do |subject| if value = graph.first_object(subject: subject, predicate: RDF.first) yield value # FIXME end end end |
#each_statement(&block) ⇒ Enumerator Also known as: to_rdf
Yields each statement constituting this list.
800 801 802 803 804 805 806 |
# File 'lib/rdf/model/list.rb', line 800 def each_statement(&block) return enum_statement unless block_given? each_subject do |subject| graph.query(subject: subject, &block) end end |
#each_subject {|subject| ... } ⇒ Enumerator
Yields each subject term constituting this list.
757 758 759 760 761 762 763 764 765 766 767 768 |
# File 'lib/rdf/model/list.rb', line 757 def each_subject return enum_subject unless block_given? subject = self.subject yield subject loop do rest = graph.first_object(subject: subject, predicate: RDF.rest) break if rest.nil? || rest.eql?(RDF.nil) yield subject = rest end end |
#eighth ⇒ RDF::Term
Returns the eighth element in this list.
654 655 656 |
# File 'lib/rdf/model/list.rb', line 654 def eighth at(7) end |
#empty? ⇒ Boolean
Returns ‘true` if this list is empty.
460 461 462 |
# File 'lib/rdf/model/list.rb', line 460 def empty? graph.query(subject: subject, predicate: RDF.first).empty? end |
#eql?(other) ⇒ Integer
Compares this list to ‘other` using eql? on each component.
432 433 434 |
# File 'lib/rdf/model/list.rb', line 432 def eql?(other) to_a.eql? other.to_a # TODO: optimize this end |
#fetch(index, default = UNSET) ⇒ RDF::Term?
Returns element at ‘index` with default.
543 544 545 546 547 548 549 550 551 552 |
# File 'lib/rdf/model/list.rb', line 543 def fetch(index, default = UNSET) val = at(index) return val unless val.nil? case when block_given? then yield index when !default.eql?(UNSET) then default else raise IndexError, "index #{index} not in the list #{self.inspect}" end end |
#fifth ⇒ RDF::Term
Returns the fifth element in this list.
621 622 623 |
# File 'lib/rdf/model/list.rb', line 621 def fifth at(4) end |
#first ⇒ RDF::Term
Returns the first element in this list.
577 578 579 |
# File 'lib/rdf/model/list.rb', line 577 def first graph.first_object(subject: first_subject, predicate: RDF.first) end |
#first_subject ⇒ RDF::Resource
Returns the first subject term constituting this list.
This is equivalent to ‘subject`.
723 724 725 |
# File 'lib/rdf/model/list.rb', line 723 def first_subject subject end |
#fourth ⇒ RDF::Term
Returns the fourth element in this list.
610 611 612 |
# File 'lib/rdf/model/list.rb', line 610 def fourth at(3) end |
#index(value) ⇒ Integer
Returns the index of the first element equal to ‘value`, or `nil` if no match was found.
490 491 492 493 494 495 |
# File 'lib/rdf/model/list.rb', line 490 def index(value) each.with_index do |v, i| return i if v == value end return nil end |
#inspect ⇒ String
Returns a developer-friendly representation of this list.
927 928 929 930 931 932 933 |
# File 'lib/rdf/model/list.rb', line 927 def inspect if self.equal?(NIL) 'RDF::List::NIL' else sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, join(', ')) end end |
#join(sep = $,) ⇒ String
Returns a string created by converting each element of this list into a string, separated by ‘sep`.
820 821 822 |
# File 'lib/rdf/model/list.rb', line 820 def join(sep = $,) map(&:to_s).join(sep) end |
#last ⇒ RDF::Term
Returns the last element in this list.
688 689 690 |
# File 'lib/rdf/model/list.rb', line 688 def last graph.first_object(subject: last_subject, predicate: RDF.first) end |
#last_subject ⇒ RDF::Resource
Returns the last subject term constituting this list.
743 744 745 |
# File 'lib/rdf/model/list.rb', line 743 def last_subject each_subject.to_a.last # TODO: optimize this end |
#length ⇒ Integer Also known as: size
Returns the length of this list.
473 474 475 |
# File 'lib/rdf/model/list.rb', line 473 def length each.count end |
#list? ⇒ Boolean
Is this a RDF::List?
97 98 99 |
# File 'lib/rdf/model/list.rb', line 97 def list? true end |
#ninth ⇒ RDF::Term
Returns the ninth element in this list.
665 666 667 |
# File 'lib/rdf/model/list.rb', line 665 def ninth at(8) end |
#rest ⇒ RDF::List
Returns a list containing all but the first element of this list.
699 700 701 |
# File 'lib/rdf/model/list.rb', line 699 def rest (subject = rest_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph) end |
#rest_subject ⇒ RDF::Resource
732 733 734 |
# File 'lib/rdf/model/list.rb', line 732 def rest_subject graph.first_object(subject: subject, predicate: RDF.rest) end |
#reverse ⇒ RDF::List
Returns the elements in this list in reversed order.
832 833 834 |
# File 'lib/rdf/model/list.rb', line 832 def reverse RDF::List[*to_a.reverse] end |
#second ⇒ RDF::Term
Returns the second element in this list.
588 589 590 |
# File 'lib/rdf/model/list.rb', line 588 def second at(1) end |
#seventh ⇒ RDF::Term
Returns the seventh element in this list.
643 644 645 |
# File 'lib/rdf/model/list.rb', line 643 def seventh at(6) end |
#shift ⇒ RDF::Term
Removes and returns the element at the head of this list.
368 369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/rdf/model/list.rb', line 368 def shift return nil if empty? value = first old_subject, new_subject = subject, rest_subject graph.delete([old_subject, RDF.type, RDF.List]) graph.delete([old_subject, RDF.first, value]) graph.delete([old_subject, RDF.rest, new_subject]) @subject = new_subject return value end |
#sixth ⇒ RDF::Term
Returns the sixth element in this list.
632 633 634 |
# File 'lib/rdf/model/list.rb', line 632 def sixth at(5) end |
#slice(*args) ⇒ RDF::Term Also known as: []
Returns a slice of a list.
507 508 509 510 511 512 513 514 |
# File 'lib/rdf/model/list.rb', line 507 def slice(*args) case argc = args.size when 2 then slice_with_start_and_length(*args) when 1 then (arg = args.first).is_a?(Range) ? slice_with_range(arg) : at(arg) when 0 then raise ArgumentError, "wrong number of arguments (0 for 1)" else raise ArgumentError, "wrong number of arguments (#{argc} for 2)" end end |
#sort(&block) ⇒ RDF::List
Returns the elements in this list in sorted order.
844 845 846 |
# File 'lib/rdf/model/list.rb', line 844 def sort(&block) RDF::List[*super] end |
#sort_by(&block) ⇒ RDF::List
Returns the elements in this list in sorted order.
856 857 858 |
# File 'lib/rdf/model/list.rb', line 856 def sort_by(&block) RDF::List[*super] end |
#tail ⇒ RDF::List
Returns a list containing the last element of this list.
710 711 712 |
# File 'lib/rdf/model/list.rb', line 710 def tail (subject = last_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph) end |
#tenth ⇒ RDF::Term
Returns the tenth element in this list.
676 677 678 |
# File 'lib/rdf/model/list.rb', line 676 def tenth at(9) end |
#third ⇒ RDF::Term
Returns the third element in this list.
599 600 601 |
# File 'lib/rdf/model/list.rb', line 599 def third at(2) end |
#to_a ⇒ Array
Returns the elements in this list as an array.
880 881 882 |
# File 'lib/rdf/model/list.rb', line 880 def to_a each.to_a end |
#to_s ⇒ String
Returns a string representation of this list.
916 917 918 |
# File 'lib/rdf/model/list.rb', line 916 def to_s 'RDF::List[' + join(', ') + ']' end |
#to_set ⇒ Set
Returns the elements in this list as a set.
891 892 893 894 |
# File 'lib/rdf/model/list.rb', line 891 def to_set require 'set' unless defined?(::Set) each.to_set end |
#to_term ⇒ RDF::Resource
Returns the subject of the list.
904 905 906 |
# File 'lib/rdf/model/list.rb', line 904 def to_term subject end |
#uniq ⇒ RDF::List
Returns a new list with the duplicates in this list removed.
868 869 870 |
# File 'lib/rdf/model/list.rb', line 868 def uniq RDF::List[*to_a.uniq] end |
#unshift(value) ⇒ RDF::List
Appends an element to the head of this list. Existing references are not updated, as the list subject changes as a side-effect.
347 348 349 350 351 352 353 354 355 356 357 358 |
# File 'lib/rdf/model/list.rb', line 347 def unshift(value) value = normalize_value(value) new_subject, old_subject = RDF::Node.new, subject graph.insert([new_subject, RDF.first, value.is_a?(RDF::List) ? value.subject : value]) graph.insert([new_subject, RDF.rest, old_subject]) @subject = new_subject return self end |
#valid? ⇒ Boolean
Validate the list ensuring that
-
rdf:rest values are all BNodes are nil
-
each subject has exactly one value for ‘rdf:first` and `rdf:rest`.
-
The value of ‘rdf:rest` must be either a BNode or `rdf:nil`.
-
All other properties are ignored.
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/rdf/model/list.rb', line 109 def valid? li = subject list_nodes = [] while li != RDF.nil do return false if list_nodes.include?(li) list_nodes << li rest = nil firsts = rests = 0 @graph.query(subject: li) do |st| return false unless st.subject.node? case st.predicate when RDF.first firsts += 1 when RDF.rest rest = st.object return false unless rest.node? || rest == RDF.nil rests += 1 end end return false unless firsts == 1 && rests == 1 li = rest end true end |
#|(other) ⇒ RDF::List
Returns the set union of this list and ‘other`.
The resulting list contains the elements from both lists, with no duplicates.
174 175 176 |
# File 'lib/rdf/model/list.rb', line 174 def |(other) RDF::List[*(to_a | other.to_a)] end |