Fork me on GitHub
#meander
<
2020-11-18
>
noprompt07:11:13

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

noprompt07:11:38

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

noprompt17:11:06

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

🙏 3
borkdude17:11:52

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

👍 3
noprompt18:11:43

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

borkdude18:11:11

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 .. :)

borkdude18:11:56

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

borkdude18:11:12

Branch also works for me

noprompt18:11:01

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

noprompt18:11:52

Actually, sorry, what’s the issue? 🙂

borkdude19:11:29

(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

borkdude19:11:29

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

borkdude19:11:09

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

borkdude19:11:09

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

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

noprompt19:11:40

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

borkdude19:11:28

yes, that would work for CLJ, CLJS and bb

noprompt19:11:18

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

borkdude19:11:54

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.

borkdude19:11:27

unless you need the seqable to return nil on seq

noprompt19:11:45

I have an idea…

borkdude19:11:52

oh wait:

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

noprompt19:11:59

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

borkdude19:11:08

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

noprompt19:11:39

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

borkdude19:11:07

:lol.impl.dont-look-here true

noprompt19:11:34

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

noprompt19:11:15

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

borkdude19:11:43

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

noprompt19:11:13

Meta linked list. 🙂

noprompt19:11:48

So, yah, the list bit does the trick.

noprompt19:11:56

Tests are passing.

noprompt19:11:05

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

noprompt19:11:31

Aren’t semantics fun?! 😄

borkdude19:11:14

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

borkdude19:11:40

The code gets rid of predicates - why?

noprompt20:11:47

Shaving those checks off can save a lot of time.

borkdude20:11:15

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

borkdude20:11:35

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

noprompt20:11:42

The set? one looks like an oversight

borkdude20:11:23

Yeah, you already have SetInterface

noprompt20:11:29

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

jimmy20:11:27

Will take a look at fixing those discrepancies

noprompt20:11:05

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

borkdude20:11:29

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 :)

noprompt20:11:35

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

noprompt20:11:01

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

borkdude20:11:03

isn't this iterator-seq maybe?

noprompt20:11:20

No that’s a different thing.

noprompt20:11:03

It might be safe to just call .iterator there.

noprompt20:11:03

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

noprompt20:11:44

I can port it

borkdude20:11:43

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

borkdude20:11:10

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

noprompt20:11:15

Basically wrote

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

borkdude21:11:08

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

borkdude21:11:55

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

noprompt21:11:22

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

noprompt21:11:19

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

borkdude21:11:00

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

noprompt21:11:49

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

noprompt21:11:27

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

borkdude21:11:25

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

borkdude21:11:33

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

borkdude21:11:47

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

noprompt21:11:29

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

borkdude21:11:58

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])))

borkdude21:11:29

I'll download your branch

borkdude22:11:54

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

borkdude22:11:33

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

borkdude22:11:42

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

borkdude09:11:47

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

mac19:11:48

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))

noprompt19:11:24

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.

noprompt19:11:19

The meander version will likely be slower.

noprompt19:11:44

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.

noprompt21:11:27

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

rfhayashi21:11:05

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