class RDF::List

An RDF list.

@example Constructing a new list

RDF::List[1, 2, 3]

@since 0.2.3

Constants

NIL

The canonical empty list.

UNSET

Attributes

graph[R]

@!attribute [r] graph @return [RDF::Graph] the underlying graph storing the statements that constitute this list

subject[R]

@!attribute [r] subject @return [RDF::Resource] the subject term of this list.

Public Class Methods

[](*values) click to toggle source

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.

@example

RDF::List[]
RDF::List[*(1..10)]
RDF::List[1, 2, 3]
RDF::List["foo", "bar"]
RDF::List["a", 1, "b", 2, "c", 3]

@param [Array<RDF::Term>] values @return [RDF::List]

# File lib/rdf/model/list.rb, line 30
def self.[](*values)
  self.new(subject: nil, graph: nil, values: values)
end
new(subject: nil, graph: nil, values: nil, wrap_transaction: false, &block) click to toggle source

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.

@example add constructed list to existing graph

l = RDF::List(values: (1, 2, 3))
g = RDF::Graph.new << l
g.count # => l.count

@example use a transaction for block initialization

l = RDF::List(graph: graph, wrap_transaction: true) do |list|
  list << RDF::Literal(1)
  # list.graph.rollback will rollback all list changes within this block.
end
list.count #=> 1

@param [RDF::Resource] subject (RDF.nil)

Subject should be an {RDF::Node}, not a {RDF::URI}. A list with an IRI head will not validate, but is commonly used to detect if a list is valid.

@param [RDF::Graph] graph (RDF::Graph.new) @param [Array<RDF::Term>] values

Any values which are not terms are coerced to `RDF::Literal`.

@param [Boolean] wrap_transaction (false)

Wraps the callback in a transaction, and replaces the graph with that transaction for the duraction of the callback. This has the effect of allowing any list changes to be made atomically, or rolled back.

@yield [list] @yieldparam [RDF::List] list

# File lib/rdf/model/list.rb, line 68
def initialize(subject: nil, graph: nil, values: nil, wrap_transaction: false, &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?
    if wrap_transaction
      old_graph = @graph
      begin
        Transaction.begin(@graph, graph_name: @graph.graph_name, mutable: @graph.mutable?) do |trans|
          @graph = trans
          case block.arity
            when 1 then block.call(self)
            else instance_eval(&block)
          end
          trans.execute if trans.mutated?
        end
      ensure
        @graph = old_graph
      end
    else
      case block.arity
        when 1 then block.call(self)
        else instance_eval(&block)
      end
    end
  end
end

Public Instance Methods

&(other) click to toggle source

Returns the set intersection of this list and ‘other`.

The resulting list contains the elements common to both lists, with no duplicates.

@example

RDF::List[1, 2] & RDF::List[1, 2]       #=> RDF::List[1, 2]
RDF::List[1, 2] & RDF::List[2, 3]       #=> RDF::List[2]
RDF::List[1, 2] & RDF::List[3, 4]       #=> RDF::List[]

@param [RDF::List] other @return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-26

# File lib/rdf/model/list.rb, line 202
def &(other)
  self.class.new(values: (to_a & other.to_a))
end
*(int_or_str) click to toggle source

Returns either a repeated list or a string concatenation of the elements in this list.

@overload *(times)

Returns a new list built of `times` repetitions of this list.

@example
  RDF::List[1, 2, 3] * 2                #=> RDF::List[1, 2, 3, 1, 2, 3]

@param  [Integer] times
@return [RDF::List]

@overload *(sep)

Returns the string concatenation of the elements in this list
separated by `sep`. Equivalent to `self.join(sep)`.

@example
  RDF::List[1, 2, 3] * ","              #=> "1,2,3"

@param  [String, #to_s] sep
@return [RDF::List]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-2A

# File lib/rdf/model/list.rb, line 276
def *(int_or_str)
  case int_or_str
    when Integer then self.class.new(values: (to_a * int_or_str))
    else join(int_or_str.to_s)
  end
end
+(other) click to toggle source

Returns the concatenation of this list and ‘other`.

@example

RDF::List[1, 2] + RDF::List[3, 4]       #=> RDF::List[1, 2, 3, 4]

@param [RDF::List] other @return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-2B

# File lib/rdf/model/list.rb, line 233
def +(other)
  self.class.new(values: (to_a + other.to_a))
end
-(other) click to toggle source

Returns the difference between this list and ‘other`, removing any elements that appear in both lists.

@example

RDF::List[1, 2, 2, 3] - RDF::List[2]    #=> RDF::List[1, 3]

@param [RDF::List] other @return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-2D

# File lib/rdf/model/list.rb, line 247
def -(other)
  self.class.new(values: (to_a - other.to_a))
end
<<(value) click to toggle source

Appends an element to the tail of this list.

@example

RDF::List[] << 1 << 2 << 3              #=> RDF::List[1, 2, 3]

@param [RDF::Term] value @return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-3C-3C

# File lib/rdf/model/list.rb, line 438
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) click to toggle source

Compares this list to ‘other` for sorting purposes.

@example

RDF::List[1] <=> RDF::List[1]           #=> 0
RDF::List[1] <=> RDF::List[2]           #=> -1
RDF::List[2] <=> RDF::List[1]           #=> 1

@param [RDF::List] other @return [Integer] @see ruby-doc.org/core-2.2.2/Array.html#method-i-3C-3D-3E

# File lib/rdf/model/list.rb, line 480
def <=>(other)
  to_a <=> Array(other)
end
==(other) click to toggle source

@see RDF::Value#==

Calls superclass method
# File lib/rdf/model/list.rb, line 183
def ==(other)
  return false if other.is_a?(RDF::Value) && !other.list?
  super
end
[](*args)
Alias for: slice
[]=(*args) click to toggle source

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).

