meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
noprompt 2020-11-18T07:06:13.284500Z

OK I’ve fixed the spec issue, the Var issue, and the record issue.

noprompt 2020-11-18T07:06:38.284900Z

Everything is currently on epsilon I’ll create a release tomorrow.

noprompt 2020-11-18T17:35:14.285300Z

https://clojars.org/meander/epsilon

noprompt 2020-11-18T17:36:06.286300Z

@rfhayashi @borkdude Lemme know if this works with babashka @mark340 The record problem has been fixed.

🙏 1
borkdude 2020-11-18T17:59:52.286800Z

@noprompt I'll take a look later today, thanks for reminding me.

👍 1
borkdude 2020-11-19T09:44:47.314700Z

I fixed a couple of issues. The latest issue I'm running into: https://github.com/noprompt/meander/issues/153

borkdude 2020-11-19T09:47:43.315100Z

Also made this comment: https://github.com/noprompt/meander/issues/153#issuecomment-730255519

noprompt 2020-11-18T18:46:43.287700Z

I’ll double check. At one point it was, however, that may no longer be case.

borkdude 2020-11-18T18:49:11.287900Z

Ok, if not, could make it just an Object

(identical? (js/Object.) (js/Object.)) ;;=> false
I could support this (reify of ISeqable) in bb but if I don't have to .. :)

borkdude 2020-11-18T18:49:56.288200Z

Don't worry about releasing, I can test with git dep

borkdude 2020-11-18T18:50:12.288400Z

Branch also works for me

noprompt 2020-11-18T18:55:01.288600Z

Cool. I tend to prefer (reify) in the place of Object and js/Object.

noprompt 2020-11-18T18:55:52.289200Z

Actually, sorry, what’s the issue? 🙂

borkdude 2020-11-18T19:00:29.289400Z

(reify ISeqable ...)
doesn't work. Since FAIL is just some unique value to indicate failure, I wondered if this was really necessary to be a seqable. You could also just make it ::whatever or Object

borkdude 2020-11-18T19:01:29.289700Z

reify does work for some cases, but I have to make explicit support for it on a class by class basis :/

borkdude 2020-11-18T19:02:09.289900Z

Since it's .cljc you could also consider a :bb branch with (Object.)

borkdude 2020-11-18T19:27:09.290100Z

@noprompt Hmm, did you mean (reify) as in without args? That works:

$ bb -e '(identical? (reify) (reify))'
false

borkdude 2020-11-18T19:28:04.290500Z

TIL

noprompt 2020-11-18T19:29:40.292200Z

Hehe. So what I should have said is “if removing the seqable stuff works then just leave it as (def FAIL (reify)).”

borkdude 2020-11-18T19:33:28.293600Z

yes, that would work for CLJ, CLJS and bb

2020-11-18T19:34:48.294Z

I have this function in plain Clojure. Out of curiosity, what would be the meander equivalent? I feel it should be straight forward, but I have not found a concise solution using meander.

(defn replace-value [data]
  (clojure.walk/prewalk
   #(if (:a %)
      (assoc % :a (:b %))
      %) data))

noprompt 2020-11-18T19:37:24.295400Z

You could use the strategy namespace combining top-down and rewrite.

(m*/top-down
  (m*/rewrite
   {:a (m/or false nil), :b ?b & ?m}
   {:a ?b & ?m}))
but, honestly, what you have is probably fine.

noprompt 2020-11-18T19:39:19.296500Z

The meander version will likely be slower.

noprompt 2020-11-18T19:40:18.296600Z

The seqable stuff is not removable it appears, however, I’m happy to support a :bb clause.

borkdude 2020-11-18T19:43:54.297900Z

This works as well:

user=> (identical? (String. "FAIL") (String. "FAIL"))
false
cljs.user=> (identical? (js/String. "FAIL") (js/String. "FAIL"))
false
The string object is unique and seqable.

borkdude 2020-11-18T19:44:27.298600Z

unless you need the seqable to return nil on seq

noprompt 2020-11-18T19:45:44.299700Z

If you need it to be quicker, you’ll need to ditch both prewalk and avoid top-down . These traversals indiscriminately hit everything and 99% of that’s a waste.

noprompt 2020-11-18T19:46:45.300Z

I have an idea…

borkdude 2020-11-18T19:46:52.300200Z

oh wait:

