\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename join-python.info @settitle join-python @afourpaper @documentencoding UTF-8 @documentlanguage en @finalout @c %**end of header @dircategory Python @direntry * join-python: (join-python). Join-calculus for Python @end direntry @copying Copyright @copyright{} 2014 Mattias Andrée @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end quotation @end copying @ifnottex @node Top @top Join Python -- Join-calculus for Python @insertcopying @end ifnottex @titlepage @title Join Python @subtitle Join-calculus for Python @author by Mattias Andrée (maandree) @page @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @menu * Overview:: Brief overview of Join Python. * Signals:: The signal construct. * Fragments:: The fragment join construct. * GNU Free Documentation License:: Copying and sharing this manual. @end menu @node Overview @chapter Overview Join Python is a Python 3 library that implements join-calculus. Join Python can be used by importing the module @code{join} in any Python 3 program, provided that Join Python is installed. Join Python provides the ability to write more concise code using almost any published concurrency pattern with explicit monitor calls. @node Signals @chapter Signals A signal it as function that runs asynchronously. It is put in its own thread. To declare a signal, add the @code{@@signal} decorator to a function definition or pass function to the the constructor of the class @code{signal}. @cartouche @example >>> from join import * >>> import time >>> >>> @@signal >>> def sig(delay, value): >>> time.sleep(delay) >>> print(value) >>> >>> sig(0.25, 'first') >>> print('last') last first @end example @end cartouche @cartouche @example >>> from join import * >>> import time >>> >>> def f(delay, value): >>> time.sleep(delay) >>> print(value) >>> >>> signal(f)(0.25, 'first') >>> print('last') last first @end example @end cartouche As an extension to join-calculus, signals in Join Java can be joined with the returned value of the function can be fetched when joined. @cartouche @example >>> from join import * >>> import time >>> >>> def f(delay, value): >>> time.sleep(delay) >>> return value ** 2 >>> >>> sig = signal(f)(0.25, 2) >>> print('between') >>> print(sig.join()) between 16 @end example @end cartouche In the next chapter fragments will be introduced. If you want a signal without a fragment capability use @code{@@puresignal} or @code{puresignal} instead of @code{@@signal} or @code{signal}. @node Fragments @chapter Fragments A fragment is a partial function. What this means is that you can make functions that block until all its fragments have returned. Signals return immediately. Waiting for a fragment is called joining,@footnote{Yes, it is a bit inconvenient that waiting for a thread or signal is also called joining.} when joining when a fragment you receive the arguments in was invoked with and the value it returned, the latter being an extension to join-calculus. Remember that a signal returns an object with an argumentless method name @code{join} that joins with the signal and returns that value the signal function returned. @cartouche @example >>> from join import * >>> >>> @@fragment >>> def fragment(value): >>> return value ** 2 >>> >>> def f(value): >>> ((fragment_value,), _kwargs, rc) = join(fragment) >>> return rc + fragment_value + value >>> >>> fragment(2) >>> print(f(3)) 10 @end example @end cartouche The function @code{join} returns a tuple of the positional arguments, the named arguments and the returned value. But you can also join with multiple fragemnts, in which case @code{join} returns a list of these tuples, one tuple for each fragment, in the same order as they appear as arguments for the @code{join} call. @cartouche @example >>> from join import * >>> >>> @@fragment >>> def f1(value): >>> return value ** 2 >>> >>> @@fragment >>> def f2(value): >>> return value ** 3 >>> >>> def f(value): >>> ((_args1, _kwargs1, rc1), (_args2, _kwargs2, rc2)) = join(f1, f2) >>> return value + rc1 + rc2 >>> >>> f1(2) >>> f2(2) >>> print(f(2)) 14 @end example @end cartouche @node GNU Free Documentation License @appendix GNU Free Documentation License @include fdl.texinfo @bye