@example

a = RDF::List.new
a[4] = "4";                 #=> [rdf:nil, rdf:nil, rdf:nil, rdf:nil, "4"]
a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", rdf:nil, "4"]
a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, rdf:nil, "4"]
a[0, 2] = "?"               #=> ["?", 2, rdf:nil, "4"]
a[0..2] = "A"               #=> ["A", "4"]
a[-1]   = "Z"               #=> ["A", "Z"]
a[1..-1] = nil              #=> ["A", rdf:nil]
a[1..-1] = []               #=> ["A"]
a[0, 0] = [ 1, 2 ]          #=> [1, 2, "A"]
a[3, 0] = "B"               #=> [1, 2, "A", "B"]

@overload []=(index, term)

Replaces the element at `index` with `term`.
@param [Integer] index
@param [RDF::Term] term
  A non-RDF::Term is coerced to a Literal.
@return [RDF::Term]
@raise [IndexError]

@overload []=(start, length, value)

Replaces a subarray from the `start` index for `length` elements with `value`. Value is a {RDF::Term}, Array of {RDF::Term}, or {RDF::List}.
@param [Integer] start
@param [Integer] length
@param [RDF::Term, Array<RDF::Term>, RDF::List] value
  A non-RDF::Term is coerced to a Literal.
@return [RDF::Term, RDF::List]
@raise [IndexError]

@overload []=(range, value)

Replaces a subarray from the `start` index for `length` elements with `value`. Value is a {RDF::Term}, Array of {RDF::Term}, or {RDF::List}.
@param [Range] range
@param [RDF::Term, Array<RDF::Term>, RDF::List] value
  A non-RDF::Term is coerced to a Literal.
@return [RDF::Term, RDF::List]
@raise [IndexError]

@since 1.1.15

# File lib/rdf/model/list.rb, line 332
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) click to toggle source

Returns the element at ‘index`.

@example

RDF::List[1, 2, 3].at(0)                #=> 1
RDF::List[1, 2, 3].at(4)                #=> nil

@return [RDF::Term, nil] @see ruby-doc.org/core-2.2.2/Array.html#method-i-at

# File lib/rdf/model/list.rb, line 596
def at(index)
  each.with_index { |v, i| return v if i == index }
  return nil
end
Also aliased as: nth
clear() click to toggle source

Empties this list

@example

RDF::List[1, 2, 2, 3].clear    #=> RDF::List[]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-clear

# File lib/rdf/model/list.rb, line 422
def clear
  until empty?
    shift
  end
  return self
end
each() { |value| ... } click to toggle source

Yields each element in this list.

@example

RDF::List[1, 2, 3].each do |value|
  puts value.inspect
end

@return [Enumerator] @see ruby-doc.org/core-1.9/classes/Enumerable.html

# File lib/rdf/model/list.rb, line 813
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) click to toggle source

Yields each statement constituting this list.

@example

RDF::List[1, 2, 3].each_statement do |statement|
  puts statement.inspect
end

@return [Enumerator] @see RDF::Enumerable#each_statement

# File lib/rdf/model/list.rb, line 833
def each_statement(&block)
  return enum_statement unless block_given?

  each_subject do |subject|
    graph.query({subject: subject}, &block)
  end
end
Also aliased as: to_rdf
each_subject() { |subject| ... } click to toggle source

Yields each subject term constituting this list.

@example

RDF::List[1, 2, 3].each_subject do |subject|
  puts subject.inspect
end

@return [Enumerator] @see RDF::Enumerable#each

# File lib/rdf/model/list.rb, line 790
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() click to toggle source

Returns the eighth element in this list.

@example

RDF::List[*(1..10)].eighth              #=> RDF::Literal(8)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 687
def eighth
  at(7)
end
empty?() click to toggle source

Returns ‘true` if this list is empty.

@example

RDF::List[].empty?                      #=> true
RDF::List[1, 2, 3].empty?               #=> false

@return [Boolean] @see ruby-doc.org/core-2.2.2/Array.html#method-i-empty-3F

# File lib/rdf/model/list.rb, line 493
def empty?
  graph.query({subject: subject, predicate: RDF.first}).empty?
end
eql?(other) click to toggle source

Compares this list to ‘other` using eql? on each component.

@example

RDF::List[1, 2, 3].eql? RDF::List[1, 2, 3]  #=> true
RDF::List[1, 2, 3].eql? [1, 2, 3]           #=> true

@param [RDF::List] other @return [Integer] @see ruby-doc.org/core-2.2.2/Array.html#method-i-3C-3D-3E

# File lib/rdf/model/list.rb, line 465
def eql?(other)
  to_a.eql? Array(other)
end
fetch(index, default = UNSET) { |index| ... } click to toggle source

Returns element at ‘index` with default.

@example

RDF::List[1, 2, 3].fetch(0)             #=> RDF::Literal(1)
RDF::List[1, 2, 3].fetch(4)             #=> IndexError
RDF::List[1, 2, 3].fetch(4, nil)        #=> nil
RDF::List[1, 2, 3].fetch(4) { |n| n*n } #=> 16

@return [RDF::Term, nil] @see ruby-doc.org/core-1.9/classes/Array.html#M000420

# File lib/rdf/model/list.rb, line 576
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() click to toggle source

Returns the fifth element in this list.

@example

RDF::List[*(1..10)].fifth               #=> RDF::Literal(5)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 654
def fifth
  at(4)
end
first() click to toggle source

Returns the first element in this list.

@example

RDF::List[*(1..10)].first               #=> RDF::Literal(1)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 610
def first
  graph.first_object(subject: first_subject, predicate: RDF.first)
end
first_subject() click to toggle source

Returns the first subject term constituting this list.

This is equivalent to ‘subject`.

@example

RDF::List[1, 2, 3].first_subject        #=> RDF::Node(...)

@return [RDF::Resource]

# File lib/rdf/model/list.rb, line 756
def first_subject
  subject
end
fourth() click to toggle source

Returns the fourth element in this list.

@example

RDF::List[*(1..10)].fourth              #=> RDF::Literal(4)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 643
def fourth
  at(3)
end
index(value) click to toggle source

Returns the index of the first element equal to ‘value`, or `nil` if no match was found.

@example

RDF::List['a', 'b', 'c'].index('a')     #=> 0
RDF::List['a', 'b', 'c'].index('d')     #=> nil

@param [RDF::Term] value @return [Integer] @see ruby-doc.org/core-2.2.2/Array.html#method-i-index

# File lib/rdf/model/list.rb, line 523
def index(value)
  each.with_index do |v, i|
    return i if v == value
  end
  return nil
end
inspect() click to toggle source

Returns a developer-friendly representation of this list.

@example

RDF::List[].inspect                     #=> "#<RDF::List(_:g2163790380)>"

@return [String]

# File lib/rdf/model/list.rb, line 960
def inspect
  if self.equal?(NIL)
    'RDF::List::NIL'
  else
    sprintf("#<%s:%#0x(%s)>", self.class.name, __id__, join(', '))
  end
end
join(sep = $,) click to toggle source

