y_support 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +22 -0
  5. data/README.md +29 -0
  6. data/Rakefile +2 -0
  7. data/lib/y_support/all.rb +40 -0
  8. data/lib/y_support/core_ext/array/misc.rb +45 -0
  9. data/lib/y_support/core_ext/array.rb +1 -0
  10. data/lib/y_support/core_ext/enumerable/misc.rb +32 -0
  11. data/lib/y_support/core_ext/enumerable.rb +1 -0
  12. data/lib/y_support/core_ext/hash/misc.rb +90 -0
  13. data/lib/y_support/core_ext/hash.rb +1 -0
  14. data/lib/y_support/core_ext/module/misc.rb +43 -0
  15. data/lib/y_support/core_ext/module.rb +2 -0
  16. data/lib/y_support/core_ext/numeric/misc.rb +13 -0
  17. data/lib/y_support/core_ext/numeric.rb +1 -0
  18. data/lib/y_support/core_ext/object/misc.rb +31 -0
  19. data/lib/y_support/core_ext/object.rb +1 -0
  20. data/lib/y_support/core_ext/string/misc.rb +80 -0
  21. data/lib/y_support/core_ext/string.rb +1 -0
  22. data/lib/y_support/core_ext/symbol/misc.rb +19 -0
  23. data/lib/y_support/core_ext/symbol.rb +1 -0
  24. data/lib/y_support/core_ext.rb +5 -0
  25. data/lib/y_support/inert_recorder.rb +51 -0
  26. data/lib/y_support/local_object.rb +39 -0
  27. data/lib/y_support/misc.rb +28 -0
  28. data/lib/y_support/name_magic.rb +373 -0
  29. data/lib/y_support/null_object.rb +96 -0
  30. data/lib/y_support/respond_to.rb +32 -0
  31. data/lib/y_support/stdlib_ext/matrix/misc.rb +134 -0
  32. data/lib/y_support/stdlib_ext/matrix.rb +2 -0
  33. data/lib/y_support/stdlib_ext.rb +3 -0
  34. data/lib/y_support/typing/array/typing.rb +17 -0
  35. data/lib/y_support/typing/array.rb +1 -0
  36. data/lib/y_support/typing/enumerable/typing.rb +75 -0
  37. data/lib/y_support/typing/enumerable.rb +1 -0
  38. data/lib/y_support/typing/hash/typing.rb +76 -0
  39. data/lib/y_support/typing/hash.rb +1 -0
  40. data/lib/y_support/typing/module/typing.rb +42 -0
  41. data/lib/y_support/typing/module.rb +1 -0
  42. data/lib/y_support/typing/object/typing.rb +178 -0
  43. data/lib/y_support/typing/object.rb +1 -0
  44. data/lib/y_support/typing.rb +43 -0
  45. data/lib/y_support/unicode.rb +76 -0
  46. data/lib/y_support/version.rb +3 -0
  47. data/lib/y_support.rb +33 -0
  48. data/test/inert_recorder_test.rb +34 -0
  49. data/test/local_object_test.rb +37 -0
  50. data/test/misc_test/test_module/fixture_class.rb +8 -0
  51. data/test/misc_test.rb +289 -0
  52. data/test/name_magic_test.rb +57 -0
  53. data/test/null_object_test.rb +50 -0
  54. data/test/respond_to_test.rb +46 -0
  55. data/test/typing_test.rb +213 -0
  56. data/test/unicode_test.rb +39 -0
  57. data/y_support.gemspec +22 -0
  58. metadata +137 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 39372bbe12e6643f53e78e2b4fd8666477554a67
