Skip to content

Instantly share code, notes, and snippets.

@nanjizal
Last active February 9, 2025 19:32
Show Gist options
  • Save nanjizal/5f8d3c567db74a998090cb4378cfb65c to your computer and use it in GitHub Desktop.
Save nanjizal/5f8d3c567db74a998090cb4378cfb65c to your computer and use it in GitHub Desktop.
Tuple5
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