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.
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.
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!'
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.
>>> 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.
>>> 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.
>>> [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.
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.
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
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]
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.
――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.
--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.
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