algebrick 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c10eb07ed10cdcc7fd01fda3b2dccf42786db60f
4
- data.tar.gz: 72b0ecfd3d3ce1bc20c5683adeabb3d2b5915bfe
3
+ metadata.gz: 2f929febec0436c6ff1ddacdefe7936cd29be50d
4
+ data.tar.gz: 929a7fad56a10ef56de4dd09c9309d138fc92b85
5
5
  SHA512:
6
- metadata.gz: 3d1dfceee22b44ed971953d37d3cb9e8e5caf03a2cdbda3be251c9e778f1a5e3ae7be41f2dfc17f3ea1ba7dc63f5a908ff481571957fe18b6267d4670f8d8be7
7
- data.tar.gz: a0ed769069be44d01001a2657a07db0aa3ad3d184afb290d38bc2a82c0c72237737867f972380cc496689f4ee9169f1b3b6081eea7a6a792976c1a10b1621f7c
6
+ metadata.gz: f2c50e7f1fc3777edb0743ba8da7ed2096424576701f16236f41e9aef8efd60a234f2a587d2b97dbd1fffc0953d8242cb0880688c0b2922af4a25c3da1a8d537
7
+ data.tar.gz: eb8666dbb9f3908dec24a4e300a9cfe6a00bb7d7ef2d4ae1c3bf1f4a6f992f760a4904748f5ab44a6da866c94754aad810cec7987cd67505f2ff39374424f439
data/README.md CHANGED
@@ -6,7 +6,7 @@ It's a gem providing **algebraic types** and **pattern matching** seamlessly int
6
6
 
7
7
  - Documentation: <http://blog.pitr.ch/algebrick>
8
8
  - Source: <https://github.com/pitr-ch/algebrick>
9
- - Blog: <http://blog.pitr.ch/blog/categories/algebrick/>
9
+ - Blog: <http://blog.pitr.ch/tag/algebrick.html>
10
10
 
11
11
  ## What is it good for?
12
12
 
data/README_FULL.md CHANGED
@@ -80,6 +80,11 @@ They use standard `#===` method to match against values.
80
80
 
81
81
  ## What is it good for?
82
82
 
83
+ ### TODO
84
+
85
+ - record like structures
86
+ - creating new types by summing existing
87
+
83
88
  ### Defining data structures
84
89
 
85
90
  <!-- {include:file:doc/data.out.rb} -->
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.7.0
data/doc/format.rb CHANGED
@@ -3,9 +3,8 @@ require 'bundler/setup'
3
3
  require 'pry'
4
4
  require 'pp'
5
5
 
6
- root = File.dirname(File.expand_path(Process.argv0))
7
6
  input_paths = if ARGV.empty?
8
- Dir.glob("#{root}/*.in.rb")
7
+ Dir.glob("#{File.dirname(__FILE__)}/*.in.rb")
9
8
  else
10
9
  ARGV
11
10
  end.map { |p| File.expand_path p }
@@ -13,7 +12,7 @@ input_paths = if ARGV.empty?
13
12
  input_paths.each_with_index do |input_path, i|
14
13
 
15
14
  pid = fork do
16
- require File.join(root, 'init.rb')
15
+ require_relative 'init.rb'
17
16
 
18
17
  begin
19
18
  output_path = input_path.gsub /\.in\.rb$/, '.out.rb'
data/doc/json.out.rb CHANGED
@@ -20,7 +20,7 @@ require 'algebrick/serializer' # => true
20
20
  require 'multi_json' # => true
21
21
 
22
22
  # Prepare a message for sending.
23
- serializer = Algebrick::Serializer.new # => #<Algebrick::Serializer:0x007fafcc96f6a8>
23
+ serializer = Algebrick::Serializer.new # => #<Algebrick::Serializer:0x007fab42bdf6d8>
24
24
  request = CreateUser[User['root', 'lajDh4']]
25
25
  # => CreateUser[User[login: root, password: lajDh4]]
26
26
  raw_request = MultiJson.dump serializer.dump(request)
data/lib/algebrick.rb CHANGED
@@ -39,9 +39,6 @@
39
39
 
40
40
  # TODO maybe should behave as monad
41
41
 
42
- # TODO anonymous types ? missing tests
43
-
44
-
45
42
  # Provides Algebraic types and pattern matching
46
43
  #
47
44
  # **Quick example**
@@ -39,7 +39,7 @@ module Algebrick
39
39
  end
40
40
 
41
41
  def to_s
42
- name
42
+ name || 'nameless-atom'
43
43
  end
44
44
 
45
45
  def pretty_print(q)
@@ -20,6 +20,12 @@ module Algebrick
20
20
  end
21
21
 
22
22
  def match(value, *cases)
23
+ success, result = match? value, *cases
24
+ raise "no match for (#{value.class}) '#{value}' by any of #{cases.map(&:first).join ', '}" unless success
25
+ result
26
+ end
27
+
28
+ def match?(value, *cases)
23
29
  cases = if cases.size == 1 && cases.first.is_a?(Hash)
24
30
  cases.first
25
31
  else
@@ -27,9 +33,9 @@ module Algebrick
27
33
  end
28
34
 
29
35
  cases.each do |matcher, block|
30
- return Matching.match_value matcher, block if matcher === value
36
+ return true, Matching.match_value(matcher, block) if matcher === value
31
37
  end
32
- raise "no match for (#{value.class}) '#{value}' by any of #{cases.map(&:first).join ', '}"
38
+ [false, nil]
33
39
  end
34
40
 
35
41
  def on(matcher, value = nil, &block)
@@ -25,8 +25,8 @@ module Algebrick
25
25
 
26
26
  def initialize(name, &definition)
27
27
  super(name, &definition)
