pub async fn call<T, E, P, Q, F, Fut>(
        self,
        first: F,
    ) -> Result<(T, Result<Chan<Q, Tx, Rx>, SessionIncomplete<Tx, Rx>>), E>
    where
        S: Session<Action = Call<P, Q>>,
        P: Session,
        Q: Session,
        F: FnOnce(Chan<P, Tx, Rx>) -> Fut,
        Fut: Future<Output = Result<T, E>>,
    {
        let (tx, rx, drop_tx, drop_rx) = self.unwrap_contents();
        let (result, chan_result) = P::over(tx.unwrap(), rx.unwrap(), first).await;
        Ok((
            result?,
            chan_result.map(|(tx, rx)| Chan {
                tx: Some(tx),
                rx: Some(rx),
                drop_tx,
                drop_rx,
                session: PhantomData,
            }),
        ))
    }
/// Execute the session type `P` as a subroutine in a closure.
///
/// This operation takes as input an asynchronous closure that runs a channel for the session
/// type `P` to completion and returns either an error `Err` or some result value `T`. The
/// result of this (provided that no errors occurred during `P`) is a channel ready to execute
/// the session type `Q`.
///
/// # Errors
///
/// The closure must *finish* the session `P` on the channel given to it and *drop* the finished
/// channel before the future returns. If the channel is dropped before completing `P` or is not
/// dropped after completing `P`, a [`SessionIncomplete`] error will be returned instead of a
/// channel for `Q`. The best way to ensure this error does not occur is to call
/// [`close`](Chan::close) on the channel before returning from the future, because this
/// statically checks that the session is complete and drops the channel.
///
/// Additionally, this function returns an `Err` if the closure returns an `Err`.
///
/// # Examples
///
/// This can be used to cleanly modularize a session-typed program by splitting it up into
/// independent subroutines:
///
/// ```
/// use dialectic::prelude::*;
/// use dialectic_tokio_mpsc as mpsc;
///
/// # #[tokio::main]
/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
/// let (c1, c2) = <Session! {
///     call { send String };
///     send String;
/// }>::channel(mpsc::unbounded_channel);
///
/// let ((), c1_result) = c1.call(|c| async move {
///     let c = c.send("Hello!".to_string()).await?;
///     // Because we're done with this subroutine, we can "close" the channel here, but it
///     // will remain open to the calling context so it can run the rest of the session:
///     c.close();
///     Ok::<_, mpsc::Error>(())
/// }).await?;
/// let c1 = c1_result?;
///
/// let c1 = c1.send("World!".to_string()).await?;
/// c1.close();
/// # Ok(())
/// # }
/// ```
///
/// More generally, this construct permits the expression of context-free session types, by
/// allowing recursion in the first parameter to [`Call`]. For a demonstration of this, see the
/// [`stack` example](https://github.com/boltlabs-inc/dialectic/tree/main/examples). For more
/// background on context-free session types, see the paper [*Context-Free Session Type
/// Inference*](https://doi.org/10.1145/3229062) by Luca Padovani. When comparing with that
/// paper, note that the [`call`](Chan::call) operation is roughly equivalent to the paper's
/// `@=` operator, and the [`Call`] type is equivalent to the paper's `;` type operator.
Execute the session type `P` as a subroutine in a closure.
Execute the session type ` P ` as a subroutine in a closure .
pub async fn call<T, E, P, Q, F, Fut>(
        self,
        first: F,
    ) -> Result<(T, Result<Chan<Q, Tx, Rx>, SessionIncomplete<Tx, Rx>>), E>
    where
        S: Session<Action = Call<P, Q>>,
        P: Session,
        Q: Session,
        F: FnOnce(Chan<P, Tx, Rx>) -> Fut,
        Fut: Future<Output = Result<T, E>>,
    {
        let (tx, rx, drop_tx, drop_rx) = self.unwrap_contents();
        let (result, chan_result) = P::over(tx.unwrap(), rx.unwrap(), first).await;
        Ok((
            result?,
            chan_result.map(|(tx, rx)| Chan {
                tx: Some(tx),
                rx: Some(rx),
                drop_tx,
                drop_rx,
                session: PhantomData,
            }),
        ))
    }
