Changed subject line. This is far from original topic.
What's wrong with using @? If I understand correctly, it's used for matrix multiplication, which is far enough from function composition to avoid confusion. And it's slightly similar visually to a circle.
I like @. Function composition is kinda-sorta enough like for product that I can even make sense of the same operator.
But how would you go about getting a .__matmul__ attribute onto all functions. For ones you write yourselves, you could decorate them at definition. What about all the other functions though. I suppose this is possible:
@compasable
def foo(x):
return x + "foo"
len = composable(len)
newfun = len @ foo @ str.upper
nbar = newfun("bar") # 6
I deliberately didn't decorate str.upper in the example since it shouldn't matter for a left-associative operator.