28
- @to_be_kind_of = []
29
- @final_variants = false
28
+ @to_be_kind_of = []
29
+ @final_variants = false
30
30
  end
31
31
 
32
32
  def set_fields(fields_or_hash)
@@ -105,7 +105,7 @@ module Algebrick
105
105
  def apply_be_kind_of
106
106
  @to_be_kind_of.each do |type|
107
107
  @constructor.send :include, type if @constructor
108
- variants.each { |v| v.be_kind_of type unless v == self } if @variants
108
+ variants.each { |v| v.be_kind_of type if v != self && v.respond_to?(:be_kind_of) } if @variants
109
109
  end
110
110
  end
111
111
 
@@ -137,12 +137,12 @@ module Algebrick
137
137
  if variant == self
138
138
  product_to_s
139
139
  else
140
- variant.name
140
+ sub_type variant
141
141
  end
142
142
  end.join(' | ') +
143
143
  ')'
144
144
  when :variant
145
- "#{name}(#{variants.map(&:name).join ' | '})"
145
+ "#{name}(#{variants.map { |v| sub_type v }.join ' | '})"
146
146
  else
147
147
  raise
148
148
  end
@@ -182,6 +182,12 @@ module Algebrick
182
182
  "#{name}(#{fields_str.join ', '})"
183
183
  end
184
184
 
185
+ def sub_type(type)
186
+ return type.name unless type.name.nil?
187
+ return '(recursive)' if type == self # FIXME: will not catch deeper recursions
188
+ return type.to_s
189
+ end
190
+
185
191
  def add_field_names(names)
186
192
  @field_names = names
187
193
  names.all? { |k| Type! k, Symbol }
@@ -26,7 +26,7 @@ module Algebrick
26
26
  end
27
27
 
28
28
  def name
29
- super || @name || 'NoName'
29
+ super || @name || nil
30
30
  end
31
31
 
32
32
  def to_m(*args)
@@ -32,27 +32,39 @@ module Algebrick
32
32
  variants TrueClass, FalseClass
33
33
  end
34
34
 
35
- LinkedList = Algebrick.type(:value_type) do |list|
35
+ List = Algebrick.type(:value_type) do |list|
36
36
  fields! value: :value_type, next: list
37
- variants EmptyLinkedList = atom, list
37
+ variants EmptyList = atom, list
38
38
  end
39
39
 
40
- module LinkedList
40
+ module List
41
41
  include Enumerable
42
42
 
43
43
  def each(&block)
44
+ return to_enum unless block_given?
45
+
44
46
  it = self
45
47
  loop do
46
- break if LinkedListEmpty === it
48
+ break if EmptyList === it
47
49
  block.call it.value
48
50
  it = it.next
49
51
  end
52
+
53
+ self
50
54
  end
51
55
 
52
56
  def next?
53
- self.next != EmptyLinkedList
57
+ self.next != EmptyList
58
+ end
59
+
60
+ def empty?
61
+ !next?
54
62
  end
55
- end
63
+
64
+ def self.build(type, *items)
65
+ items.reverse_each.reduce(EmptyList) { |list, item| self[type][item, list] }
66
+ end
67
+ end
56
68
  end
57
69
 
58
70
  include Types
@@ -669,6 +669,31 @@ Named[
669
669
  it { List.(any, List) === List[1, Empty] }
670
670
  end
671
671
 
672
+ describe 'LinkedList' do
673
+ specify do
674
+ Algebrick::List.build(Integer, 1, 2).must_equal(
675
+ Algebrick::List[Integer][
676
+ value: 1,
677
+ next: Algebrick::List[Integer][
678
+ value: 2,
679
+ next: Algebrick::Types::EmptyList]]
680
+ )
681
+ assert_equal %w[1 2],
682
+ Algebrick::List.build(Integer, 1, 2).map(&:to_s)
683
+ end
684
+
685
+ TreeList = Algebrick.type do
686
+ fields! tag: String, trees: Algebrick::List[Tree]
687
+ end
688
+
689
+ specify do
690
+ assert_equal 'TreeList(tag: String, trees: Algebrick::Types::List[Tree(Empty | Leaf | Node)])',
691
+ TreeList.to_s
692
+ assert_equal 'TreeList[tag: tag, trees: Algebrick::Types::List[Tree(Empty | Leaf | Node)][value: Node[Empty, Empty], next: Algebrick::Types::EmptyList]]',
693
+ TreeList['tag', Algebrick::List.build(Tree, Node[Empty, Empty])].to_s
694
+ end
695
+ end
696
+
672
697
  require 'algebrick/serializer'
673
698
 
674
699
  describe 'serializer' do
@@ -730,6 +755,26 @@ Named[
730
755
  serializer.load(from).must_equal to
731
756
  end
732
757
  end
758
+
759
+ describe 'no name types' do
760
+ WithNoName = Algebrick.type do |t|
761
+ fields a: String, v: t
762
+ variants t,
763
+ type { |it| variants TrueClass, FalseClass, it },
764
+ type { fields string: String },
765
+ atom
766
+ end
767
+
768
+ it 'prints reasonably' do
769
+ assert_equal 'WithNoName(WithNoName(a: String, v: WithNoName) | (TrueClass | FalseClass | (recursive)) | (string: String) | nameless-atom)',
770
+ WithNoName.to_s
771
+ assert_equal '(TrueClass | FalseClass | (recursive))', WithNoName.variants[1].to_s
772
+ assert_equal '(string: String)', WithNoName.variants[2].to_s
773
+ assert_equal 'nameless-atom', WithNoName.variants[3].to_s
774
+
775
+ end
776
+ end
777
+
733
778
  end
734
779
 
735
780
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algebrick
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Petr Chalupa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-12 00:00:00.000000000 Z
11
+ date: 2015-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: minitest