Last active
February 9, 2025 19:32
-
-
Save nanjizal/5f8d3c567db74a998090cb4378cfb65c to your computer and use it in GitHub Desktop.
Tuple5
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Test { | |
static function main() { | |
var oot:OneOfFive<Int, Float, Bool, String, haxe.Int64> = 39; | |
//trace((oot : haxe.Int64)); | |
trace((oot : Int)); | |
oot = haxe.Int64.fromFloat(13928044195); | |
trace((oot : haxe.Int64)); | |
oot = true; | |
trace((oot : Bool)); | |
var oneofpart1:haxe.Int64 = oot; | |
trace(oneofpart1); | |
var oneofpart2:Bool = oot; | |
trace(oneofpart2); | |
var t5 = new Tuple5( 10, 'string', true, 10.1); | |
var tt = new Tuple5( 10, 'string', true, false, 10.1 ); | |
trace( tt ); | |
var t55 = t5.reorder('ba'); | |
trace('19'); | |
trace( 'reorder ' + t55 ); | |
trace( t5.a_type() ); | |
trace( t5.e_type() ); | |
trace( t5 ); | |
trace( t5.a ); | |
t5.a = 11; | |
trace( t5.a ); | |
//trace( t5._1 ); | |
//trace( t5._2 ); | |
//trace( t5._3 ); | |
trace( t5.e ); | |
//t5.e = 100; | |
//t5._0 = 11; | |
trace( t5 ); | |
//t5._0 = 'oops'; | |
//trace( t5._0 ); | |
trace( t5.length ); | |
haxe.Timer.measure(() -> { | |
var i = 0; | |
while (++i != 999999) { | |
var oneOfTwo:OneOfTwo<Int, Float> = 29.2; | |
var result:Float = oneOfTwo; | |
} | |
}); | |
} | |
} | |
class Tuple5<A,B,C,D,E> { | |
var _a: OneOfFive<A,B,C,D,E>; | |
var _b: OneOfFive<B,C,D,E,A>; | |
@:optional var _c: OneOfFive<C,D,E,A,B>; | |
@:optional var _d: OneOfFive<D,E,A,B,C>; | |
@:optional var _e: OneOfFive<E,A,B,C,D>; | |
public inline | |
function new( a: OneOfFive<A,B,C,D,E>, b: OneOfFive<B,C,D,E,A> | |
, ?c: OneOfFive<C,D,E,A,B>, ?d: OneOfFive<D,E,A,B,C> | |
, ?e: OneOfFive<E,A,B,C,D>){ | |
_a = a; | |
_b = b; | |
if( c != null ) _c = c; | |
if( d != null ) _d = d; | |
if( e != null ) _e = e; | |
} | |
@:keep | |
public inline | |
function toString(){ | |
var out = '| ' + a + ', ' + b; | |
if( _c != null ){ | |
out += ', ' + c; | |
if( _d != null ) { | |
out += ', ' + d; | |
if( _e!= null ) out += ', ' + e; | |
} | |
} | |
out += ' |'; | |
return out; | |
} | |
public var a( get, set ): A; | |
inline | |
function get_a(): A{ | |
return (_a:A); | |
} | |
inline | |
function set_a( v: A ){ | |
_a = v; | |
return v; | |
} | |
public inline | |
function a_type(){ | |
return Type.typeof( a ); | |
} | |
public inline | |
function b_type(){ | |
return Type.typeof( b ); | |
} | |
public inline | |
function c_type(){ | |
return Type.typeof( c ); | |
} | |
public inline | |
function d_type(){ | |
return Type.typeof( d ); | |
} | |
public inline | |
function e_type(){ | |
return Type.typeof( e ); | |
} | |
var b( get, set ): B; | |
inline | |
function get_b(): B{ | |
return (_b:B); | |
} | |
public inline | |
function set_b( v: B ){ | |
_b = v; | |
return v; | |
} | |
var c( get, set ): Null<C>; | |
inline | |
function get_c(): C{ | |
return if( _c!= null ){ | |
(_c:C); | |
} else { | |
trace( "can't get c as this truple does not contain c"); | |
null; | |
} | |
} | |
inline | |
function set_c( v: Null<C> ){ | |
if( _c == null ) throw new haxe.Exception( "can't set c, tuple does not contain c"); | |
if( _c != null ) _c = v; | |
return v; | |
} | |
public var d( get, null ): Null<D>; | |
inline | |
function get_d(): Null<D>{ | |
return if( _d!= null ){ | |
(_d:D); | |
} else { | |
trace( "can't get d as this truple does not contain d"); | |
null; | |
} | |
} | |
inline | |
function set_d( v: Null<D> ){ | |
if( _d == null ) throw new haxe.Exception( "can't set d, tuple does not contain d"); _d = v; | |
return v; | |
} | |
public var e( get, set ): Null<E>; | |
inline | |
function get_e(): Null<E>{ | |
return if( _e!= null ){ | |
(_e:E); | |
} else { | |
trace( "can't get e as this truple does not contain e"); | |
null; | |
} | |
} | |
inline | |
function set_e( v: Null<E> ){ | |
if( _e == null ) throw new haxe.Exception( "can't set e, tuple does not contain e"); | |
_e = v; | |
return v; | |
} | |
public var length( get, null ): Int; | |
inline function get_length(): Int { | |
return if( _e == null ) { | |
if( _d == null ){ | |
if( _c == null ){ | |
2; | |
} else { | |
3; | |
} | |
} else { | |
4; | |
} | |
} else { | |
5; | |
} | |
} | |
@:keep | |
public | |
function reorder( str: String ){ | |
var aa = 'a'.code; | |
var bb = 'b'.code; | |
var cc = 'c'.code; | |
var dd = 'd'.code; | |
var ee = 'e'.code; | |
var let = [aa,bb,cc,dd,ee]; | |
var found =[false,false,false,false,false]; | |
var eDone = false; | |
var charNo: Int; | |
var g: Dynamic = null; | |
var h: Dynamic = null; | |
var i: Dynamic = null; | |
var j: Dynamic = null; | |
var k: Dynamic = null; | |
var count = 0; | |
var goodLength = ( str.length > 1 && str.length < 6 ); | |
if( !goodLength ) return null; | |
var validChar = function( char: Int ){ | |
return ( char > 96 && char < 102 ); | |
} | |
var charNo:Int = str.charCodeAt( 0 ); | |
if( validChar( charNo ) ){ | |
var idx = let.indexOf(charNo); | |
if( idx == -1 ) return null; | |
if( found[idx]== false){ | |
g = switch( charNo ){ | |
case 97: | |
_a; | |
case 98: | |
_b; | |
case 99: | |
_c; | |
case 100: | |
_d; | |
case 101: | |
_e; | |
case _: | |
null; | |
} | |
found[idx]=true; | |
} | |
} | |
charNo = str.charCodeAt( 1 ); | |
if( validChar( charNo ) ){ | |
var idx = let.indexOf(charNo); | |
if( idx == -1 ) return null; | |
if( found[idx]== false){ | |
h = switch( charNo ){ | |
case 97: | |
_a; | |
case 98: | |
_b; | |
case 99: | |
_c; | |
case 100: | |
_d; | |
case 101: | |
_e; | |
case _: | |
null; | |
} | |
found[idx]=true; | |
} | |
} | |
charNo = str.charCodeAt( 2 ); | |
if( validChar( charNo ) ){ | |
var idx = let.indexOf(charNo); | |
if( idx == -1 ) return null; | |
if( found[idx]== false){ | |
i = switch( charNo ){ | |
case 97: | |
_a; | |
case 98: | |
_b; | |
case 99: | |
_c; | |
case 100: | |
_d; | |
case 101: | |
_e; | |
case _: | |
null; | |
} | |
found[idx]=true; | |
} | |
} | |
charNo = str.charCodeAt( 3 ); | |
if( validChar( charNo ) ){ | |
var idx = let.indexOf(charNo); | |
if( idx == -1 ) return null; | |
if( found[idx]== false){ | |
j = switch( charNo ){ | |
case 97: | |
a; | |
case 98: | |
b; | |
case 99: | |
c; | |
case 100: | |
d; | |
case 101: | |
e; | |
case _: | |
null; | |
} | |
found[idx]=true; | |
} | |
} | |
charNo = str.charCodeAt( 4 ); | |
if( validChar( charNo ) ){ | |
var idx = let.indexOf(charNo); | |
if( idx == -1 ) return null; | |
if( found[idx]== false){ | |
k = switch( charNo ){ | |
case 97: | |
_a; | |
case 98: | |
_b; | |
case 99: | |
_c; | |
case 100: | |
_d; | |
case 101: | |
_e; | |
case _: | |
null; | |
} | |
found[idx]=true; | |
} | |
} | |
return if( str.length == 2 ){ | |
new Tuple5( g, h ); | |
} else if( str.length == 3 ){ | |
new Tuple5( g, h, i ); | |
} else if( str.length == 4 ){ | |
new Tuple5( g, h, i, j ); | |
} else if( str.length == 5 ){ | |
new Tuple5( g, h, i, j, k ); | |
} else { null; } | |
} | |
} | |
/** | |
* This is the base class for OneOf. | |
* It contains 5 variables representing types in the parameter, | |
* allowing you to properly unify values that are competely different types | |
* when declaring a variable with the type OneOf or a local variable, | |
*while completely avoiding Dynamic. | |
* Here's how the system will work. | |
* So, here's a code example of OneOf. | |
```haxe | |
var oneOfThree:OneOfThree<String, Bool, Int> = "Hello world"; | |
var str:String = oneOfThree; | |
trace(str); | |
oneOfThree = true; | |
var positive:Bool = oneOfThree; | |
trace(positive); | |
oneOfThree = 902597; | |
var score:Int = oneOfThree; | |
trace(score); | |
``` | |
* See how it works? When you assign oneOfThree to a value that's a different type, | |
* You can change the underlying type for it entirely, which means you can assign a | |
* local variable to it with the correct type having results which work as expected, | |
* and the wrong type type which returns null. | |
* You see, each time you assign a oneOf with a different type, a new OneOfAny class | |
* is constructed and stays that way until you assign with a different type. | |
* This is how an either type works because you don't want multiple unifying types. | |
* That includes when you assign a OneOfTwo variable's type parameters as just | |
* a Float and an Int. If the value is a whole number (integer), the underlying type | |
* of Int is chosen. And if the value is a number with a decimal (float), the | |
* underlying type of Float is chosen. However, the type unification can also choose | |
* the type Single to be the underlying type of the oneOf. | |
* Now, if you want to know how values with different types can't throw a compile-time | |
* error, it's because the types in the parameters are allowed to be chosen from | |
* assigning the oneOf with a different type when the initial type was for example, | |
* a float, integer, string, boolean, or whatever class you want the oneOf to input. | |
* See, like I said at the start, OneOfAny stores 5 variables representing types which | |
* allows you to completely avoid using Dynamic entirely and use that to create your own | |
* type-safe either implementation that performs ~93 times faster than just using Dynamic. | |
* See, Dynamic needs to be used when it wants to be used, like for example, save data, | |
* which requires a Dynamic if you want a small amount of code in it. However, for any | |
* other stuff than that, it won't perform any good and type safety goes out the window. | |
* This is why I've created a OneOf impl that doesn't use dynamic at all, because there's | |
* basically nothing in the way when assigning a variable to a completely different type, or | |
* in that case, intializing it to a type that is in the type parameter list. This is | |
* because we know what types we're working with. | |
* Now, the types that are available are: | |
* OneOfTwo<T1, T2> | |
* OneOfThree<T1, T2, T3> | |
* OneOfFour<T1, T2, T3, T4> | |
* OneOfFive<T1, T2, T3, T4, T5> | |
* I made this project for fun and I hope for you to use this (with credit) | |
Happy coding! | |
OneOfAny and wrappers of it written by SomeGuyWhoLikesFNF, including this wall of text. | |
*/ | |
// The class used for the wrappers. Use with caution. | |
@:generic | |
class OneOfAny<T1, T2, T3, T4, T5> { | |
public var underlyingType1:T1; | |
public var underlyingType2:T2; | |
public var underlyingType3:T3; | |
public var underlyingType4:T4; | |
public var underlyingType5:T5; | |
inline public function new() {} | |
} | |
// Now we're onto the wrappers. | |
@:generic | |
abstract OneOfTwo<T1, T2>(OneOfAny<T1, T2, Bool, Bool, Bool>) { | |
public var underlyingType1(get, set):T1; | |
inline function get_underlyingType1():T1 { | |
return this.underlyingType1; | |
} | |
inline function set_underlyingType1(t:T1):T1 { | |
return this.underlyingType1 = t; | |
} | |
public var underlyingType2(get, set):T2; | |
inline function get_underlyingType2():T2 { | |
return this.underlyingType2; | |
} | |
inline function set_underlyingType2(t:T2):T2 { | |
return this.underlyingType2 = t; | |
} | |
inline private function new() { | |
this = new OneOfAny<T1, T2, Bool, Bool, Bool>(); | |
} | |
@:from inline static function fromT1<T1, T2>(t:T1):OneOfTwo<T1, T2> { | |
var instance = new OneOfTwo<T1, T2>(); | |
instance.underlyingType1 = t; | |
return instance; | |
} | |
@:to inline function toT1():T1 { | |
return underlyingType1; | |
} | |
@:from inline static function fromT2<T1, T2>(t:T2):OneOfTwo<T1, T2> { | |
var instance = new OneOfTwo<T1, T2>(); | |
instance.underlyingType2 = t; | |
return instance; | |
} | |
@:to inline function toT2():T2 { | |
return underlyingType2; | |
} | |
} | |
@:generic | |
abstract OneOfThree<T1, T2, T3>(OneOfAny<T1, T2, T3, Bool, Bool>) { | |
public var underlyingType1(get, set):T1; | |
inline function get_underlyingType1():T1 { | |
return this.underlyingType1; | |
} | |
inline function set_underlyingType1(t:T1):T1 { | |
return this.underlyingType1 = t; | |
} | |
public var underlyingType2(get, set):T2; | |
inline function get_underlyingType2():T2 { | |
return this.underlyingType2; | |
} | |
inline function set_underlyingType2(t:T2):T2 { | |
return this.underlyingType2 = t; | |
} | |
public var underlyingType3(get, set):T3; | |
inline function get_underlyingType3():T3 { | |
return this.underlyingType3; | |
} | |
inline function set_underlyingType3(t:T3):T3 { | |
return this.underlyingType3 = t; | |
} | |
inline private function new() { | |
this = new OneOfAny<T1, T2, T3, Bool, Bool>(); | |
} | |
@:from inline static function fromT1<T1, T2, T3>(t:T1):OneOfThree<T1, T2, T3> { | |
var instance = new OneOfThree<T1, T2, T3>(); | |
instance.underlyingType1 = t; | |
return instance; | |
} | |
@:to inline function toT1():T1 { | |
return underlyingType1; | |
} | |
@:from inline static function fromT2<T1, T2, T3>(t:T2):OneOfThree<T1, T2, T3> { | |
var instance = new OneOfThree<T1, T2, T3>(); | |
instance.underlyingType2 = t; | |
return instance; | |
} | |
@:to inline function toT2():T2 { | |
return underlyingType2; | |
} | |
@:from inline static function fromT3<T1, T2, T3>(t:T3):OneOfThree<T1, T2, T3> { | |
var instance = new OneOfThree<T1, T2, T3>(); | |
instance.underlyingType3 = t; | |
return instance; | |
} | |
@:to inline function toT3():T3 { | |
return underlyingType3; | |
} | |
} | |
@:generic | |
abstract OneOfFour<T1, T2, T3, T4>(OneOfAny<T1, T2, T3, T4, Bool>) { | |
public var underlyingType1(get, set):T1; | |
inline function get_underlyingType1():T1 { | |
return this.underlyingType1; | |
} | |
inline function set_underlyingType1(t:T1):T1 { | |
return this.underlyingType1 = t; | |
} | |
public var underlyingType2(get, set):T2; | |
inline function get_underlyingType2():T2 { | |
return this.underlyingType2; | |
} | |
inline function set_underlyingType2(t:T2):T2 { | |
return this.underlyingType2 = t; | |
} | |
public var underlyingType3(get, set):T3; | |
inline function get_underlyingType3():T3 { | |
return this.underlyingType3; | |
} | |
inline function set_underlyingType3(t:T3):T3 { | |
return this.underlyingType3 = t; | |
} | |
public var underlyingType4(get, set):T4; | |
inline function get_underlyingType4():T4 { | |
return this.underlyingType4; | |
} | |
inline function set_underlyingType4(t:T4):T4 { | |
return this.underlyingType4 = t; | |
} | |
inline private function new() { | |
this = new OneOfAny<T1, T2, T3, T4, Bool>(); | |
} | |
@:from inline static function fromT1<T1, T2, T3, T4>(t:T1):OneOfFour<T1, T2, T3, T4> { | |
var instance = new OneOfFour<T1, T2, T3, T4>(); | |
instance.underlyingType1 = t; | |
return instance; | |
} | |
@:to inline function toT1():T1 { | |
return underlyingType1; | |
} | |
@:from inline static function fromT2<T1, T2, T3, T4>(t:T2):OneOfFour<T1, T2, T3, T4> { | |
var instance = new OneOfFour<T1, T2, T3, T4>(); | |
instance.underlyingType2 = t; | |
return instance; | |
} | |
@:to inline function toT2():T2 { | |
return underlyingType2; | |
} | |
@:from inline static function fromT3<T1, T2, T3, T4>(t:T3):OneOfFour<T1, T2, T3, T4> { | |
var instance = new OneOfFour<T1, T2, T3, T4>(); | |
instance.underlyingType3 = t; | |
return instance; | |
} | |
@:to inline function toT3():T3 { | |
return underlyingType3; | |
} | |
@:from inline static function fromT4<T1, T2, T3, T4>(t:T4):OneOfFour<T1, T2, T3, T4> { | |
var instance = new OneOfFour<T1, T2, T3, T4>(); | |
instance.underlyingType4 = t; | |
return instance; | |
} | |
@:to inline function toT4():T4 { | |
return underlyingType4; | |
} | |
} | |
@:generic | |
abstract OneOfFive<T1, T2, T3, T4, T5>(OneOfAny<T1, T2, T3, T4, T5>) { | |
public var underlyingType1(get, set):T1; | |
inline function get_underlyingType1():T1 { | |
return this.underlyingType1; | |
} | |
inline function set_underlyingType1(t:T1):T1 { | |
return this.underlyingType1 = t; | |
} | |
public var underlyingType2(get, set):T2; | |
inline function get_underlyingType2():T2 { | |
return this.underlyingType2; | |
} | |
inline function set_underlyingType2(t:T2):T2 { | |
return this.underlyingType2 = t; | |
} | |
public var underlyingType3(get, set):T3; | |
inline function get_underlyingType3():T3 { | |
return this.underlyingType3; | |
} | |
inline function set_underlyingType3(t:T3):T3 { | |
return this.underlyingType3 = t; | |
} | |
public var underlyingType4(get, set):T4; | |
inline function get_underlyingType4():T4 { | |
return this.underlyingType4; | |
} | |
inline function set_underlyingType4(t:T4):T4 { | |
return this.underlyingType4 = t; | |
} | |
public var underlyingType5(get, set):T5; | |
inline function get_underlyingType5():T5 { | |
return this.underlyingType5; | |
} | |
inline function set_underlyingType5(t:T5):T5 { | |
return this.underlyingType5 = t; | |
} | |
inline private function new() { | |
this = new OneOfAny<T1, T2, T3, T4, T5>(); | |
} | |
@:from inline static function fromT1<T1, T2, T3, T4, T5>(t:T1):OneOfFive<T1, T2, T3, T4, T5> { | |
var instance = new OneOfFive<T1, T2, T3, T4, T5>(); | |
instance.underlyingType1 = t; | |
return instance; | |
} | |
@:to inline function toT1():T1 { | |
return underlyingType1; | |
} | |
@:from inline static function fromT2<T1, T2, T3, T4, T5>(t:T2):OneOfFive<T1, T2, T3, T4, T5> { | |
var instance = new OneOfFive<T1, T2, T3, T4, T5>(); | |
instance.underlyingType2 = t; | |
return instance; | |
} | |
@:to inline function toT2():T2 { | |
return underlyingType2; | |
} | |
@:from inline static function fromT3<T1, T2, T3, T4, T5>(t:T3):OneOfFive<T1, T2, T3, T4, T5> { | |
var instance = new OneOfFive<T1, T2, T3, T4, T5>(); | |
instance.underlyingType3 = t; | |
return instance; | |
} | |
@:to inline function toT3():T3 { | |
return underlyingType3; | |
} | |
@:from inline static function fromT4<T1, T2, T3, T4, T5>(t:T4):OneOfFive<T1, T2, T3, T4, T5> { | |
var instance = new OneOfFive<T1, T2, T3, T4, T5>(); | |
instance.underlyingType4 = t; | |
return instance; | |
} | |
@:to inline function toT4():T4 { | |
return underlyingType4; | |
} | |
@:from inline static function fromT5<T1, T2, T3, T4, T5>(t:T5):OneOfFive<T1, T2, T3, T4, T5> { | |
var instance = new OneOfFive<T1, T2, T3, T4, T5>(); | |
instance.underlyingType5 = t; | |
return instance; | |
} | |
@:to inline function toT5():T5 { | |
return underlyingType5; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment