haxetink / tink_core Goto Github PK
View Code? Open in Web Editor NEWCore utilities
Home Page: https://haxetink.github.io/tink_core
License: MIT License
Core utilities
Home Page: https://haxetink.github.io/tink_core
License: MIT License
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
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.
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.
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>
For example adding this.callStack = haxe.CallStack.callStack()
at here
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
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!)
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>
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/
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.
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()
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.
Would be cool! But I guess it is not possible because Surprise is a typedef?!?
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?
See #62 (comment)
One option would be add a cast path to Future, but I prefer to figure out why it works for Promise (on the off chance that it actually does something it shouldn't).
So for example ENOENT
becomes NotFound
etc.
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:
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.-D Serializable
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.
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.
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;
}
}
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
.
For this commit 90a80bc
And hopefully tink_web's tests will pass
Possible now with the new @:genericBuild
HaxeFoundation/haxe#3089
https://gist.github.com/nadako/2ad4246f257e627a5833
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)
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
I would like to join one. If there does not exist one, gitter maybe a good choice.
That could save a little code size, or are there any particular reason?
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
Reasons:
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.
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.
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;
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
And mention Signal.generate.
Unfortunately this will be a breaking change, so it will have to wait.
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.
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)
I can't make it work with haxe 3.1.3.
I have these errors :
https://gist.github.com/boorik/4743aa470bf516fbc347
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?
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
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.
./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.
The latter reads far better in most cases. For compatibility dissolve
should become a deprecated alias to cancel
.
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 ?
Promise.lift(1)
.next(function(_) return ['a'])
.handle(function(o) trace(Std.string(o)));
raises an error at the .next()
line:
String should be tink.core.Future<Unknown<0>>
but works if the return type is explicitly stated as :Array<String>
See #89 (comment)
Error: Extern type not supported : tink.core._Promise.Nonsense
git version will got this error.
1,24,0 ok
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.