From adfe08560d981d7326a208a86308d783db3119bc Mon Sep 17 00:00:00 2001 From: Gregg Kellogg Date: Thu, 16 Dec 2021 16:20:23 -0800 Subject: [PATCH] Support Common Lisp vectors (`#(foo)`) using the Ruby Vector class. For #16. --- lib/sxp/extensions.rb | 21 +++++++++++++++------ lib/sxp/reader/common_lisp.rb | 5 ++++- spec/common_lisp_spec.rb | 10 +++++++--- spec/extensions_spec.rb | 12 ++++++++++++ 4 files changed, 38 insertions(+), 10 deletions(-) diff --git a/lib/sxp/extensions.rb b/lib/sxp/extensions.rb index 3c96aea..d88e330 100644 --- a/lib/sxp/extensions.rb +++ b/lib/sxp/extensions.rb @@ -1,5 +1,6 @@ # -*- encoding: utf-8 -*- require 'bigdecimal' +require 'matrix' require 'time' ## @@ -146,12 +147,6 @@ class Array ## # Returns the SXP representation of this object. # - # If array is of the form `[:base, uri, ..]`, the base_uri is taken from the second value - # - # If array is of the form `[:prefix, [..], ..]`, prefixes are taken from the second value - # - # Prefixes always are terminated by a ':' - # # @param [Hash{Symbol => RDF::URI}] prefixes(nil) # @param [RDF::URI] base_uri(nil) # @return [String] @@ -160,6 +155,20 @@ def to_sxp(prefixes: nil, base_uri: nil) end end +## +# Extensions for Ruby's `Vector` class. +class Vector + ## + # Returns the SXP representation of this object. + # + # @param [Hash{Symbol => RDF::URI}] prefixes(nil) + # @param [RDF::URI] base_uri(nil) + # @return [String] + def to_sxp(prefixes: nil, base_uri: nil) + '#(' << to_a.map { |x| x.to_sxp(prefixes: prefixes, base_uri: base_uri) }.join(' ') << ')' + end +end + ## # Extensions for Ruby's `Hash` class. class Hash diff --git a/lib/sxp/reader/common_lisp.rb b/lib/sxp/reader/common_lisp.rb index 9b683fb..42e3619 100644 --- a/lib/sxp/reader/common_lisp.rb +++ b/lib/sxp/reader/common_lisp.rb @@ -1,4 +1,6 @@ # -*- encoding: utf-8 -*- +require 'matrix' + module SXP; class Reader ## # A Common Lisp S-expressions parser. @@ -88,7 +90,8 @@ def read_symbol(delimiter = nil) # # @return [Array] def read_vector - raise NotImplementedError, "#{self.class}#read_vector" # TODO + list = read_list(')') + Vector.[](*list) end ## diff --git a/spec/common_lisp_spec.rb b/spec/common_lisp_spec.rb index 3d317ea..b9526c1 100644 --- a/spec/common_lisp_spec.rb +++ b/spec/common_lisp_spec.rb @@ -86,13 +86,17 @@ end end - context "when reading vectors", pending: "Support for vectors" do + context "when reading vectors" do it "reads `#()` as an empty vector" do - expect(read(%q(#()))).to eq [] + expect(read(%q(#()))).to eq Vector[] end it "reads `#(1 2 3)` as a vector" do - expect(read(%q(#(1 2 3)))).to eq [1, 2, 3] + expect(read(%q(#(1 2 3)))).to eq Vector[1, 2, 3] + end + + it "reads `#(hello \"world\")` as a vector" do + expect(read(%q(#(hello "world")))).to eq Vector[:hello, "world"] end end diff --git a/spec/extensions_spec.rb b/spec/extensions_spec.rb index 5e2512a..901b1c8 100644 --- a/spec/extensions_spec.rb +++ b/spec/extensions_spec.rb @@ -26,6 +26,18 @@ end end +describe "Vector" do + { + Vector[] => %q(#()), + Vector[1, 2, 3] => %q(#(1 2 3)), + Vector[:hello, "world"] => %q(#(hello "world")) + }.each do |value, result| + it "returns #{result.inspect} for #{value.inspect}" do + expect(value.to_sxp).to eq result + end + end +end + describe "RDF::Node#to_sxp" do specify { expect(RDF::Node.new("a").to_sxp).to eq %q(_:a)} end