Class: RDF::List

Inherits:
Object
  • Object
show all
Includes:
Comparable, Enumerable, Value
Defined in:
lib/rdf/model/list.rb

Overview

An RDF list.

Examples:

Constructing a new list

RDF::List[1, 2, 3]

Since:

  • 0.2.3

Constant Summary collapse

NIL =

The canonical empty list.

Since:

  • 0.2.3

RDF::List.new(subject: RDF.nil).freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Value

#anonymous?, #canonicalize, #canonicalize!, #constant?, #graph?, #inspect!, #invalid?, #iri?, #literal?, #node?, #resource?, #start_with?, #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_graph, #enum_object, #enum_predicate, #enum_quad, #enum_statement, #enum_subject, #enum_term, #enum_triple, #graph?, #graph_names, #invalid?, #method_missing, #object?, #objects, #predicate?, #predicates, #project_graph, #quad?, #quads, #respond_to_missing?, #statement?, #statements, #subject?, #subjects, #supports?, #term?, #terms, #to_h, #triple?, #triples, #validate!

Methods included from Util::Aliasing::LateBound

#alias_method

Methods included from Countable

#count

Constructor Details

#initialize(subject: nil, graph: nil, values: nil, wrap_transaction: false) {|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.

Examples:

add constructed list to existing graph

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

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

Parameters:

  • subject (RDF::Resource) (defaults to: nil)

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

  • graph (RDF::Graph) (defaults to: nil)

    (RDF::Graph.new)

  • values (Array<RDF::Term>) (defaults to: nil)

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

  • wrap_transaction (Boolean) (defaults to: false)

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

Yields:

  • (list)

Yield Parameters:

Since:

  • 0.2.3


68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# 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

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class RDF::Enumerable

Instance Attribute Details

#graphRDF::Graph (readonly)

Returns the underlying graph storing the statements that constitute this list.

Returns:

  • (RDF::Graph)

    the underlying graph storing the statements that constitute this list

Since:

  • 0.2.3


179
180
181
# File 'lib/rdf/model/list.rb', line 179

def graph
  @graph
end

#subjectRDF::Resource (readonly)

Returns the subject term of this list.

Returns:

Since:

  • 0.2.3


175
176
177
# File 'lib/rdf/model/list.rb', line 175

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.

Examples:

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

Parameters:

Returns:

Since:

  • 0.2.3


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.

Examples:

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[]

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


202
203
204
# File 'lib/rdf/model/list.rb', line 202

