Yesterday I decided I needed a break from calculator programming for a day or two, so I decided to have another practice with Ruby. Somehow, looking up a substitute for Bignums in Ruby brought me to the Perl 6 specifications over time. When I was glancing over the specs, I noticed that it introduced the module Quantum::Superposition as an official part of the language. This module defined the use of Junctions in Perl. I didn't know what a junction was before it, but once I learned it seemed like a decently cool idea. Therefore, I decided to write my own module for Junctions in Ruby written the Ruby Way.
For those who haven't heard of them: Junctions are data types that are treated like a single value but in reality occupy multiple values, much like in quantum theory certain molecules can occupy superpositions -- they can occupy different spatial areas concurrently. Junctions are to be treated as single values that are determined based on their rules (based on ANY and ALL declarations) but can be expanded out to evaluate contents when wanted. When a Junction is going by an exclusive-all ruleset, all values have to be true when evaluated in an expression to give true; when going on an exclusive-any ruleset, if any of the values give true, then it gives a true value. They can also be mixed so that to obtain a true at least a certain number of values must come out as true.
Anyways, here's the class I wrote for Ruby Junctions. No RDoc yet cause I'm lazy with commenting, but it kinda speaks for itself. I cheated a bit and basically held the overall value in an array and made specific evaluation methods, but it works perfectly so its hard to complain:
Code:
And with the test code:
Code:
I get:
Code:
So I can confirm that instances of Junction are treated like they're supposed to according to the specifications for ALL and ANY specifications. I'm thinking of adding a SOM sub-type where you can specify non-completeness of ANY and ALL mixes, such as [1&2&3|4|5] which isn't exactly how the Perl one goes, but this isn't Perl I'm doing this in, is it? Anyways, while at the moment it's not quite as useful as the Perl version (it's mostly only useful for standard-type instances and doesn't fare well with supplying a form of generic like it can be used in Perl), it at least gave my a decent programming practice, and might shorten some of my code that makes use of the class by using junctions instead of Arrays with constant element checking.
Anyways, for other people who use Ruby, I'd like to hear any ideas you have for me concerning additions and fixes
right now I don't have that many standard methods for Junctions yet, but any that anyone would like to provide would be appreciated.
For those who haven't heard of them: Junctions are data types that are treated like a single value but in reality occupy multiple values, much like in quantum theory certain molecules can occupy superpositions -- they can occupy different spatial areas concurrently. Junctions are to be treated as single values that are determined based on their rules (based on ANY and ALL declarations) but can be expanded out to evaluate contents when wanted. When a Junction is going by an exclusive-all ruleset, all values have to be true when evaluated in an expression to give true; when going on an exclusive-any ruleset, if any of the values give true, then it gives a true value. They can also be mixed so that to obtain a true at least a certain number of values must come out as true.
Anyways, here's the class I wrote for Ruby Junctions. No RDoc yet cause I'm lazy with commenting, but it kinda speaks for itself. I cheated a bit and basically held the overall value in an array and made specific evaluation methods, but it works perfectly so its hard to complain:
Code:
class Junction
attr_accessor :value, :coelements
attr_reader :type
ANY = "|";ALL = "&"
def initialize(num_of_values,typeof,array=nil)
if block_given?
index = 0;@value = Array.new(num_of_values){|value|
yield value, index;index+=1}
elsif array;@value = array
else;@coelements = (@value = Array.new(num_of_values)).size.to_i
end
@coelements = @value.size.to_i
@type = (typeof=="any" or typeof=="all")?
((typeof=="any")?ANY: ALL):
((typeof==ANY)?ANY: ALL) #always defaults to ALL if not valid
end
def forall
if block_given?
index = 0;while index < coelements
yield @value.at(index), index;index+=1
end
else;raise "No block given to \'forall\' method"
end
end
def ==(value)
if @type==ANY
return @value.include?(value)
elsif @type==ALL
return (@value==value)?true:false
else;raise "Unknown Junction Typing error in \'==\' method"
end
end
def !=(value)
if @type==ANY
return !(@value.include?(value))
elsif @type==ALL
return (@value==value)?false:true
else;raise "Unknown Junction Typing error in \'==\' method"
end
end
def <(value)
return @value.max < value
end
def >(value)
return @value.min > value
end
def <=(value)
return @value.max <= value
end
def >=(value)
return @value.min >= value
end
def ===(value)
return (@value.include?(value) and @value.at(@value.index(value))===value)
end
def to_a#override
return @value.to_a
end
def to_s#override
return @value.to_s.gsub(", ",((@type==ANY)?ANY: ALL))
end
def to_i
@value.each {|i|(i = (i.to_i)) rescue i = 0}.to_a;return self
end
def to_f
@value.each {|i|(i = (i.to_f)) rescue i = 0.0}.to_a;return self
end
def <<(value)
@value.push(value);return self
end
def push_to_last(value)
@value.push(value);return self
end
def pop_last!
return @value.pop
end
def pop_last_array!
@value.pop;return self
end
def type_change(new_type=nil)
if new_type;@type = new_type
else;@type = ((@type==ANY)?ALL: ANY)
end
end
def elements?
@coelements.to_i
end
def clean!
@value.uniq!;return self
end
def pretty_puts #not needed, but cool for easy reading :3
self.forall {|i,j|puts "#{(j+1).to_s}" <<
format_number_th(j) << " possible value is #{i.to_s}" }
end
private#helpers
def format_number_th(j)#helper for pretty_puts
if [10,11,12].include?(j%100);return "th"
else;return (["st","nd","rd","th"].at((j%10>=4)?3:j%10)).to_s
end
end
end
And with the test code:
Code:
superpos = Junction.new 5,Junction::ANY,[1,2,3,4,5]
superpos.pretty_puts
puts superpos.to_s
puts superpos.to_i.to_s
puts superpos.to_a.to_s
puts (superpos << 6).to_s
puts superpos.pop_last_array!.to_s
puts superpos == 3 #all
superpos.type_change
puts superpos == 3 #any
puts superpos.to_s
superpos.forall{|value,coelement_i|
puts "\\o/ hai mr.#{value} from #{coelement_i} I liek chocolat mikl"
}
I get:
Code:
1st value is 1
2nd value is 2
3rd value is 3
4th value is 4
5th value is 5
[1|2|3|4|5]
[1|2|3|4|5]
[1, 2, 3, 4, 5]
[1|2|3|4|5|6]
[1|2|3|4|5]
false
true
[1&2&3&4&5]
\o/ hai mr.1 from 0 I liek chocolat mikl
\o/ hai mr.2 from 1 I liek chocolat mikl
\o/ hai mr.3 from 2 I liek chocolat mikl
\o/ hai mr.4 from 3 I liek chocolat mikl
\o/ hai mr.5 from 4 I liek chocolat mikl
So I can confirm that instances of Junction are treated like they're supposed to according to the specifications for ALL and ANY specifications. I'm thinking of adding a SOM sub-type where you can specify non-completeness of ANY and ALL mixes, such as [1&2&3|4|5] which isn't exactly how the Perl one goes, but this isn't Perl I'm doing this in, is it? Anyways, while at the moment it's not quite as useful as the Perl version (it's mostly only useful for standard-type instances and doesn't fare well with supplying a form of generic like it can be used in Perl), it at least gave my a decent programming practice, and might shorten some of my code that makes use of the class by using junctions instead of Arrays with constant element checking.
Anyways, for other people who use Ruby, I'd like to hear any ideas you have for me concerning additions and fixes