Returns a string created by converting each element of this list into a string, separated by ‘sep`.

@example

RDF::List[1, 2, 3].join                 #=> "123"
RDF::List[1, 2, 3].join(", ")           #=> "1, 2, 3"

@param [String] sep @return [String] @see ruby-doc.org/core-2.2.2/Array.html#method-i-join

# File lib/rdf/model/list.rb, line 853
def join(sep = $,)
  map(&:to_s).join(sep)
end
last() click to toggle source

Returns the last element in this list.

@example

RDF::List[*(1..10)].last                 #=> RDF::Literal(10)

@return [RDF::Term] @see ruby-doc.org/core-2.2.2/Array.html#method-i-last

# File lib/rdf/model/list.rb, line 721
def last
  graph.first_object(subject: last_subject, predicate: RDF.first)
end
last_subject() click to toggle source

Returns the last subject term constituting this list.

@example

RDF::List[1, 2, 3].last_subject         #=> RDF::Node(...)

@return [RDF::Resource]

# File lib/rdf/model/list.rb, line 776
def last_subject
  each_subject.to_a.last # TODO: optimize this
end
length() click to toggle source

Returns the length of this list.

@example

RDF::List[].length                      #=> 0
RDF::List[1, 2, 3].length               #=> 3

@return [Integer] @see ruby-doc.org/core-2.2.2/Array.html#method-i-length

# File lib/rdf/model/list.rb, line 506
def length
  each.count
end
Also aliased as: size
list?() click to toggle source

Is this a {RDF::List}?

@return [Boolean]

# File lib/rdf/model/list.rb, line 122
def list?
  true
end
ninth() click to toggle source

Returns the ninth element in this list.

@example

RDF::List[*(1..10)].ninth               #=> RDF::Literal(9)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 698
def ninth
  at(8)
end
nth(index)
Alias for: at
rest() click to toggle source

Returns a list containing all but the first element of this list.

@example

RDF::List[1, 2, 3].rest                 #=> RDF::List[2, 3]

@return [RDF::List]

# File lib/rdf/model/list.rb, line 732
def rest
  (subject = rest_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph)
end
rest_subject() click to toggle source

@example

RDF::List[1, 2, 3].rest_subject         #=> RDF::Node(...)

@return [RDF::Resource]

# File lib/rdf/model/list.rb, line 765
def rest_subject
  graph.first_object(subject: subject, predicate: RDF.rest)
end
reverse() click to toggle source

Returns the elements in this list in reversed order.

@example

RDF::List[1, 2, 3].reverse              #=> RDF::List[3, 2, 1]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-reverse

# File lib/rdf/model/list.rb, line 865
def reverse
  self.class.new(values: to_a.reverse)
end
second() click to toggle source

Returns the second element in this list.

@example

RDF::List[*(1..10)].second              #=> RDF::Literal(2)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 621
def second
  at(1)
end
seventh() click to toggle source

Returns the seventh element in this list.

@example

RDF::List[*(1..10)].seventh             #=> RDF::Literal(7)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 676
def seventh
  at(6)
end
shift() click to toggle source

Removes and returns the element at the head of this list.

@example

RDF::List[1,2,3].shift              #=> 1

@return [RDF::Term] @see ruby-doc.org/core-2.2.2/Array.html#method-i-shift

# File lib/rdf/model/list.rb, line 401
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() click to toggle source

Returns the sixth element in this list.

@example

RDF::List[*(1..10)].sixth               #=> RDF::Literal(6)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 665
def sixth
  at(5)
end
size()
Alias for: length
slice(*args) click to toggle source

Returns a slice of a list.

@example

RDF::List[1, 2, 3].slice(0)    #=> RDF::Literal(1),
RDF::List[1, 2, 3].slice(0, 2) #=> RDF::List[1, 2],
RDF::List[1, 2, 3].slice(0..2) #=> RDF::List[1, 2, 3]

@return [RDF::Term] @see ruby-doc.org/core-2.2.2/Array.html#method-i-slice

# File lib/rdf/model/list.rb, line 540
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
Also aliased as: []
sort(&block) click to toggle source

Returns the elements in this list in sorted order.

@example

RDF::List[2, 3, 1].sort                 #=> RDF::List[1, 2, 3]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-sort

Calls superclass method
# File lib/rdf/model/list.rb, line 877
def sort(&block)
  self.class.new(values: super)
end
sort_by(&block) click to toggle source

Returns the elements in this list in sorted order.

@example

RDF::List[2, 3, 1].sort_by(&:to_i)      #=> RDF::List[1, 2, 3]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-sort_by

Calls superclass method
# File lib/rdf/model/list.rb, line 889
def sort_by(&block)
  self.class.new(values: super)
end
tail() click to toggle source

Returns a list containing the last element of this list.

@example

RDF::List[1, 2, 3].tail                 #=> RDF::List[3]

@return [RDF::List]

# File lib/rdf/model/list.rb, line 743
def tail
  (subject = last_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph)
end
tenth() click to toggle source

Returns the tenth element in this list.

@example

RDF::List[*(1..10)].tenth               #=> RDF::Literal(10)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 709
def tenth
  at(9)
end
third() click to toggle source

Returns the third element in this list.

@example

RDF::List[*(1..10)].third               #=> RDF::Literal(4)

@return [RDF::Term]

# File lib/rdf/model/list.rb, line 632
def third
  at(2)
end
to_a() click to toggle source

Returns the elements in this list as an array.

@example

RDF::List[].to_a                        #=> []
RDF::List[1, 2, 3].to_a                 #=> [RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]

@return [Array]

# File lib/rdf/model/list.rb, line 913
def to_a
  each.to_a
end
to_rdf(&block)
Alias for: each_statement
to_s() click to toggle source

Returns a string representation of this list.

@example

RDF::List[].to_s                        #=> "RDF::List[]"
RDF::List[1, 2, 3].to_s                 #=> "RDF::List[1, 2, 3]"

@return [String]

# File lib/rdf/model/list.rb, line 949
def to_s
  'RDF::List[' + join(', ') + ']'
end
to_set() click to toggle source

Returns the elements in this list as a set.

@example

RDF::List[1, 2, 3].to_set               #=> Set[RDF::Literal(1), RDF::Literal(2), RDF::Literal(3)]

@return [Set]

# File lib/rdf/model/list.rb, line 924
def to_set
  require 'set' unless defined?(::Set)
  each.to_set
end
to_term() click to toggle source

Returns the subject of the list.

@example

RDF::List[].to_term                     #=> "RDF[:nil]"
RDF::List[1, 2, 3].to_term              #=> "RDF::Node"

@return [RDF::Resource]

# File lib/rdf/model/list.rb, line 937
def to_term
  subject
end
uniq() click to toggle source

Returns a new list with the duplicates in this list removed.

@example

RDF::List[1, 2, 2, 3].uniq              #=> RDF::List[1, 2, 3]

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-uniq

# File lib/rdf/model/list.rb, line 901
def uniq
  self.class.new(values: to_a.uniq)
end
unshift(value) click to toggle source

Appends an element to the head of this list. Existing references are not updated, as the list subject changes as a side-effect.

@example

RDF::List[].unshift(1).unshift(2).unshift(3) #=> RDF::List[3, 2, 1]

@param [RDF::Term, Array<RDF::Term>, RDF::List] value

A non-RDF::Term is coerced to a Literal

@return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-unshift

# File lib/rdf/model/list.rb, line 380
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?() click to toggle source

Validate the list ensuring that

  • each node is referenced exactly once (except for the head, which may have no reference)

  • 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`.

  • only the list head may have any other properties

