Code Monkey home page Code Monkey logo

tink_core's Introduction

Tinkerbell Core Library

Build Status Gitter Discord

The tink_core lib contains a set of lightweight tools for robust programming.

All modules are situated in tink.core.*. Some contain more than a single type. Generally, it is advisable to import the modules of this package through using rather than import.

In addition, you can import all modules at once with using tink.CoreApi;.

Documentations

Documentations have been moved to a new home: https://haxetink.github.io/tink_core/

tink_core's People

Contributors

adrianv avatar andyli avatar back2dos avatar benmerckx avatar cambiata avatar cedx avatar ciscoheat avatar confidantcommunications avatar gama11 avatar gene-pavlovsky avatar grisevg avatar jasononeil avatar kevinresol avatar markknol avatar nadako avatar sebthom avatar sh-dave avatar t1ml3arn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tink_core's Issues

Port all tests to tink_unittest

With haxe.unit being deprecated (which I probably wouldn't mind in itself) and having no support for async (which turns out to be increasingly annoying), the tests need to be ported.

That's generally true for many if not most tink libs. This is gonna be fun \o/

Ref class bug?

Hi!

First of all, thank you for that kind of library. I'd like to use it in my future project, but in process of testing the functionality of lib i faced width feature of Ref class:

public function ref() 
{
	var r:Ref< Int > = 4;
	var r2:Ref< Int > = r;
		
	trace(r2);// prints @[4] - ok
	r = 1;
	trace(r2);// prints @[4] - why, if it should reference to r value?
	r2 = 2;
	trace(r);// prints @[1] - same question
}

It is looks like it is bug. Or may be i'm using it in wrong way?
Compiled width haxe 3.4.0 (3.3.0-rc1 the same)
and tink_core 1.6.2 from haxelib

Make signals destroyable.

Signal triggers should be manually destroyable, which should not only clear them, but also make sure handlers are not registered in the future. Derived signals should be destroyed accordingly.

Technically, this is breaking change, because it increases the constraints of the SignalObject interface, but since no other public code on GitHub seems to implement it, it shouldn't be an issue.

Outcome docs minor: asSuccess() and asFailure() missing

Hi Juraj!

In the current Outcome docs https://github.com/haxetink/tink_core#outcome, the code example uses the .asSuccess() and .asFailure() helper methods. These methods don't seem to exist in OutcomeTools any more.

Just curious: Is there a problem with these helper methods, or why did you remove them..?
(Don't want to do a PR for updating the docs until I know that these helper methods weren't accidentally left out in the current OutcomeTools. Guess they weren't!)

handleSuccess/handleFailure

Hey,

I think it would be very useful to have "handleSuccess" and "handleFailure" functions for "Surprise". I do not know where the intrinsic place would be to add these, but if I do know I am happy to make a pull request :-).

Best,
Nathan

tink.core.Any unwanted cast

class Main {
    static function main() {
        trace(tinkAny());
        trace(stdAny());
    }
    
    static function tinkAny():tink.core.Any {
        return new MultiPolygon();
    }
    static function stdAny():std.Any {
        return new MultiPolygon();
    }
}


abstract MultiPolygon({}){
	public inline function new()
		this = {}
	@:to
	public function castIt():Array<Polygon> {
		return [];
	}
}

typedef Polygon = {};

In the generated code tinkAny returns value wrapped by castIt() while stdAny returns the object itself. Not sure why. (tested haxe 4p4 and 3.4.7)

This only happens in a "older" version of tink_core when we haven't typedef std.Any yet.

Compile error with latest haxe (nightly builds)

The error I get:

/usr/lib/haxe/lib/tink_core/git/src/tink/core/Outcome.hx:44: characters 4-8 : tink.core.Lazy<orUse.D> should be orUse.D

haxe version:

Haxe Compiler 3.2.0  (git build development @ 11cba31)

Unwanted implicit cast of Dynamic when returning Promise<Dynamic>

I'd like this example code to work correctly without the workaround: https://try.haxe.org/#DE849

// Test: haxe -cp . -lib tink_core -main Test -js test.js && node test.js

using tink.CoreApi;

class Test {
    static function main() {
        load().next(parse).handle(function (o) trace(o));
    }
    
    static function load():Promise<String>
    	return '{"e": 2.71828}';
    
	static function parse(str:String):Promise<Dynamic>
    	return haxe.Json.parse(str); // Uncaught TypeError: l.get(...).handle is not a function,
    	//return Success(haxe.Json.parse(str)); // Workaround
}

Json.parse returns Dynamic which is interpreted as Promise<Dynamic>

"clearing" a FutureTrigger

I have situation, where I am handling a Future with a function, but after a certain time I do not want that function to be executed anymore on the future triggering.

Of course, I could rewrite the function and tell it to do nothing, if that time has been reached.

Still, it would be nice, if I could "clear" a FutureTrigger. As in, when it is triggered now, non of the added functions will be invoked anymore. Same thing for SignalTriggers!

Adding such a function is simple, what I am wondering is: Is this within the philosophy of Futures? Would an pull request be accepted?

Combining multiple futures

In the promhx library, there is a when function that combines multiple Promises in to a single one which accepts type-safe callback and I think Future could do the same.

There is an implementation already in the ufront library. (though IMO "combine" is a better name here)

compile waring Callbacks.hx:45

./tests/Callbacks.hx:45: characters 5-36 : Warning : Implicit cast from Callback is deprecated. Please create an issue if you find it useful, and don't want this cast removed.

Recover cast failed

var p:Promise<Int> = 5;
var recover = function(e:Error) return 1;
p.recover(recover).handle(function(v) assertEquals(5, v)); // works
p.recover(function(e:Error) return 1).handle(function(v) assertEquals(5, v)); // fail: Int should be tink.Future<Int>

This one is super strange, should be a Haxe issue.

Recommend "await" or even make it "tink" officially

I am talking about this library: https://github.com/benmerckx/await

Maybe I am just a not-good-enough programmer to write good codes. But I have been coding async stuff for a big project with tink_core in the past few months, from which I learnt that control flows in async programming is simply nightmare. Consider the following code:

function afterIf() return doSomething();

return if(myBool) {
  doSomethingAsync() >> function(_) return afterIf();
} else
  afterIf();

Unlike sync programming, one would need to "invert" their code (i.e. put afterIf before the if) in async programming. And normally there would be multiple if, nested if, loops or other control flows in your async code. So, suppose the function code is literally written as ABCDEFG, you may end up have to read it as FGCDEAB. Because actual "first statement" of the function is somewhere in the middle and the code before that are just the declaration of the callback of some control flow. Things get unmanageable really quickly when the code are "inverted" like that.

With await we can simply write:

if(myBool) {
  @:await doSomethingAsync();
}
return @:await doSomething();

IMO, async code can't be simpler than that.

So using it with tink_core Futures should be "enabled by default" in my opinion.

On the other hand, await (or the credit should goes to haxe-continuation as mentioned in await's readme) utilized macro to solve a problem that can never be solved so elegantly in other languages. It truly demonstrates the power of Haxe macro and I believe it should be highly promoted.

At the end, a BIG BIG THANK to @benmerckx again. And I would like to hear from you on this topic.

Signal.create does not seem to exist

Hi,

Just trying tink_core library for using signal and reading the documentation it mention the possibility to use Signal.create() to instantiate a new Signal but haxe says : "tink.core.Signal has no field create"

Do I require another library ?

Thanks

Rename `dissolve` to `cancel`

The latter reads far better in most cases. For compatibility dissolve should become a deprecated alias to cancel.

What is the best way to "map" a surprise

I find my self often in the situation, that I want to use map on a Surprise, and by this want to "map" the inner Outcome.

surprise.map(function(o) {return o.map(function(r) {return some_calculation_on_r})});

Now, this is lengthy. Can this be shortened? Maybe there should be a "deepMap" function on Surprise.

Future / Promise merge should be parallel

The way the code is written right now, the second future only gets evaluated once the first one is done, so if the second future is lazy, both operations are performed in sequence.

Something like:

var ret = Future.async(function (cb) {
  var aDone = false, bDone = false;
  var aRes = null, bRes = null;
  function check() if (aDone && bDone) cb(combine(aRes, bRes));
  a.handle(function (a) { aRes = a; aDone = true; check(); });
  b.handle(function (b) { bRes = b; bDone = true; check(); });
}, true);
return if (gather) ret.gather() else ret;

Implement Future, Signal, CallbackLink on top of interfaces/classes

Reasons:

  • Anonymous functions can be really slow, particularly on C++
  • Other optimizations are also possible with type hierarchies
  • API is stable and mature

It's important to maintain full API compatibility, in particular with the function based constructors.

Ideally Callback would also be implemented over an interface, but it would break code that relies on type inference.

signal's clock example in README.md

The tickHandlers var seems rather unused or did i miss something ๐Ÿค”

class Clock {
    public var tick(default, null):Signal<Noise>;
    var tickHandlers:SignalTrigger<Noise>;
    public function new() {
        var s = Signal.trigger();
        var t = new Timer(1000);
        t.run = function () s.trigger(Noise);
        this.tick = s;
    }
}

Eager evaluation of future

function doStuff() {
  return otherFuture >> function(o) return doOtherStuff(o);
}

doStuff(); // this does not trigger doOtherStuff
doStuff().handle(function(_){}); // unless the returned future is handled

Possible solution:
function eager<A>(f:Future<A>) { f.handle(function () {}); return f; }
and then return eager(otherFuture >> function(o) return doOtherStuff(o))

or put it inside the Future abstract
function eager<A>() { this.handle(function () {}); return this; }
and then return (otherFuture >> function(o) return doOtherStuff(o)).eager()

dox - Incompatibilities between tink.core.Future in flash and js (could not merge definition)

haxelib newrepo
haxelib install tink_core
haxelib install dox
haxe -lib tink_core --macro "include('tink')" -D doc-gen --no-output -xml xml/php.xml -php bin
haxe -lib tink_core --macro "include('tink')" -D doc-gen --no-output -xml xml/neko.xml -neko bin/docs.n
haxe -lib tink_core --macro "include('tink')" -D doc-gen --no-output -xml xml/js.xml -js bin/docs.js
haxe -lib tink_core --macro "include('tink')" -D doc-gen --no-output -xml xml/flash.xml -swf-version 11 -swf bin/docs.swf
haxelib run dox -i xml -o api --toplevel-package "tink"
Parsing xml/flash.xml
Parsing xml/js.xml
Called from ? line 1
Called from dox/Dox.hx line 146
Called from dox/Dox.hx line 139
Called from C:\GitHub\haxe\std/haxe/rtti/XmlParser.hx line 90
Called from C:\GitHub\haxe\std/haxe/rtti/XmlParser.hx line 317
Called from C:\GitHub\haxe\std/haxe/rtti/XmlParser.hx line 284
Uncaught exception - Incompatibilities between tink.core.Future in flash and js (could not merge definition)

tink.core.Future definition brokes hexMachina API generation: https://travis-ci.org/DoclerLabs/hexMachina/jobs/373031409

Any idea how to fix that?

Nodejs error on 1.6.1

After updating to 1.6.1, I get the following error on node.js:

C:\HaxeToolkit\haxe\lib\tink_core/1,6,1/src/tink/core/Callback.hx:32: characters 6-8 : Type not found : js.Node

And on travis:

/usr/lib/haxe/lib/tink_core/1,6,1/src/tink/core/Callback.hx:32: characters 6-8 : Unknown identifier : js

The quick-fix I did on that line was to change #elseif nodejs to #elseif hxnodejs.

Cannot set a Future var to null

var f:Future<Dynamic> = null;

The above code throws the following error on flash, is it expected?

On static platforms, null can't be used as basic type tink.Future<Dynamic>

About Noise

I wonder what is the point of having a single value Noise there?

Couldn't it be enum Noise { }?
It will only unify with null.

Or even better abstract Noise(Dynamic) {} or abstract Noise(Void) {}?
It will only unify with null and there is nothing added to the output.

Getting `Pair` to play nice with haxe.Serializer

Pair, is great for simple composition, but it doesn't serialize consistently across targets, and does not serialize on neko at all (it throws Cannot Serialize [...]).

This means, for example, you could not use a Pair as a return value on a Haxe Remoting API, hosted using neko.

Obviously serializing the pair itself is easy if we do it manually:

var s = new haxe.Serializer();
s.serialize( p.a );
s.serialize( p.b );

but while we have varying underlying data structures I can't think of any way to do it automatically.

My thoughts:

  • Won't work: Adding custom serialization to the private class Data<A, B> definition, so that it serializes as { a: A, b: B }. You will still end up with Cy14:tink.core.Data before the serialized object.
  • Won't work: Implementing any kind of custom serialization for abstracts. AFAIK there's no way to detect an abstract is an abstract at runtime, and serialization is all runtime reflection. Unless I'm missing something?
  • Conditional compilation? -D Serializable
  • A serializable version? SPair

For now I've got some classes which holding Pairs, so I'll do custom serializing on those, but it would be great to come up with a solution so I can serialize Pair directly, because I think I'd use it in remoting APIs a fair bit.

Problems compiling on cpp and android

Hi,

Ive started having problems compiling my app that is using tink_core (and tink_macro)... The error is:

Error: error running arm-linux-androideabi-g++ -Iinclude --sysroot=C:\tools\OpenFLTools\AndroidNDK/platforms/android-9/arch-arm -IC:\tools\OpenFLTools\AndroidNDK/sources/cxx-stl/gnu-libstdc++/4.4.3/include -IC:\tools\OpenFLTools\AndroidNDK/sources/cxx-stl/gnu-libstdc++/4.4.3/libs/armeabi/include -DHXCPP_VISIT_ALLOCS -DHXCPP_API_LEVEL=321 -IC:/Servers/Haxe/haxe/lib/hxcpp/3,2,37/include -Iinclude -fpic -fvisibility=hidden -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums "-D_LINUX_STDDEF_H " -Wno-psabi -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -fomit-frame-pointer -fexceptions -fno-strict-aliasing -finline-limit=10000 -DANDROID=ANDROID -DHX_ANDROID -DHXCPP_ANDROID_PLATFORM=14 -Wa,--noexecstack -O2 -DNDEBUG -c -x c++ -Wno-invalid-offsetof -frtti ./src/tink/core/_Ref/Ref_Impl_.cpp -oobj/android-v7/828b6933_Ref_Impl_.obj

In file included from ./src/tink/core/_Ref/Ref_Impl_.cpp:7:
include/tink/core/_Ref/Ref_Impl_.h:34: error: 'ArrayBase' in namespace 'cpp' does not name a type
include/tink/core/_Ref/Ref_Impl_.h:37: error: 'cpp::ArrayBase' has not been declared
include/tink/core/_Ref/Ref_Impl_.h:40: error: 'cpp::ArrayBase' has not been declared
include/tink/core/_Ref/Ref_Impl_.h:43: error: 'cpp::ArrayBase' has not been declared
include/tink/core/_Ref/Ref_Impl_.h:46: error: 'ArrayBase' in namespace 'cpp' does not name a type
./src/tink/core/_Ref/Ref_Impl_.cpp:31: error: 'ArrayBase' in namespace 'cpp' does not name a type
./src/tink/core/_Ref/Ref_Impl_.cpp: In function 'Dynamic tink::core::_Ref::__Ref_Impl__obj_new()':
./src/tink/core/_Ref/Ref_Impl_.cpp:53: error: '_new' is not a member of 'tink::core::_Ref::Ref_Impl__obj'
./src/tink/core/_Ref/Ref_Impl_.cpp: At global scope:
./src/tink/core/_Ref/Ref_Impl_.cpp:55: error: 'Dynamic tink::core::_Ref::Ref_Impl__obj::get_value' is not a static member of 'class tink::core::_Ref::Ref_Impl__obj'
./src/tink/core/_Ref/Ref_Impl_.cpp:55: error: 'ArrayBase' is not a member of 'cpp'
./src/tink/core/_Ref/Ref_Impl_.cpp:55: error: expected ',' or ';' before '{' token
./src/tink/core/_Ref/Ref_Impl_.cpp:69: error: 'Dynamic tink::core::_Ref::Ref_Impl__obj::set_value' is not a static member of 'class tink::core::_Ref::Ref_Impl__obj'
./src/tink/core/_Ref/Ref_Impl_.cpp:69: error: 'ArrayBase' is not a member of 'cpp'
./src/tink/core/_Ref/Ref_Impl_.cpp:69: error: expected primary-expression before 'param'
./src/tink/core/_Ref/Ref_Impl_.cpp:69: error: expected ',' or ';' before '{' token
./src/tink/core/_Ref/Ref_Impl_.cpp:86: error: 'String tink::core::_Ref::Ref_Impl__obj::toString' is not a static member of 'class tink::core::_Ref::Ref_Impl__obj'
./src/tink/core/_Ref/Ref_Impl_.cpp:86: error: 'ArrayBase' is not a member of 'cpp'
./src/tink/core/_Ref/Ref_Impl_.cpp:86: error: expected ',' or ';' before '{' token
./src/tink/core/_Ref/Ref_Impl_.cpp:106: error: 'ArrayBase' in namespace 'cpp' does not name a type
./src/tink/core/_Ref/Ref_Impl_.cpp: In function 'Dynamic tink::core::_Ref::__Ref_Impl__objto(const Dynamic&)':
./src/tink/core/_Ref/Ref_Impl_.cpp:137: error: 'to' is not a member of 'tink::core::_Ref::Ref_Impl__obj'
Error: error running arm-linux-androideabi-g++ -Iinclude --sysroot=C:\tools\OpenFLTools\AndroidNDK/platforms/android-9/arch-arm -IC:\tools\OpenFLTools\AndroidNDK/sources/cxx-stl/gnu-libstdc++/4.4.3/include -IC:\tools\OpenFLTools\AndroidNDK/sources/cxx-stl/gnu-libstdc++/4.4.3/libs/armeabi/include -DHXCPP_VISIT_ALLOCS -DHXCPP_API_LEVEL=321 -IC:/Servers/Haxe/haxe/lib/hxcpp/3,2,37/include -Iinclude -fpic -fvisibility=hidden -ffunction-sections -funwind-tables -fstack-protector -fno-short-enums "-D_LINUX_STDDEF_H " -Wno-psabi -D__ARM_ARCH_5__ -D__ARM_ARCH_5T__ -D__ARM_ARCH_5E__ -D__ARM_ARCH_5TE__ -march=armv7-a -mfpu=vfpv3-d16 -mfloat-abi=softfp -fomit-frame-pointer -fexceptions -fno-strict-aliasing -finline-limit=10000 -DANDROID=ANDROID -DHX_ANDROID -DHXCPP_ANDROID_PLATFORM=14 -Wa,--noexecstack -O2 -DNDEBUG -c -x c++ -Wno-invalid-offsetof -frtti ./src/tink/core/_Ref/Ref_Impl_.cpp -oobj/android-v7/828b6933_Ref_Impl_.obj

Thats the android stack trace, and the cpp seems similar but longer (ie, there seems to be other bits too).

Im using haxe 3.2.0 and tink_core 1.0.0-rc.10... ... any ideas?

Cheers,
Ian

Future.NEVER being wrapped in a SyncFuture

It is now generated as the following:

tink_core__$Future_Future_$Impl_$.NEVER = new tink_core__$Future_SyncFuture(new tink_core__$Lazy_LazyConst(tink_core__$Future_NeverFuture.inst));

Not sure from when this happens, needa investigate.

Future -> Stream

Hi there,
I'm having a look at how the Futures work in tink and I must say I quite like them. Especially the use of abstracts and inlining makes it very efficient from what I saw. I still struggle a bit with the API (handle instead of then and so on) but I can get over it ...

However it is falling short in one (for now) particular use case that I have:
I use Streams to handle async operations that can resolve multiple times (a websocket connection in particular) so that I can register callbacks that will be called every time the Stream resolves.

I found a partial workaround to do that with Futures, by creating my own StreamTrigger which doesn't clear the CallbackList on resolve. The problem is that as soon as I map/flatMap/merge/etc the "Stream" with another transformer, it goes back to a standard FutureTrigger.

I would have to create a Stream abstract class that mimics the Future for most of it's behaviour, since I can't extend an abstract. Or maybe there's a better way to get the Stream behaviour with the current Future implementation?

This is the code I've been using for testing/exploring this https://gist.github.com/alebianco/24d2dee448dd90cae24f

About `Sequence`.

So I've merged it for now. I wonder though, what exactly is the purpose of it?

Is it mostly to just say "one or many"? Or do we want immutability? Does it really make sense to allow for array access? Wouldn't it potentially be better to have a more opaque implementation that could potentially be lazy, so that e.g. seq.filter(...).slice(x, y).map(...).filter(...).map(...) really just constructs one sequence, and it only does it when the iterator on said sequence is created?

I'm just throwing around ideas. Maybe you could share your experience about how you've been using this @kevinresol ?

Surprise.map

Would be cool! But I guess it is not possible because Surprise is a typedef?!?

Futures should should be more lazy

This utility function attempts to be lazy if there are no handlers registered for the resulting Future:

	/**
	 * Returns a `Future` which resolves to `value` after `time_ms` milliseconds.
	 */
	public static function yieldLater<T>(value:Lazy<T>, time_ms:Int):Future<T>
		return Future.async(function (yield)
			Timer.delay(yield.bind(Noise), time_ms)
		).map(function (_) return value.get());

The test code looks like this:

TimerUtil.yieldLater(function () { trace('call'); return 42; }, 1000);

There are no handlers but "call" message does appear in the console log.
Tested with tink_core 1.17.0.

Ideally futures and promises would be as lazy as possible to avoid unnecessary computations/service calls. Would be good to add a set of laziness tests to verify their behavior.

Error with latest haxe version

Hi, you might be already aware but using latest haxe (3.2.0 dev) I got this error with tink_core :

C:\HaxeToolkit\haxe\lib/tink_core/1,0,0-rc,6/src/tink/core/Outcome.hx:44: characters 4-8 : tink.core.Lazy<orUse.D> should be orUse.D

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.