4
+ data.tar.gz: 9d1c8f648ab7369104ba1ca178fe6ca4abec4cf7
5
+ SHA512:
6
+ metadata.gz: 7e3457d0f805683af3c83018bb7174b161868f614a77b90e7ecc022937ec9b4768fbbfc904717b97beb71dbe0f96296cac46fe60f52db06f89c80c9afa5ce755
7
+ data.tar.gz: 8a57a47dcb40f4c286ffcdf3ad19c0ccd3cd6a58bb32f7d32861701c6907c4734db0eb6e72b6490afcf43e8c2797b0661fda1e7166ed15267736729d45fb06b8
data/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *~
2
+ .#*
3
+ \#*#
4
+ *.gem
5
+ *.rbc
6
+ .bundle
7
+ .config
8
+ .yardoc
9
+ Gemfile.lock
10
+ InstalledFiles
11
+ _yardoc
12
+ coverage
13
+ doc/
14
+ lib/bundler/man
15
+ pkg
16
+ rdoc
17
+ spec/reports
18
+ test/tmp
19
+ test/version_tmp
20
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in y_support.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 boris
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # YSupport
2
+
3
+ Common support library for Y* gems.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'y_support'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install y_support
18
+
19
+ ## Usage
20
+
21
+ Require 'y_support/all', or require 'y_support/something', and use it.
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,40 @@
1
+ #encoding: utf-8
2
+
3
+ require 'y_support'
4
+ require 'y_support/name_magic'
5
+ require 'y_support/typing'
6
+ require 'y_support/unicode'
7
+ require 'y_support/respond_to'
8
+ require 'y_support/null_object'
9
+ require 'y_support/inert_recorder'
10
+ require 'y_support/local_object'
11
+ require 'y_support/misc'
12
+
13
+
14
+ # # Test me!
15
+ # class BlankSlate
16
+ # class << self
17
+ # # Hide the method named +name+ in the BlankSlate class. Don't
18
+ # # hide +instance_eval+ or any method beginning with "__".
19
+ # def hide( name )
20
+ # if instance_methods.include? name and
21
+ # name !~ /^(__|instance_eval)/
22
+ # @hidden_methods ||= {}
23
+ # @hidden_methods[name] = instance_method name
24
+ # undef_method name
25
+ # end
26
+ # end
27
+
28
+ # def find_hidden_method name
29
+ # @hidden_methods ||= {}
30
+ # @hidden_methods[name] || superclass.find_hidden_method( name )
31
+ # end
32
+
33
+ # # Redefine a previously hidden method
34
+ # def reveal name
35
+ # unbound_method = find_hidden_method name
36
+ # fail "Don't know how to reveal method '#{name}'" unless unbound_method
37
+ # define_method( name, unbound_method )
38
+ # end
39
+ # end
40
+ # end # class BlankSlate
@@ -0,0 +1,45 @@
1
+ class Array
2
+ # Converts an array, whose elements are also arrays, to a hash. Head
3
+ # (position 0) of each array is made to point at the rest of the array
4
+ # (tail), normally starting immediately after the head (position 1). The
5
+ # starting position of the tail can be controlled by an optional
6
+ # argument. Tails of 2 and more elements are represented as arrays.
7
+ #
8
+ def to_hash( tail_from = 1 )
9
+ self.reject { | e | e[0].nil? }.reduce({}) { |a, e|
10
+ tail = e[tail_from..-1]
11
+ a.merge( { e[0] => tail.size >= 2 ? tail : tail[0] } )
12
+ }
13
+ end
14
+
15
+ # Does things for each consecutive pair (expects a binary block).
16
+ #
17
+ def each_consecutive_pair
18
+ if block_given?
19
+ return self if ( n = self.size - 1 ) <= 0
20
+ n.times.with_index{|i| yield( self[i], self[i+1] ) }
21
+ return self
22
+ else
23
+ return Enumerator.new do |yielder|
24
+ n.times.with_index{|i| yielder << [ self[i], self[i+1] ] } unless
25
+ ( n = self.size - 1 ) <= 0
26
+ end
27
+ end
28
+ end
29
+
30
+ # Allows style &[ function, *arguments ]
31
+ #
32
+ def to_proc
33
+ proc { |receiver| receiver.send *self }
34
+ end # def to_proc
35
+
36
+ # TEST ME
37
+ # def pretty_inspect
38
+ # each_slice( 4 ) { |slice|
39
+ # slice.map { |e|
40
+ # str = e.to_s[0..25]
41
+ # str + ' ' * ( 30 - str.size )
42
+ # }.reduce( :+ ) + "\n"
43
+ # }.reduce( :+ )
44
+ # end
45
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/array/misc'
@@ -0,0 +1,32 @@
1
+ #encoding: utf-8
2
+
3
+ module Enumerable
4
+ # Checks whether #all? collection elements are #kind_of? module
5
+ # supplied as an argument
6
+ #
7
+ def all_kind_of?( kind )
8
+ all? {|e| e.kind_of? kind }
9
+ end
10
+
11
+ # Checks whether #all? collection elements are #kind_of? Numeric.
12
+ #
13
+ def all_numeric?
14
+ all? {|e| e.kind_of? Numeric }
15
+ end
16
+
17
+ # Checks whether the receiver collection is fully included in the
18
+ # collection supplied as an argument.
19
+ #
20
+ def subset_of?( other_collection )
21
+ all? {|e| other_collection.include? e }
22
+ end
23
+ alias :⊂? :subset_of?
24
+
25
+ # Checks whether the receiver collection contains every element of
26
+ # the collection supplied as an argument.
27
+ #
28
+ def superset_of?( other_collection )
29
+ other.all? {|e| self.include? e }
30
+ end
31
+ alias :⊃? :superset_of?
32
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/enumerable/misc'
@@ -0,0 +1,90 @@
1
+ #encoding: utf-8
2
+
3
+ require 'active_support/core_ext/hash/reverse_merge'
4
+
5
+ class Hash
6
+ # reversed merge!: defaults.merge( self! )
7
+ alias :default! :reverse_merge!
8
+
9
+ # Applies a block as a mapping on all keys, returning a new hash
10
+ def with_keys
11
+ keys.each_with_object self.class.new do |hash_key, ꜧ|
12
+ ꜧ[ yield( hash_key ) ] = self[ hash_key ]
13
+ end
14
+ end
15
+ alias :do_with_keys :with_keys
16
+
17
+ # The difference from do_with_keys is that modify_keys expects block
18
+ # that takes 2 arguments (key: value pair) and returns the new key.
19
+ def modify_keys
20
+ each_with_object self.class.new do |hash_pair, ꜧ|
21
+ ꜧ[ yield( hash_pair ) ] = self[ hash_pair[0] ]
22
+ end
23
+ end
24
+
25
+ # Applies a block as a mapping on all values, returning a new hash
26
+ def with_values
27
+ each_with_object self.class.new do |hash_pair, ꜧ|
28
+ ꜧ[ hash_pair[0] ] = yield( hash_pair[1] )
29
+ end
30
+ end
31
+ alias :do_with_values :with_values
32
+
33
+ # Like #do_with_values, but modifies the receiver.
34
+ def with_values!
35
+ each_with_object self do |hash_pair, ꜧ|
36
+ hash_key, hash_val = hash_pair
37
+ ꜧ[ hash_key ] = yield( hash_val )
38
+ end
39
+ end
40
+ alias :do_with_values! :with_values!
41
+
42
+ # The difference from #do_with_values is that modify_values expects block
43
+ # that takes 2 arguments (key: value pair) and returns the new value.
44
+ def modify_values
45
+ each_with_object self.class.new do |hash_pair, ꜧ|
46
+ ꜧ[ hash_pair[0] ] = yield( hash_pair )
47
+ end
48
+ end
49
+
50
+ # Like #modify_values, but modifies the receiver
51
+ def modify_values!
52
+ each_with_object self do |hash_pair, ꜧ|
53
+ ꜧ[ hash_pair[0] ] = yield( hash_pair )
54
+ end
55
+ end
56
+
57
+ # Like #map that returns a hash.
58
+ def modify
59
+ each_with_object self.class.new do |hash_pair, ꜧ|
60
+ key, val = yield hash_pair
61
+ ꜧ[key] = val
62
+ end
63
+ end
64
+
65
+ # Makes hash keys accessible as methods. If the hash keys collide with
66
+ # its methods, ArgumentError is raised, unless :overwrite_methods
67
+ # option == true.
68
+ #
69
+ def dot!( oo = {} )
70
+ keys.each do |key|
71
+ msg = "key #{key} of #dot!-ted hash is not convertible to a symbol"
72
+ raise ArgumentError, msg unless key.respond_to? :to_sym
73
+ unless oo[:overwrite_methods]
74
+ if methods.include? key.to_sym
75
+ raise ArgumentError, "#dot!-ted hash must not have key names " +
76
+ "colliding with its methods"
77
+ end
78
+ end
79
+
80
+ define_singleton_method key.to_sym do
81
+ self[key]
82
+ end
83
+
84
+ define_singleton_method "#{key}=".to_sym do |value|
85
+ self[key] = value
86
+ end
87
+ end
88
+ return self
89
+ end
90
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/hash/misc'
@@ -0,0 +1,43 @@
1
+ #encoding: utf-8
2
+
3
+ class Module
4
+ # Further automation of soon-to-be-deprecated #autorequire.
5
+ #
6
+ def autoreq( *symbols, descending_path: '..', ascending_path_prefix: 'lib' )
7
+
8
+ require 'active_support/core_ext/string/inflections'
9
+
10
+ namespace = self.name
11
+ namespace_path = namespace.underscore
12
+ namespace_chain = namespace.split "::"
13
+ ascending_path = ascending_path_prefix + '/' + namespace_path
14
+ symbols.map( &:to_s ).each { |ς|
15
+ next if ς.strip.empty?
16
+ camelized_ß = ς.camelize.to_sym
17
+ path = './' + [ descending_path, ascending_path, ς ].join( '/' )
18
+ autoload camelized_ß, path
19
+ }
20
+ end
21
+
22
+ # I didn't write this method by myself.
23
+ #
24
+ def attr_accessor_with_default *symbols, &block
25
+ raise ArgumentError, 'Block with default value required!' unless block
26
+ symbols.each { |ß|
27
+ module_eval {
28
+ define_method "#{ß}=" do |arg|
29
+ instance_variable_set "@#{ß}", arg
30
+ end
31
+ define_method ß do
32
+ singleton_class.class_eval { attr_reader ß }
33
+ if instance_variables.include? "@#{ß}".to_sym then
34
+ instance_variable_get "@#{ß}"
35
+ else
36
+ instance_variable_set "@#{ß}", block.call
37
+ end
38
+ end
39
+ }
40
+ }
41
+ end
42
+ alias :attr_accessor_w_default :attr_accessor_with_default
43
+ end
@@ -0,0 +1,2 @@
1
+ require 'y_support'
2
+ require 'y_support/core_ext/module/misc'
@@ -0,0 +1,13 @@
1
+ #encoding: utf-8
2
+
3
+ class << Integer
4
+ def zero; 0 end
5
+ end
6
+
7
+ class << Float
8
+ def zero; 0.0 end
9
+ end
10
+
11
+ class << Complex
12
+ def zero; Complex 0, 0 end
13
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/numeric/misc'
@@ -0,0 +1,31 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Object
4
+ def const_set_if_not_defined( const, value )
5
+ mod = self.is_a?(Module) ? self : self.singleton_class
6
+ mod.const_set( const, value ) unless mod.const_defined?( const )
7
+ end
8
+
9
+ def const_redefine_without_warning( const, value )
10
+ mod = self.is_a?(Module) ? self : self.singleton_class
11
+ mod.send(:remove_const, const) if mod.const_defined?( const )
12
+ mod.const_set( const, value )
13
+ end
14
+
15
+ # Create public attributes (ie. with readers) and initialize them with
16
+ # prescribed values. Takes a hash of { symbol => value } pairs. Existing methods
17
+ # are not overwritten by the new getters, unless option :overwrite_methods
18
+ # is set to true.
19
+ def singleton_set_attr_with_readers( hash, oo = {} )
20
+ hash.each { |key, val|
21
+ key = key.aE_respond_to( :to_sym, "key of the attr hash" ).to_sym
22
+ instance_variable_set( "@#{key}", val )
23
+ if oo[:overwrite_methods] then ⓒ.module_exec { attr_reader key }
24
+ elsif methods.include? key
25
+ raise "Attempt to add \##{key} getter failed: " +
26
+ "method \##{key} already defined."
27
+ else ⓒ.module_exec { attr_reader key } end
28
+ }
29
+ end
30
+ alias :ⓒ_set_attr_w_readers :singleton_set_attr_with_readers
31
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/object/misc'
@@ -0,0 +1,80 @@
1
+ #encoding: utf-8
2
+
3
+ require 'active_support/core_ext/object/blank'
4
+
5
+ class String
6
+ # Integer() style conversion, or false if conversion impossible.
7
+ #
8
+ def to_Integer
9
+ begin
10
+ int = Integer stripn
11
+ return int
12
+ rescue ArgumentError
13
+ return false
14
+ end
15
+ end
16
+
17
+ # Float() style conversion, or false if conversion impossible.
18
+ #
19
+ def to_Float
20
+ begin
21
+ fl = Float stripn
22
+ return fl
23
+ rescue ArgumentError
24
+ return false
25
+ end
26
+ end
27
+
28
+ # Like #strip, but also strips newlines.
29
+ #
30
+ def stripn
31
+ encode( universal_newline: true )
32
+ .gsub("\n", "")
33
+ .strip
34
+ end
35
+
36
+ # Joins a paragraph of possibly indented, newline separated lines into a
37
+ # single contiguous string.
38
+ #
39
+ def wring_heredoc
40
+ encode(universal_newline: true)
41
+ .split("\n") # split into lines
42
+ .map( &:strip ) # strip them
43
+ .delete_if( &:blank? ) # delete blank lines
44
+ .join " " # and join with whitspace
45
+ end
46
+
47
+ # If the string is empty, it gets replace with the string given as argument.
48
+ #
49
+ def default! default_string
50
+ strip.empty? ? clear << default_string.to_s : self
51
+ end
52
+
53
+ # As it says – replaces spaces with underscores.
54
+ #
55
+ def underscore_spaces
56
+ gsub ' ', '_'
57
+ end
58
+
59
+ # Converts a string into a standard symbol. While Symbol class objects can
60
+ # be created from any string, it is good practice to keep symbols free of
61
+ # whitespaces and weird characters, so that the are typed easily, usable as
62
+ # variable names etc. This method thus removes punctuation, removes
63
+ # superfluous spaces, and underscores the remaining ones, before returning
64
+ # the string.
65
+ #
66
+ def standardize
67
+ ς = self.dup
68
+ ",.;".each_char { |c| ς.gsub! c, " " }
69
+ ς.stripn
70
+ .squeeze(" ")
71
+ .underscore_spaces
72
+ end
73
+
74
+ # Applies #standardize to the receiver and converts the result to a symbol.
75
+ #
76
+ def to_standardized_sym
77
+ standardize
78
+ .to_sym
79
+ end
80
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/string/misc'
@@ -0,0 +1,19 @@
1
+ # -*- coding: utf-8 -*-
2
+ class Symbol
3
+ # This method applies String#default! method to the receiver converted to
4
+ # a string. Of course, symbols are immutable, so in spite of the exclamation
5
+ # mark in the method name, a new symbol (supplied as argument) is returned,
6
+ # if the original one is considered "defaulted" (otherwise, original symbol
7
+ # is returned unchanged).
8
+ #
9
+ def default! default_symbol
10
+ to_s.default!( default_symbol ).to_sym
11
+ end
12
+
13
+ # Applies String#to_standardized_sym method to the recevier converted to a
14
+ # string.
15
+ #
16
+ def to_standardized_sym
17
+ to_s.to_standardized_sym
18
+ end
19
+ end
@@ -0,0 +1 @@
1
+ require 'y_support/core_ext/symbol/misc'
@@ -0,0 +1,5 @@
1
+ #encoding: utf-8
2
+
3
+ Dir["#{File.dirname( __FILE__ )}/core_ext/*.rb"].sort.each do |path|
4
+ require "y_support/core_ext/#{File.basename( path, '.rb' )}"
5
+ end
@@ -0,0 +1,51 @@
1
+ #encoding: utf-8
2
+
3
+ require 'y_support'
4
+
5
+ # Inert recorder is similar to a null object in the sense, that in response to
6
+ # almost all messages it returns self. But in addition, it records received
7
+ # messages along with their arguments and blocks (if given). Recoded messages
8
+ # are available via #recorded_messages reader, aliased #ρ (small Greek rho).
9
+ # Inert recorder does not require any arguments for initalization, but if they
10
+ # are supplied, they are silently recoded into @init_args (for arguments) and
11
+ # @init_block (for block, if given) instance variables, exposed via standard
12
+ # readers.
13
+ #
14
+ class InertRecorder
15
+ attr_reader :init_args, :init_block, :recorded_messages
16
+ alias ρ recorded_messages
17
+
18
+ # No arguments are required for initialization, but if they are supplied, they
19
+ # are silently recorded into @init_args (for argument array) and @init_block
20
+ # (for block, if given) instance variables, exposed via standard readers.
21
+ #
22
+ def initialize *args, &block
23
+ @init_args = args
24
+ @init_block = block
25
+ @recorded_messages = []
26
+ end
27
+
28
+ # Always true.
29
+ #
30
+ def present?; true end
31
+
32
+ # Always false.
33
+ #
34
+ def blank?; false end
35
+
36
+ # Always true.
37
+ #
38
+ def respond_to? ß, *args, &block; true end
39
+
40
+ def method_missing ß, *args, &block # :nodoc:
41
+ @recorded_messages << [ ß, args, block ]
42
+ return self
43
+ end
44
+ end # class InertRecorder
45
+
46
+
47
+ class Object
48
+ # InertRecorder constructor.
49
+ #
50
+ def InertRecorder *args, &block; InertRecorder.new *args, &block end
51
+ end
@@ -0,0 +1,39 @@
1
+ #encoding: utf-8
2
+
3
+ require 'y_support'
4
+
5
+ # Object, whose business is to stay local to methods. Optional signature
6
+ # provides additional level of safety in ensuring object locality. (Signature
7
+ # accessor is :signature, aliased as :σ (small Greek sigma).)
8
+ #
9
+ class LocalObject
10
+ attr_reader :signature
11
+ alias σ signature
12
+
13
+ # Optional argument signature provides additional level of safety in
14
+ # ascertaining that the object indeed is of local origin.
15
+ #
16
+ def initialize signature=__callee__
17
+ @signature=signature
18
+ end
19
+
20
+ # True if the (optional) signature matches.
21
+ #
22
+ def local_object? signature=__callee__
23
+ signature == self.signature
24
+ end
25
+ alias ℓ? local_object?
26
+ end
27
+
28
+
29
+ class Object
30
+ # LocalObject constructor.
31
+ #
32
+ def LocalObject signature=nil; LocalObject.new signature end
33
+ alias L! LocalObject
34
+
35
+ # False for normal objects, overriden in the LocalObject class.
36
+ #
37
+ def local_object? signature=nil; false end
38
+ alias ℓ? local_object?
39
+ end
@@ -0,0 +1,28 @@
1
+ #encoding: utf-8
2
+ require 'y_support'
3
+
4
+ # Typing library.
5
+ #
6
+ # Apart from usual <em>typing by class and ancestry</em>, supported by built-in
7
+ # #kind_of?, alias #is_a? inquirerers, this typing library provides support for
8
+ # provides support for <em>typing by declaration</em> and <em>duck typing</em>.
9
+ #
10
+ # 1. Using method <b>declare_compliance</b>, a module can explicitly declare that
11
+ # it provides the interface compliant with another module. Corresponding inquirer
12
+ # methods are <b>declared_compliance</b> (returning a list of modules with which
13
+ # the receiver declares compliance or implicitly complies) and
14
+ # <b>declares_compliance?( other_module )</b>, which anwers whether the receiver
15
+ # complies with other_module. An object always implicitly complies with its class
16
+ # and class ancestry.
17
+ #
18
+ # 2. Duck type enforcement for method parameters is supported by a collection of
19
+ # enforcer methods (aka. run-time assertions). These methods look very much like
20
+ # assertions, but they start with <b>tE_...</b>, meaning "enforce by raising
21
+ # TypeError".
22
+
23
+ [ :core_ext, :stdlib_ext ].each do |ext|
24
+ Dir["#{File.dirname( __FILE__ )}/#{ext}/*/misc.rb"].sort.each { |path|
25
+ dir = File.dirname( path ).match( "y_support/#{ext}" ).post_match
26
+ require "y_support/#{ext}#{dir}/misc"
27
+ }
28
+ end