Comments (21)
It should only ever be used when you absolutely have to use it. I don't agree that it is more dangerous than it should be. Maybe we need to talk more about what you are trying to do.
from sodium.
It sounds like all but the third issue are the result of crossing the
threshold between the FRP and non-FRP code.
I may have to agree that 'defer' is a bit of a strange beast; it seems to
require the programmer to give more thought to the underlying evaluation
model than would be preferred. i.e. it seems to run contrary to the
so-called 'denotative' semantics or at least the declarative style that I
associate with FRP.
On Tue, Aug 4, 2015 at 8:32 AM, the-real-blackh [email protected]
wrote:
It should only ever be used when you absolutely have to use it. I don't
agree that it is more dangerous than it should be. Maybe we need to talk
more about what you are trying to do.—
Reply to this email directly or view it on GitHub
#72 (comment).
from sodium.
Exactly. The interface between FRP and non-FRP does require some care, and so the "danger" of these things is there to help you. The best example of this is send() inside listen().
I understand your reservations about defer(), though strictly speaking it is denotational (except that the implementation doesn't match the semantics until I have fixed issue #71). It was intended for certain operational cases, not for general use. I think the solution is to put it into Operational along with updates() and value().
from sodium.
It seems I found a solution: to make special version of send
:
public fun sendInExplicitTx(a: A) {
val tx = Transaction()
try {
send(tx, Value(a))
} finally {
tx.close()
}
}
It solves the problems 2, 3 and 4.
from sodium.
This is a bad, bad idea, for two reasons:
- It is VERY important that people do not write their own primitives, because denotational semantics and therefore compositionality can be easily compromised. Most of the value of FRP is suddenly lost. This is why I (went to all the trouble I did) to make it so send() can't be used inside a listen() callback.
- Even if it were a good idea to encourage people to write their own primitives (which it is not), it is not possible to track dependencies, so it is not possible to guarantee execution in dependency order, so it is not possible to guarantee compositional semantics.
I urge you not to go down this path.
from sodium.
Yes it allows user to write its own primitive-like operations, but them will be not the real primitives. The send
will always be the start of computations, and listen
will always be the end.
It easier to understand for user. The order of computations will be defined by this rule.
C1 = { send -> primitive1 -> primitive2 -> listen(doIoAndSendC2) }
C2 = { send -> primitive1 -> listen(doIo) }
from sodium.
If send() is the start of a computation, then you won't fall foul of "2. send inside listen - Exception". You also shouldn't use it inside a map() function.
from sodium.
You right, I think about it.
from sodium.
I understood one thing: the problem with flatMap
and my advantures with send
cinsist of trying to do IO in primitives.
Other idea: how about throw listen
body from the transaction? We can then safely call send
in there, and automatically solve the problem with defer
.
Or just provide user the ability to create explicit transaction?
from sodium.
I suggest you do it this way:
.listen((x) -> { new Thread(() -> { ... do I/O ... .send(y); }).start(); }
from sodium.
Yes I can, but as I described in #64, I meet with unpredictable exception with codel like this. I can fix it here, but I can not guarantee that not meet this problem again. I already spent in this place about 10 hours. The code is simple, but not easy.
Actially I want to send
- listen
pair be as safe as possible.
from sodium.
Ouch... not like this.
I want to listen
- IO
- send
be as safe as possible.
from sodium.
It can be done without an unpredictable exception. I'll try to help. Are you sometimes not launching a new thread? You must guarantee to do so.
from sodium.
Yes, man can walk through mine field without explosion, but it is wrong way.
from sodium.
Sodium should be very free from anything non-deterministic. What exception are you getting?
from sodium.
Here is the solution of my problem in Android:
val handler = Handler()
stream.listen {
val result = it.value
handler.post {
sink.send(result)
}
}
Is it legal?
This code is not multithread. And it solution is for Android only. Actually this code eqivalent to my suggestion to make listen
execute body outside from the transaction.
from sodium.
What does handler.post do?
from sodium.
It just queue of actions like main application queue.
More detail:
val handler = Handler()
val stream = ...
val sink = ...
stream.listen {
val result = it.value
handler.post {
sink.send(result)
}
}
handler.post {
stream.send(Unit)
}
from sodium.
Handler.post
is equivalent to Executors.singleThreadExecutor().execute
.
from sodium.
Thanks - Not very familiar with that java.util.concurrent stuff. So this code of yours would definitely be legal Sodium, and it shouldn't throw an exception.
val handler = Handler()
stream.listen {
val result = it.value
handler.post {
sink.send(result)
}
}
from sodium.
Just small experiment: SodiumFRP/sodium-kotlin@1a0f8fd#diff-9c15ed34aea5dff2bbe7206855238731L120
The listen
now is outside of transaction. Now you can call send
inside listen
, but you still can not do it in map
or other primitives.
Also notice the defer
implementation.
from sodium.
Related Issues (20)
- Add Test For Transaction Regen To C# Version
- Fix Transaction Regen Bug In C# Version
- Add Test For Transaction Regen to Java Version
- Add Test For Transaction Regen To Scala Version
- Improve Transaction.Post
- Fix Send allowed in Operator
- Fix Send allowed in Operator
- Fix Send allowed in Operator
- Fix Send allowed in Operator
- More aggressive cleanup for switchC / switchS HOT 2
- FRP book, javascript code refactoring HOT 1
- Check whether rank bug needs to be fixed in Java version
- Check whether rank bug needs to be fixed in C# version HOT 1
- C# Cell Lift firing twice, but only propogating value from single execution HOT 2
- [1.17/dev] Game crashed after joined the server HOT 1
- Simultaneous timer events HOT 4
- Causality in the Haskell denotational semantics
- Alternative to ranks & priority queue
- Cannot create account on sodium.nz because https is down
- Cell WPF binding HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sodium.