I tried using Pythonect, a dataflow programming language.

Overview

Recently, I've introduced a language called Pythonect that I happened to find, so I'll write about it. Since it is still a beta version of the language (environment?), I think there are bugs.

What is Pythonect?

Pythonect http://docs.pythonect.org/en/latest/index.html

Pythonect is a new, experimental, general-purpose dataflow programming language based on Python. It provides both a visual programming language and a text-based scripting language. The text-based scripting language aims to combine the quick and intuitive feel of shell scripting, with the power of Python. The visual programming language is based on the idea of a diagram with “boxes and arrows”.

The Pythonect interpreter (and reference implementation) is a free and open source software written completely in Python, and is available under the BSD 3-Clause license.

Pythonect is a new experimental, general-purpose dataflow programming language based on Python. Pythonect offers both a visual programming language and a text-based scripting language. The text-based scripting language aims to be as intuitive and easy to combine as a shell script, thanks to the power of Python. The visual programming language is based on the idea of "box" and "arrow" diagrams. The Pythonect interpreter (and reference implementation) is all written in Python, is free open source, and is available under the BSD 3-Clause license.

You can think of it as a rough extension of Python's syntax and a modification for a dataflow language. Visual programming can be done with software called Dia, but I will omit it here.

Installation method

For easy_install

$ easy_install pythonect

For pip

$ pip install pythonect

Very easy.

HelloWorld!

