clj-python / libpython-clj

Python bindings for Clojure
Eclipse Public License 2.0
1.05k stars 68 forks source link

ISSUE-255: add py! macro with enhanced(?) data transformation capabilities #256

Closed jjtolton closed 8 months ago

jjtolton commented 8 months ago

"Closes": https://github.com/clj-python/libpython-clj/issues/255

(require '[libpython-clj2.sugar :refer [py!]])
(require '[libpython-clj2.python :refer [py..])
(require '[libpython-clj2.require :refer [require-python])
(require-python '[numpy :as np])
(require '[tech.v3.dataset :as ds])

(py! (python/dict {:a 1 :b 2})
     ->jvm
     (->> (repeat 3) (ds/->dataset))
     ->python
     ->jvm
     (->> vals (apply concat))
     (as-> $ (apply + $))
     (->> (repeat 10))
     (->> (partition 3))
     ->python
     (-> np/array)
     sum) ;;=> 81
(defn times-11 [n]
  (py! (python/list [1 2 3])
        __len__
        (as-> $ (+ 2 $))
        (some-> vector (get 3) (+ 3))
        (cond->
         nil?
          (conj 1))
        (-> first)
        (as-> $ (python/list [1 2 3 $ 4]))
        (->> (repeat n)
             (transduce
              (map (fn [args]
                     (apply + args)))
              (completing +)
              0))))

(- (times-11 4) 2) ;;=> 42
(py! (python/list)
     (doto
      (py.. (append 1))
      (py.. (append 1))
      (py.. (append 1)))
     (as-> $
           (cond-> $
             (< (count $) 4)
             (doto
              (py.. (append 5)))
             (< (count $) 6)
             (doto
              (py.. (append 7)))))) => [1, 1, 1, 5, 7]

:neutral_face:

jjtolton commented 8 months ago

This is a little out of control so I put it in sugar instead of py. Not sure we should be encouraging this madness. Also the cond is a little reflection heavy so there are some performance concerns there on tight loops. Great for exploration though. Also I suppose there is an infinitesimal chance that someone somewhere wrote a Python class with a .doto() method -- but I've never seen one. So I felt pretty safe adding that in.

jjtolton commented 8 months ago

Closing for now, I'm thinking this might be too out there for libpython-clj core but might be better as an ecosystem addition.