Giter Club home page Giter Club logo

Comments (21)

the-real-blackh avatar the-real-blackh commented on August 10, 2024

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.

kbaldor avatar kbaldor commented on August 10, 2024

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.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

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.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

This is a bad, bad idea, for two reasons:

  1. 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.
  2. 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.

romansl avatar romansl commented on August 10, 2024

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.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

You right, I think about it.

from sodium.

romansl avatar romansl commented on August 10, 2024

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.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

I suggest you do it this way:

.listen((x) -> { new Thread(() -> { ... do I/O ... .send(y); }).start(); }

from sodium.

romansl avatar romansl commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

Ouch... not like this.

I want to listen - IO - send be as safe as possible.

from sodium.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

Yes, man can walk through mine field without explosion, but it is wrong way.

from sodium.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

Sodium should be very free from anything non-deterministic. What exception are you getting?

from sodium.

romansl avatar romansl commented on August 10, 2024

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.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

What does handler.post do?

from sodium.

romansl avatar romansl commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

Handler.post is equivalent to Executors.singleThreadExecutor().execute.

from sodium.

the-real-blackh avatar the-real-blackh commented on August 10, 2024

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.

romansl avatar romansl commented on August 10, 2024

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)

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.