pub async fn call < T , E , P , Q , F , Fut > ( self , first : F , ) -> Result < ( T , Result < Chan < Q , Tx , Rx > , SessionIncomplete < Tx , Rx > > ) , E > where S : Session < Action = Call < P , Q > > , P : Session , Q : Session , F : FnOnce ( Chan < P , Tx , Rx > ) -> Fut , Fut : Future < Output = Result < T , E > > , { let ( tx , rx , drop_tx , drop_rx ) = self . unwrap_contents ( ) ; let ( result , chan_result ) = P :: over ( tx . unwrap ( ) , rx . unwrap ( ) , first ) . await ; Ok ( ( result ? , chan_result . map ( | ( tx , rx ) | Chan { tx : Some ( tx ) , rx : Some ( rx ) , drop_tx , drop_rx , session : PhantomData , } ) , ) ) }
Execute the session type `P` as a subroutine in a closure.
Execute the session type ` P ` as a subroutine in a closure .
self
first
F
errors
The closure must *finish* the session `P` on the channel given to it and *drop* the finished
channel before the future returns. If the channel is dropped before completing `P` or is not
dropped after completing `P`, a [`SessionIncomplete`] error will be returned instead of a
channel for `Q`. The best way to ensure this error does not occur is to call
[`close`](Chan::close) on the channel before returning from the future, because this
statically checks that the session is complete and drops the channel.

Additionally, this function returns an `Err` if the closure returns an `Err`.
The closure must * finish * the session ` P ` on the channel given to it and * drop * the finished channel before the future returns . If the channel is dropped before completing ` P ` or is not dropped after completing ` P ` a [ ` SessionIncomplete ` ] error will be returned instead of a channel for ` Q ` . The best way to ensure this error does not occur is to call [ ` close ` ] ( Chan :: close ) on the channel before returning from the future because this statically checks that the session is complete and drops the channel . Additionally this function returns an ` Err ` if the closure returns an ` Err ` .
examples
This can be used to cleanly modularize a session-typed program by splitting it up into
independent subroutines.

```
use dialectic::prelude::*;
use dialectic_tokio_mpsc as mpsc.
This can be used to cleanly modularize a session - typed program by splitting it up into independent subroutines . ` ` ` use dialectic :: prelude :: * ; use dialectic_tokio_mpsc as mpsc .
#[tokio::main]
None
async fn main() -> result<(), box<dyn std::error::error>> {


let ((), c1_result) = c1.call(|c| async move {
let c = c.send("Hello!".to_string()).await?;
Because we're done with this subroutine, we can "close" the channel here, but it
will remain open to the calling context so it can run the rest of the session:
c.close();
Ok::<_, mpsc::Error>(())
}).await?;
let c1 = c1_result?.


let (( ) c1_result ) = c1 . call ( |c| async move { let c = c . send ( " Hello! " . to_string () ) . await? ; Because we ' re done with this subroutine we can " close " the channel here but it will remain open to the calling context so it can run the rest of the session : c . close () ; Ok :: <_ mpsc :: Error > (( )) } ) . await? ; let c1 = c1_result? .
ok(())
None
}


More generally, this construct permits the expression of context-free session types, by
allowing recursion in the first parameter to [`Call`]. For a demonstration of this, see the
[`stack` example]. For more
background on context-free session types, see the paper [*Context-Free Session Type
Inference*] by Luca Padovani. When comparing with that
paper, note that the [`call`](Chan::call) operation is roughly equivalent to the paper's
`@=` operator, and the [`Call`] type is equivalent to the paper's `;` type operator.
More generally this construct permits the expression of context - free session types by allowing recursion in the first parameter to [ ` Call ` ] . For a demonstration of this see the [ ` stack ` example ] . For more background on context - free session types see the paper [ * Context - Free Session Type Inference * ] by Luca Padovani . When comparing with that paper note that the [ ` call ` ] ( Chan :: call ) operation is roughly equivalent to the paper ' s ` @ = ` operator and the [ ` Call ` ] type is equivalent to the paper ' s ` ; ` type operator .