概要
Python を最近触り始めたところコードブロックがインデント基準というのが個人的に気に入らず、スーパーセットを探したところ Haxe "ハックス(Youtube調べ)" (https://haxe.org/) を見つけた。
バイトコードを吐くのではなく、Python のソースにトランスパイルできるので、既存の Python コードとキメラ合体できるのでは?と思い触ってみた。
- Python へのトランスパイル方法はこちら
https://haxe.org/manual/target-python-getting-started.html
環境
Haxe: 4.2.1
コード1
Haxe
Main.hx
class Main {
static public function main():Void {
trace("Hello World");
}
}
ファイル名はクラス名と一緒じゃないといかんのかな?
Python
トランスパイルコマンド: haxe --python main.py --main Main
main.py
# Generated by Haxe 4.2.1+bf9ff69
# coding: utf-8
import sys
class Main:
__slots__ = ()
@staticmethod
def main():
print("Hello World")
class haxe_iterators_ArrayIterator:
__slots__ = ("array", "current")
def __init__(self,array):
self.current = 0
self.array = array
def hasNext(self):
return (self.current < len(self.array))
def next(self):
def _hx_local_3():
def _hx_local_2():
_hx_local_0 = self
_hx_local_1 = _hx_local_0.current
_hx_local_0.current = (_hx_local_1 + 1)
return _hx_local_1
return python_internal_ArrayImpl._get(self.array, _hx_local_2())
return _hx_local_3()
class python_internal_ArrayImpl:
__slots__ = ()
@staticmethod
def _get(x,idx):
if ((idx > -1) and ((idx < len(x)))):
return x[idx]
else:
return None
class python_internal_MethodClosure:
__slots__ = ("obj", "func")
def __init__(self,obj,func):
self.obj = obj
self.func = func
def __call__(self,*args):
return self.func(self.obj,*args)
Main.main()
でかい。
コード2
Haxe
Main.hx
class Main {
static public function main():Void {
trace("Hello World");
var items = ["a", "b", "c"];
for (index in 0...items.length) {
trace('$index : ${items[index]}');
}
if (items.length == 3) {
trace('length is ');
trace('3');
} else {
trace('length is ');
trace('not 3');
}
trace('end');
}
}
肝心のコードブロックを作ってみた。
Python
トランスパイルコマンド: haxe --python main.py --main Main
main.py
# Generated by Haxe 4.2.1+bf9ff69
# coding: utf-8
import sys
class Main:
__slots__ = ()
@staticmethod
def main():
print("Hello World")
items = ["a", "b", "c"]
_g = 0
_g1 = len(items)
while (_g < _g1):
index = _g
_g = (_g + 1)
print(str(((("" + str(index)) + " : ") + HxOverrides.stringOrNull((items[index] if index >= 0 and index < len(items) else None)))))
if (len(items) == 3):
print("length is ")
print("3")
else:
print("length is ")
print("not 3")
print("end")
class haxe_iterators_ArrayIterator:
__slots__ = ("array", "current")
def __init__(self,array):
self.current = 0
self.array = array
def hasNext(self):
return (self.current < len(self.array))
def next(self):
def _hx_local_3():
def _hx_local_2():
_hx_local_0 = self
_hx_local_1 = _hx_local_0.current
_hx_local_0.current = (_hx_local_1 + 1)
return _hx_local_1
return python_internal_ArrayImpl._get(self.array, _hx_local_2())
return _hx_local_3()
class python_internal_ArrayImpl:
__slots__ = ()
@staticmethod
def _get(x,idx):
if ((idx > -1) and ((idx < len(x)))):
return x[idx]
else:
return None
class HxOverrides:
__slots__ = ()
@staticmethod
def stringOrNull(s):
if (s is None):
return "null"
else:
return s
class python_internal_MethodClosure:
__slots__ = ("obj", "func")
def __init__(self,obj,func):
self.obj = obj
self.func = func
def __call__(self,*args):
return self.func(self.obj,*args)
Main.main()
for
じゃない!…のは index in ...
でイテレートしてるからかな?まぁコードブロックはよしなにしてくれるのでありがたい。
あと HxOverrides
というのが増えてる。
気づき
- 互換性のためのイテレータコードとか入ってるけど、ロジックでは使ってない。そこは Tree-shaking されないっぽい。でもまぁイテレータなんて実際のコード書いたら100%出てくるから無駄ではないか。
- python の package manager (pyenv とか poetry とか) で Haxe を Virtualenv スコープにできたら、つよいと思う。
他の気になるポイント
- python の 3rd party library の使い方
- IDE補完力(上記ありきだと思うけど)