Now that I think of it OpenCV is actually a good example of a library that benefits. Most of their APIs take a numpy array and return a new one
Technically the or operator already has Symantec meaning “l” as in apply OR to both images
So overriding that breaks your ability to do that if you override that in the numpy class
You can do intermediate assignment to variables but in OpenCV that causes memory copies meaning you get the same result but at the cost of more memory especially if you don’t use same intermediate variable
OpenCV settled on adding a final argument for most of their APis that allows you to do the maths in place.
Numpy itself has also had to do the same thing.
Which can kind of be clunky to do as a result most people reach for the easier to write in Python but terrible for performance option of using operators or temporary variables
Theoretically let’s say we added this operator of |>
It could allow numpy and openCV to actually be able to know you want to do an operation in-place and allow for optimizations that just aren’t possible with current langauge design without special arguments in functions, dedicated more performant functions which do same thing as operator or just wrapping the code in your own class which does these things
For example take this
import cv2
import numpy as np
# Load image
img = cv2.imread('image.jpg')
# OpenCV copies: every operation returns a new array
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
dilated = cv2.dilate(edges, np.ones((3, 3), np.uint8), iterations=1)
# NumPy copy
brightened += dilated
brightness += 60
cv2.imshow("With Copies", brightened)
cv2.waitKey(0)
cv2.destroyAllWindows()
Easy to read but the user has been making copy of the images each time
The only way you can currently indicate you want it in place is like so
import cv2
import numpy as np
# Load image (copy so we can reuse original)
img = cv2.imread('image.jpg')
in_place = img.copy()
# OpenCV in-place: some functions support a 'dst' argument
gray = cv2.cvtColor(in_place, cv2.COLOR_BGR2GRAY)
# Overwriting original variable, still reuses memory after gray
cv2.GaussianBlur(gray, (5, 5), 0, dst=gray) # In-place blur
cv2.Canny(gray, 50, 150, dst=gray) # In-place Canny
cv2.dilate(gray, np.ones((3, 3), np.uint8), iterations=1, dst=gray) # In-place dilate
# NumPy in-place: modify gray directly
np.add(gray, 50, out=gray, casting="unsafe") # In-place pixel boost
cv2.imshow("In-Place", gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
So @pf_moore this would be one thing you can’t really do in a fully explicit way in current language design that feature could unlock
You can find ways to chain with current language even if it’s clunky and therefore people may not use until the syntax is more useful (or maybe they will)
But you cannot hint to a library you want to do an in-place operation. Instead library has to decide on some kind of convention for doing this
With a funnel operator that could unlock that
img = cv2.imread("image.jpg")
result = img \
|> cv2.cvtColor(_, cv2.COLOR_BGR2GRAY) \
|> cv2.GaussianBlur((5, 5), 0) \
|> cv2.Canny(50, 150) \
|> cv2.dilate(np.ones((3, 3), np.uint8), iterations=1) \
|> np.add(50, casting='unsafe')
Whilst the code is more or less the same and we can argue about if it’s more or less readable or not
What is maybe harder to argue about is that this would allow the library to determine that the user is chaining operations and therefore should be doing in-place optimizations when possible which right now require the user to learn that there is an entirely separate way to use these libraries
Potentially this is what would justify this addition ? Basically the ability to specify a “explicit in-place pipeline”
But apart from that I would broadly agree that a pipe function is probably a better place to focus on than syntax