$ pythonect
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[Pythonect 0.6.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "HelloWorld!" -> print
<MainProcess:MainThread> : HelloWorld!
'HelloWorld!'

Basic syntax

It looks like Python, but there are more elements that are not Python. For example, for and if cannot be used. Probably the ones that make up compound sentences are almost unusable. There are also some pythonect-specific syntaxes.

Synchronous Forward

>>> a=[1,2,3,4,5,6,7,8,9,10]
>>> a | print 
<MainProcess:MainThread> : 1
<MainProcess:Thread-4576> : 2
<MainProcess:Thread-4577> : 3
<MainProcess:Thread-4576> : 4
<MainProcess:Thread-4577> : 5
<MainProcess:Thread-4576> : 6
<MainProcess:Thread-4577> : 7
<MainProcess:Thread-4576> : 8
<MainProcess:Thread-4577> : 9
<MainProcess:Thread-4576> : 10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

The contents of the data are retrieved synchronously with the operator |. Be sure to take out in the order of 1,2,3,4,5,6,7,8,9,10.

Asynchronous Forward

>>> a -> print 
<MainProcess:MainThread> : 1
<MainProcess:Thread-4797> : 3
<MainProcess:Thread-4796> : 2
<MainProcess:Thread-4797> : 4
<MainProcess:Thread-4796> : 5
<MainProcess:Thread-4796> : 7
<MainProcess:Thread-4797> : 6
<MainProcess:Thread-4796> : 8
<MainProcess:Thread-4797> : 9
<MainProcess:Thread-4796> : 10
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

The contents of the data are retrieved asynchronously with the operator ->. In the synchronous transfer example above,

<MainProcess:MainThread> : 1
<MainProcess:Thread-4576> : 2
<MainProcess:Thread-4577> : 3
<MainProcess:Thread-4576> : 4
...

It worked like this, but when it was executed with ->,

<MainProcess:MainThread> : 1
<MainProcess:Thread-4797> : 3
<MainProcess:Thread-4796> : 2
<MainProcess:Thread-4797> : 4
...

You can see that they are in no particular order.

Assignment operator

>>> [x=10] -> x -> print 
<MainProcess:MainThread> : 10
10

You can put values in variables while the pythonect transfer operator is on. However, it is quite difficult to use.

Predefined variables

Current Value ( _ )

>>> range(3) -> print _
<MainProcess:MainThread> : 0
<MainProcess:Thread-1166> : 1
<MainProcess:Thread-1167> : 2
[0, 1, 2]

_ retrieves only one piece of data from the flow.

All Current Values ( _! )

>>> xrange(3) | sum(_!) | print
<MainProcess:Thread-521> : 3
3

_! Extracts all values from the flow.

Therefore, as an operation

>>> sum(xrange(3))
3

It will be the same as.

Flow control

pyconnect has a bool discriminant during flow control, and only when that value becomes True, the next processing is performed.

Therefore, in the case of True, all are output.

>>> range(3) | True | print
<MainProcess:MainThread> : 0
<MainProcess:Thread-1311> : 1
<MainProcess:Thread-1312> : 2
[0, 1, 2]

On the contrary, in the case of False, nothing is output.

>>> range(3) | False | print
[False, False, False]

As an example of a simple application, it looks like this. Output only when the flow value is 1.

>>> range(3) | _ == 1 | print
<MainProcess:Thread-1491> : 1
[False, 1, False]

It is also possible to decompose one flow into two flows.

>>> range(3) | [[[_ == 0] -> print 'Zero' ],[ print _ ]]
<MainProcess:Thread-7596> : 0
<MainProcess:MainThread> : Zero
<MainProcess:Thread-7621> : 1
<MainProcess:Thread-7641> : 2
[0, 0, False, 1, False, 2]

In one flow, it is judged whether it is 0, and if it is true, Zero is output. After that, the number obtained from the flow is output unconditionally.

After that, there is something like a switch statement, which is rare. It's just very classic and seems to see the dict key match on the switch.

>>> range(10) | _ % 3 | {0: 'Zero' , 1 : 'One' , 2 : 'Two'} | print
<MainProcess:MainThread> : Zero
<MainProcess:Thread-4146> : One
<MainProcess:Thread-4147> : Two
<MainProcess:Thread-4146> : Zero
<MainProcess:Thread-4147> : One
<MainProcess:Thread-4146> : Two
<MainProcess:Thread-4147> : Zero
<MainProcess:Thread-4146> : One
<MainProcess:Thread-4147> : Two
<MainProcess:Thread-4146> : Zero

Process

See the code below.

>>> range(3) -> print
<MainProcess:MainThread> : 0
<MainProcess:Thread-437> : 2
<MainProcess:Thread-436> : 1
[0, 1, 2]

There is a display like <MainProcess: MainThread>. You can see that it runs in a thread in the Python process. You can start a process by adding & to a script running in a thread like this.

>>> range(3) -> print &
<PID #29242> : 0
<PID #29266> : 2
<PID #29268> : 1
[0, 1, 2]

Write FizzBuzz

FizzBuzz.p2y


range(1,20)
    -> [ x = _ ]
    -> [ flag3 = _ % 3 == 0 ]
    -> [ flag5 = _ % 5 == 0 ]
    -> [
            [     flag3 and     flag5 -> print "{0} FizzBuzz".format(x)],
            [     flag3 and not flag5 -> print "{0} Fizz".format(x)    ],
            [ not flag3 and     flag5 -> print "{0} Buzz".format(x)    ],
            [ not flag3 and not flag5 -> print "{0}".format(x)         ]
       ]

I think it's a very similar code, but ** it doesn't work **. The code that actually works looks like this

$ cat ~/FizzBuzz.p2y | tr -d "\n"
range(1,20)    -> [ x = _ ]    -> [ flag3 = _ % 3 == 0 ]    -> [ flag5 = _ % 5 == 0 ]    -> [            [     flag3 and     flag5 -> print "{0} FizzBuzz".format(x)],            [     flag3 and not flag5 -> print "{0} Fizz".format(x)    ],            [ not flag3 and     flag5 -> print "{0} Buzz".format(x)    ],            [ not flag3 and not flag5 -> print "{0}".format(x)         ]       ]

This is a point that I think is a little bit. Maybe Perth is still sweet. When you actually move it, it looks like this.

$ cat ~/FizzBuzz.p2y | tr -d "\n" | pythonect
Python 2.7.12 (default, Nov 19 2016, 06:48:10) 
[Pythonect 0.6.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> <MainProcess:Thread-41> : 1
<MainProcess:Thread-171> : 3 Fizz
<MainProcess:Thread-172> : 2
<MainProcess:Thread-374> : 5 Buzz
<MainProcess:Thread-371> : 4
<MainProcess:Thread-571> : 6 Fizz
<MainProcess:Thread-572> : 7
<MainProcess:Thread-773> : 9 Fizz
<MainProcess:Thread-770> : 8
<MainProcess:Thread-975> : 10 Buzz
<MainProcess:Thread-971> : 11
<MainProcess:Thread-1171> : 12 Fizz
<MainProcess:Thread-1172> : 13
<MainProcess:Thread-6> : 15 FizzBuzz
<MainProcess:Thread-1371> : 14
<MainProcess:Thread-1570> : 16
<MainProcess:Thread-1573> : 17
<MainProcess:Thread-1770> : 18 Fizz
<MainProcess:Thread-1773> : 19
[False, False, False, 1, False, False, False, 2, False, 3, False, False, False, False, False, 4, False, False, 5, False, False, 6, False, False, False, False, False, 7, False, False, False, 8, False, 9, False, False, False, False, 10, False, False, False, False, 11, False, 12, False, False, False, False, False, 13, False, False, False, 14, 15, False, False, False, False, False, False, 16, False, False, False, 17, False, 18, False, False, False, False, False, 19]

It's a code with a very different atmosphere. Pure FizzBuzz is output in the order of 1,2, Fizz, 4, Buzz ... so it's not an exact match, but well. .. .. It's a dataflow language version.

good point

――It works as a dataflow language (there is no dataflow language that works very well in the world) ――It's nice to be able to use the Python library. ――It was also very easy to read, clean and easy to write.

Bad points

--Not compatible with ordinary Python --The result processed by flow cannot be assigned to a variable --Other if, for, and def syntax cannot be used --The readability of flow processing is poor. ――The writing method itself is very simple, but it cannot be indented. --The flow process that returns a list is very difficult to write --You can only get the top or the whole flow value. (I can't take 2 or 3) --I want a named pipe.

Impressions

I think it's quite interesting, but I still want a function. Or rather, I wish I could use other Python syntax. If it can be used as a built-in function normally, why not use it regularly? I think. I think it's the closest language to shell scripts, but it's also close to Street, which I talked about a while ago. Recently, my personal interest is a language with a strong type system, so I hope that a language like this will come out in that area as well.

Recommended Posts

I tried using Pythonect, a dataflow programming language.
I tried playing a ○ ✕ game using TensorFlow
I tried drawing a line using turtle
I tried a functional language with Python
Try using a stochastic programming language (Pyro)
I tried using pipenv, so a memo
I tried using parameterized
I tried using argparse
I tried using mimesis
I tried competitive programming
I tried using aiomysql
I tried using Summpy
I tried using Pipenv
I tried using matplotlib
I tried using ESPCN
I tried using openpyxl
I tried using Ipython
I tried using PyCaret
I tried reading a CSV file using Python
I tried using cron
I tried using ngrok
I tried using face_recognition
I tried using Jupyter
I tried using PyCaret
I tried shell programming
I tried using Heapq
I tried using doctest
I tried using folium
I tried using jinja2
I tried using the functional programming library toolz
I tried using a database (sqlite3) with kivy
I tried using folium
I tried using time-window
I tried to make a ○ ✕ game using TensorFlow
I tried hosting a Pytorch sample model using TorchServe
[Python] I tried running a local server using flask
I tried drawing a pseudo fractal figure using Python
I tried reading data from a file using Node.js.
I tried using Python (3) instead of a scientific calculator
PyTorch Learning Note 2 (I tried using a pre-trained model)
I tried to identify the language using CNN + Melspectogram
I tried to draw a configuration diagram using Diagrams
[I tried using Pythonista 3] Introduction
I tried using easydict (memo).
I tried face recognition using Face ++
I tried using Random Forest
I tried using BigQuery ML
I tried using Amazon Glacier
I tried using git inspector
[Python] I tried using OpenPose
I tried 100 language processing knock 2020
I tried using magenta / TensorFlow
I tried using AWS Chalice
I tried using Slack emojinator
I tried hosting a TensorFlow deep learning model using TensorFlow Serving
I tried using Tensorboard, a visualization tool for machine learning
I tried to automate [a certain task] using Raspberry Pi
I tried to make a stopwatch using tkinter in python
I tried to divide with a deep learning language model
I tried to make a simple text editor using PyQt
I tried using Rotrics Dex Arm