(seq "")
;;=> nil
that works too. So:
cljs.user=> (identical? (js/String. "") (js/String. ""))
false
fits the bill in all cases.

noprompt 2020-11-18T19:47:59.300500Z

user=> (identical? (list) (list))
true
user=> (identical? (with-meta (list) {}) (list))
false
user=> (identical? (with-meta (list) {}) (with-meta (list) {}))
false

noprompt 2020-11-18T19:48:01.300700Z

😛

borkdude 2020-11-18T19:49:08.300900Z

That works too :) You can even put some nice info in that metadata ;)

noprompt 2020-11-18T19:49:39.301100Z

Like {:lol-is-this-a-hack? 'yes}

noprompt 2020-11-18T19:49:59.301500Z

😂

borkdude 2020-11-18T19:50:07.301700Z

:lol.impl.dont-look-here true

noprompt 2020-11-18T19:51:34.301900Z

Random aside: I wonder if anyone has ever Xibit style put meta on their meta.

noprompt 2020-11-18T19:52:15.302200Z

(with-meta x (with-meta ,,,))

borkdude 2020-11-18T19:52:43.302400Z

I think there are metadata values with metadata. E.g. when you datafy something, the original value is stored as metadata

noprompt 2020-11-18T19:53:13.302600Z

Meta linked list. 🙂

noprompt 2020-11-18T19:53:48.302800Z

So, yah, the list bit does the trick.

noprompt 2020-11-18T19:53:56.303Z

Tests are passing.

noprompt 2020-11-18T19:55:05.303200Z

OK I’ve pushed it up. Wanna try it?

noprompt 2020-11-18T19:55:31.303400Z

Aren’t semantics fun?! 😄

borkdude 2020-11-18T19:59:14.303600Z

I'm now running into another Seqable reference:

user=> (require '[meander.epsilon] :reload)
Could not resolve symbol: clojure.lang.Seqable [at /Users/borkdude/.gitlibs/libs/meander/epsilon/7ed07ce8766aa5fbf7d457bdeffe39e2e1323f73/src/meander/match/ir/epsilon.cljc:851:31]
Maybe I'll just have to bite the bullet and add it to bb

borkdude 2020-11-18T19:59:40.303800Z

The code gets rid of predicates - why?

borkdude 2020-11-18T19:59:44.304Z

perf?

noprompt 2020-11-18T20:07:16.304200Z

Yes.

noprompt 2020-11-18T20:07:47.304400Z

Shaving those checks off can save a lot of time.

borkdude 2020-11-18T20:12:15.304600Z

This isn't exactly the same though:

#'clojure.core/seqable? clojure.lang.Seqable
E.g. strings are seqable, but they are not clojure.lang.Seqable set? checks for IPersistentHashSet but you map it to PersistentHashSet

borkdude 2020-11-18T20:13:35.304800Z

I support clojure.lang.IPersistentSet already in bb. I'll add support for checking Seqable as well

noprompt 2020-11-18T20:13:42.305Z

The set? one looks like an oversight

borkdude 2020-11-18T20:15:23.305300Z

Yeah, you already have SetInterface

noprompt 2020-11-18T20:16:29.305500Z

We should probably tag @jimmy on this bit too. 🙂

jimmy 2020-11-18T20:18:27.305700Z

Will take a look at fixing those discrepancies

noprompt 2020-11-18T20:19:05.305900Z

@jimmy No pressure. I’m hacking away at them as @borkdude brings stuff up. I just wanted to tag you on the thread.

borkdude 2020-11-18T20:21:29.306100Z

The next thing I'm running into:

user=> (require '[meander.epsilon] :reload)
Could not resolve symbol: clojure.lang.RT/iter [at /Users/borkdude/.gitlibs/libs/meander/epsilon/7ed07ce8766aa5fbf7d457bdeffe39e2e1323f73/src/meander/substitute/runtime/epsilon.cljc:11:12]
Don't know what the normal Clojure function is for this, but you might want to add a :bb branch for this. Note that :bb branches have to go before :clj branches, else bb will take the :clj branch :)

noprompt 2020-11-18T20:39:35.306300Z

I don’t think there is a clean mapping to core clojure.

noprompt 2020-11-18T20:43:01.306500Z

Basically the goal is to make a java.lang.Iterator and this was the easiest way to do that without porting the RT code.

borkdude 2020-11-18T20:45:03.306800Z

isn't this iterator-seq maybe?

noprompt 2020-11-18T20:46:20.307Z

No that’s a different thing.

noprompt 2020-11-18T20:48:03.307200Z

It might be safe to just call .iterator there.

noprompt 2020-11-18T20:49:03.307400Z

Eh, no, cause there’s special sauce for strings, etc.

noprompt 2020-11-18T20:49:44.307600Z

I can port it

borkdude 2020-11-18T20:55:43.307800Z

I think that would be useful regardless of babashka, as to not rely on Clojure internals too much

borkdude 2020-11-18T20:56:10.308Z

After your port I will check if it works and make necessary changes to bb if needed

noprompt 2020-11-18T20:57:02.308200Z

Done

noprompt 2020-11-18T20:57:15.308400Z

Basically wrote

(if (instance? java.lang.Iterable coll)
  (.iterator ^java.lang.Iterable coll)
  (.iterator (seq coll)))

borkdude 2020-11-18T21:01:08.309Z

Feedback:

(set! *warn-on-reflection* true)

(defn iter [coll]
  (if (instance? java.lang.Iterable coll)
    (.iterator ^java.lang.Iterable coll)
    (.iterator ^java.lang.Iterable (seq coll))))

(prn (iter []))
(prn (iter "x")) ;; needs type hint on seq
(prn (iter nil)) ;; needs fixing

2020-11-18T21:01:37.309200Z

@noprompt Thanks.

borkdude 2020-11-18T21:01:55.309300Z

Maybe return (iter []) for (iter nil) ?

noprompt 2020-11-18T21:02:09.309500Z

Oh duh

noprompt 2020-11-18T21:09:21.309900Z

Got it

noprompt 2020-11-18T21:19:22.310100Z

I’m still trying to figure out the Seqable thing.

noprompt 2020-11-18T21:21:19.310300Z

Installed bb… looks like it doesn’t like java.lang.Iterable either?

borkdude 2020-11-18T21:22:00.310500Z

That's easy to fix. Let me get back to you after I finish another (unrelated) refactor

noprompt 2020-11-18T21:42:17.310700Z

https://github.com/noprompt/meander/pull/154

noprompt 2020-11-18T21:42:49.311Z

The test script, however, doesn’t account for babashka yet

noprompt 2020-11-18T21:45:27.311200Z

You can bang on that branch if you want. I’ve gotta take my hands off of it for a bit.

borkdude 2020-11-18T21:46:25.312400Z

This is a better way to write it for bb:

(defn iter [coll]
  (if (instance? java.lang.Iterable coll)
    (.iterator ^java.lang.Iterable coll)
    (.iterator ^java.lang.Iterable (seq coll))))
since it actually uses the type hint

noprompt 2020-11-18T21:46:27.312600Z

@rfhayashi We’re (@borkdude and I) have been working back and forth on supporting bb. There’s an issue and PR in the works.

borkdude 2020-11-18T21:46:33.312700Z

else I'm afraid it won't even work :)

borkdude 2020-11-18T21:46:47.312900Z

I'm almost ready here, let me then push Iterable

noprompt 2020-11-18T21:47:29.313100Z

I just added a :bb clause without type hints. Feel free to adjust it.

2020-11-18T21:48:05.313500Z

Thank you both so much for that 🙂 I'll try to give it a go tomorrow.

borkdude 2020-11-18T21:53:58.313700Z

I now pushed a commit to bb master where this should work:

(defn iter [coll]
  (if (instance? java.lang.Iterable coll)
    (.iterator ^java.lang.Iterable coll)
    (let [s (or (seq coll) [])]
      (.iterator ^java.lang.Iterable s))))
Also added a unit test for it:
(= [1 2 3] (iterator-seq (iter [1 2 3])))

borkdude 2020-11-18T21:54:29.313900Z

I'll download your branch

borkdude 2020-11-18T22:05:54.314100Z

iter is fixed now on babashka master. Note that you can download binaries from #babashka_circleci_builds or simply from the builds on Github, if you want to try the binary version. The next issue I'll just mention on Github

borkdude 2020-11-18T22:09:33.314300Z

The next issue is the 2 arg version of resolve. I'll have to fix that in sci (the interpreter backing babashka).

borkdude 2020-11-18T22:09:42.314500Z

I'll get back to this, getting late now.