@return [Boolean]

# File lib/rdf/model/list.rb, line 135
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
      when RDF.type
      else
        # It may have no other properties
        return false unless li == subject
      end
    end
    return false unless firsts == 1 && rests == 1
    li = rest
  end

  # All elements other than the head must be referenced exactly once
  return list_nodes.all? do |li|
    refs = @graph.query({object: li}).count
    case refs
    when 0 then li == subject
    when 1 then true
    else        false
    end
  end
end
|(other) click to toggle source

Returns the set union of this list and ‘other`.

The resulting list contains the elements from both lists, with no duplicates.

@example

RDF::List[1, 2] | RDF::List[1, 2]       #=> RDF::List[1, 2]
RDF::List[1, 2] | RDF::List[2, 3]       #=> RDF::List[1, 2, 3]
RDF::List[1, 2] | RDF::List[3, 4]       #=> RDF::List[1, 2, 3, 4]

@param [RDF::List] other @return [RDF::List] @see ruby-doc.org/core-2.2.2/Array.html#method-i-7C

# File lib/rdf/model/list.rb, line 220
def |(other)
  self.class.new(values: (to_a | other.to_a))
end

Protected Instance Methods

slice_with_range(range) click to toggle source

@private

# File lib/rdf/model/list.rb, line 558
def slice_with_range(range)
  self.class.new(values: to_a.slice(range))
end
slice_with_start_and_length(start, length) click to toggle source

@private

# File lib/rdf/model/list.rb, line 552
def slice_with_start_and_length(start, length)
  self.class.new(values: to_a.slice(start, length))
end

Private Instance Methods

normalize_value(value) click to toggle source

Normalizes ‘Array` to `RDF::List` and `nil` to `RDF.nil`.

@param value [Object] @return [RDF::Value, Object] normalized value

# File lib/rdf/model/list.rb, line 975
def normalize_value(value)
  case value
    when nil         then RDF.nil
    when RDF::Value  then value
    when Array       then self.class.new(subject: nil, graph: graph, values: value)
    else value
  end
end