def &(other)
  self.class.new(values: (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.

Overloads:

  • #*(times) ⇒ RDF::List

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

    Examples:

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

    Parameters:

    • times (Integer)

    Returns:

  • #*(sep) ⇒ RDF::List

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

    Examples:

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

    Parameters:

    Returns:

Returns:

See Also:

Since:

  • 0.2.3


276
277
278
279
280
281
# 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) ⇒ RDF::List

Returns the concatenation of this list and other.

Examples:

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

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


233
234
235
# File 'lib/rdf/model/list.rb', line 233

def +(other)
  self.class.new(values: (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.

Examples:

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

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


247
248
249
# File 'lib/rdf/model/list.rb', line 247

def -(other)
  self.class.new(values: (to_a - other.to_a))
end

#<<(value) ⇒ RDF::List

Appends an element to the tail of this list.

Examples:

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

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
# File 'lib/rdf/model/list.rb', line 451

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.

Examples:

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

Parameters:

Returns:

  • (Integer)

See Also:

Since:

  • 0.2.3


493
494
495
# File 'lib/rdf/model/list.rb', line 493

def <=>(other)
  to_a <=> Array(other)
end

#==(other) ⇒ Object

See Also:

  • Value#==

Since:

  • 0.2.3


183
184
185
186
# File 'lib/rdf/model/list.rb', line 183

def ==(other)
  return false if other.is_a?(RDF::Value) && !other.list?
  super
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).

Examples:

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"]

Overloads:

Since:

  • 1.1.15


345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
# File 'lib/rdf/model/list.rb', line 345

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.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


609
610
611
612
# File 'lib/rdf/model/list.rb', line 609

def at(index)
  each.with_index { |v, i| return v if i == index }
  return nil
end

#clearRDF::List

Empties this list

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


435
436
437
438
439
440
# File 'lib/rdf/model/list.rb', line 435

def clear
  until empty?
    shift
  end
  return self
end

#eachEnumerator

Yields each element in this list.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


826
827
828
829
830
831
832
833
834
# File 'lib/rdf/model/list.rb', line 826

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.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


846
847
848
849
850
851
852
# File 'lib/rdf/model/list.rb', line 846

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.

Examples:

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

Yields:

Returns:

See Also:

  • Enumerable#each

Since:

  • 0.2.3


803
804
805
806
807
808
809
810
811
812
813
814
# File 'lib/rdf/model/list.rb', line 803

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

#eighthRDF::Term

Returns the eighth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


700
701
702
# File 'lib/rdf/model/list.rb', line 700

def eighth
  at(7)
end

#empty?Boolean

Returns true if this list is empty.

Examples:

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

Returns:

  • (Boolean)

See Also:

Since:

  • 0.2.3


506
507
508
# File 'lib/rdf/model/list.rb', line 506

def empty?
  graph.query({subject: subject, predicate: RDF.first}).empty?
end

#eql?(other) ⇒ Integer

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

Examples:

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

Parameters:

Returns:

  • (Integer)

See Also:

Since:

  • 0.2.3


478
479
480
# File 'lib/rdf/model/list.rb', line 478

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.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


589
590
591
592
593
594
595
596
597
598
# File 'lib/rdf/model/list.rb', line 589

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

#fifthRDF::Term

Returns the fifth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


667
668
669
# File 'lib/rdf/model/list.rb', line 667

def fifth
  at(4)
end

#firstRDF::Term

Returns the first element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


623
624
625
# File 'lib/rdf/model/list.rb', line 623

def first
  graph.first_object(subject: first_subject, predicate: RDF.first)
end

#first_subjectRDF::Resource

Returns the first subject term constituting this list.

This is equivalent to subject.

Examples:

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

Returns:

Since:

  • 0.2.3


769
770
771
# File 'lib/rdf/model/list.rb', line 769

def first_subject
  subject
end

#fourthRDF::Term

Returns the fourth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


656
657
658
# File 'lib/rdf/model/list.rb', line 656

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.

Examples:

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

Parameters:

Returns:

  • (Integer)

See Also:

Since:

  • 0.2.3


536
537
538
539
540
541
# File 'lib/rdf/model/list.rb', line 536

def index(value)
  each.with_index do |v, i|
    return i if v == value
  end
  return nil
end

#inspectString

Returns a developer-friendly representation of this list.

Examples:

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

Returns:

Since:

  • 0.2.3


973
974
975
976
977
978
979
# File 'lib/rdf/model/list.rb', line 973

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.

Examples:

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

Parameters:

  • sep (String) (defaults to: $,)

Returns:

See Also:

Since:

  • 0.2.3


866
867
868
# File 'lib/rdf/model/list.rb', line 866

def join(sep = $,)
  map(&:to_s).join(sep)
end

#lastRDF::Term

Returns the last element in this list.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


734
735
736
# File 'lib/rdf/model/list.rb', line 734

def last
  graph.first_object(subject: last_subject, predicate: RDF.first)
end

#last_subjectRDF::Resource

Returns the last subject term constituting this list.

Examples:

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

Returns:

Since:

  • 0.2.3


789
790
791
# File 'lib/rdf/model/list.rb', line 789

def last_subject
  each_subject.to_a.last # TODO: optimize this
end

#lengthInteger Also known as: size

Returns the length of this list.

Examples:

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

Returns:

  • (Integer)

See Also:

Since:

  • 0.2.3


519
520
521
# File 'lib/rdf/model/list.rb', line 519

def length
  each.count
end

#list?Boolean

Is this a RDF::List?

Returns:

  • (Boolean)

Since:

  • 0.2.3


122
123
124
# File 'lib/rdf/model/list.rb', line 122

def list?
  true
end

#ninthRDF::Term

Returns the ninth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


711
712
713
# File 'lib/rdf/model/list.rb', line 711

def ninth
  at(8)
end

#restRDF::List

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

Examples:

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

Returns:

Since:

  • 0.2.3


745
746
747
# File 'lib/rdf/model/list.rb', line 745

def rest
  (subject = rest_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph)
end

#rest_subjectRDF::Resource

Examples:

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

Returns:

Since:

  • 0.2.3


778
779
780
# File 'lib/rdf/model/list.rb', line 778

def rest_subject
  graph.first_object(subject: subject, predicate: RDF.rest)
end

#reverseRDF::List

Returns the elements in this list in reversed order.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


878
879
880
# File 'lib/rdf/model/list.rb', line 878

def reverse
  self.class.new(values: to_a.reverse)
end

#secondRDF::Term

Returns the second element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


634
635
636
# File 'lib/rdf/model/list.rb', line 634

def second
  at(1)
end

#seventhRDF::Term

Returns the seventh element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


689
690
691
# File 'lib/rdf/model/list.rb', line 689

def seventh
  at(6)
end

#shiftRDF::Term

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

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


414
415
416
417
418
419
420
421
422
423
424
425
# File 'lib/rdf/model/list.rb', line 414

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

#sixthRDF::Term

Returns the sixth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


678
679
680
# File 'lib/rdf/model/list.rb', line 678

def sixth
  at(5)
end

#slice(*args) ⇒ RDF::Term Also known as: []

Returns a slice of a list.

Examples:

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]

Returns:

See Also:

Since:

  • 0.2.3


553
554
555
556
557
558
559
560
# File 'lib/rdf/model/list.rb', line 553

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.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


890
891
892
# File 'lib/rdf/model/list.rb', line 890

def sort(&block)
  self.class.new(values: super)
end

#sort_by(&block) ⇒ RDF::List

Returns the elements in this list in sorted order.

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


902
903
904
# File 'lib/rdf/model/list.rb', line 902

def sort_by(&block)
  self.class.new(values: super)
end

#tailRDF::List

Returns a list containing the last element of this list.

Examples:

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

Returns:

Since:

  • 0.2.3


756
757
758
# File 'lib/rdf/model/list.rb', line 756

def tail
  (subject = last_subject).eql?(RDF.nil) ? nil : self.class.new(subject: subject, graph: graph)
end

#tenthRDF::Term

Returns the tenth element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


722
723
724
# File 'lib/rdf/model/list.rb', line 722

def tenth
  at(9)
end

#thirdRDF::Term

Returns the third element in this list.

Examples:

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

Returns:

Since:

  • 0.2.3


645
646
647
# File 'lib/rdf/model/list.rb', line 645

def third
  at(2)
end

#to_aArray

Returns the elements in this list as an array.

Examples:

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

Returns:

  • (Array)

Since:

  • 0.2.3


926
927
928
# File 'lib/rdf/model/list.rb', line 926

def to_a
  each.to_a
end

#to_sString

Returns a string representation of this list.

Examples:

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

Returns:

Since:

  • 0.2.3


962
963
964
# File 'lib/rdf/model/list.rb', line 962

def to_s
  'RDF::List[' + join(', ') + ']'
end

#to_setSet

Returns the elements in this list as a set.

Examples:

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

Returns:

  • (Set)

Since:

  • 0.2.3


937
938
939
940
# File 'lib/rdf/model/list.rb', line 937

def to_set
  require 'set' unless defined?(::Set)
  each.to_set
end

#to_termRDF::Resource

Returns the subject of the list.

Examples:

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

Returns:

Since:

  • 0.2.3


950
951
952
# File 'lib/rdf/model/list.rb', line 950

def to_term
  subject
end

#uniqRDF::List

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

Examples:

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

Returns:

See Also:

Since:

  • 0.2.3


914
915
916
# File 'lib/rdf/model/list.rb', line 914

def uniq
  self.class.new(values: 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.

Examples:

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

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


393
394
395
396
397
398
399
400
401
402
403
404
# File 'lib/rdf/model/list.rb', line 393

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

  • 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

Returns:

  • (Boolean)

Since:

  • 0.2.3


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# 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) ⇒ RDF::List

Returns the set union of this list and other.

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

Examples:

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]

Parameters:

Returns:

See Also:

Since:

  • 0.2.3


220
221
222
# File 'lib/rdf/model/list.rb', line 220

def |(other)
  self.class.new(values: (to_a | other.to_a))
end