OK I’ve fixed the spec issue, the Var issue, and the record issue.
Everything is currently on epsilon
I’ll create a release tomorrow.
@rfhayashi @borkdude Lemme know if this works with babashka @mark340 The record problem has been fixed.
@noprompt I'll take a look later today, thanks for reminding me.
I fixed a couple of issues. The latest issue I'm running into: https://github.com/noprompt/meander/issues/153
Also made this comment: https://github.com/noprompt/meander/issues/153#issuecomment-730255519
@noprompt Is it necessary that the FAIL sentinel is seqable? https://github.com/noprompt/meander/blob/f4b1a90c75a8428e77f59feb0e152216e0460a82/src/meander/match/runtime/epsilon.cljc#L20
I’ll double check. At one point it was, however, that may no longer be case.
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 .. :)Don't worry about releasing, I can test with git dep
Branch also works for me
Cool. I tend to prefer (reify)
in the place of Object
and js/Object
.
Actually, sorry, what’s the issue? 🙂
(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
reify does work for some cases, but I have to make explicit support for it on a class by class basis :/
Since it's .cljc you could also consider a :bb
branch with (Object.)
@noprompt Hmm, did you mean (reify)
as in without args? That works:
$ bb -e '(identical? (reify) (reify))'
false
TIL
Hehe. So what I should have said is “if removing the seqable stuff works then just leave it as (def FAIL (reify))
.”
yes, that would work for CLJ, CLJS and bb
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))
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.The meander version will likely be slower.
The seqable stuff is not removable it appears, however, I’m happy to support a :bb
clause.
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.unless you need the seqable to return nil on seq
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.
I have an idea…
oh wait:
(seq "")
;;=> nil
that works too.
So:
cljs.user=> (identical? (js/String. "") (js/String. ""))
false
fits the bill in all cases.user=> (identical? (list) (list))
true
user=> (identical? (with-meta (list) {}) (list))
false
user=> (identical? (with-meta (list) {}) (with-meta (list) {}))
false
😛
That works too :) You can even put some nice info in that metadata ;)
Like {:lol-is-this-a-hack? 'yes}
😂
:lol.impl.dont-look-here true
Random aside: I wonder if anyone has ever Xibit style put meta on their meta.
(with-meta x (with-meta ,,,))
I think there are metadata values with metadata. E.g. when you datafy something, the original value is stored as metadata
Meta linked list. 🙂
So, yah, the list bit does the trick.
Tests are passing.
OK I’ve pushed it up. Wanna try it?
Aren’t semantics fun?! 😄
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 bbThe code gets rid of predicates - why?
perf?
Yes.
Shaving those checks off can save a lot of time.
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 PersistentHashSetI support clojure.lang.IPersistentSet
already in bb. I'll add support for checking Seqable
as well
The set?
one looks like an oversight
Yeah, you already have SetInterface
We should probably tag @jimmy on this bit too. 🙂
Will take a look at fixing those discrepancies
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 :)I don’t think there is a clean mapping to core clojure.
Basically the goal is to make a java.lang.Iterator
and this was the easiest way to do that without porting the RT code.
isn't this iterator-seq
maybe?
No that’s a different thing.
It might be safe to just call .iterator
there.
Eh, no, cause there’s special sauce for strings, etc.
I can port it
I think that would be useful regardless of babashka, as to not rely on Clojure internals too much
After your port I will check if it works and make necessary changes to bb if needed
Done
Basically wrote
(if (instance? java.lang.Iterable coll)
(.iterator ^java.lang.Iterable coll)
(.iterator (seq coll)))
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
@noprompt Thanks.
Maybe return (iter [])
for (iter nil)
?
Oh duh
You still need a type hint here: https://github.com/noprompt/meander/commit/6f7b8265e5102ae98eb304719b884a73aef53fe3#diff-cdb266462b83e64b48c052f2f26fca6ea027e9663cce3ff64b08fc81b840e69bR16
Got it
I’m still trying to figure out the Seqable
thing.
Installed bb
… looks like it doesn’t like java.lang.Iterable
either?
That's easy to fix. Let me get back to you after I finish another (unrelated) refactor
The test script, however, doesn’t account for babashka yet
You can bang on that branch if you want. I’ve gotta take my hands off of it for a bit.
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@rfhayashi We’re (@borkdude and I) have been working back and forth on supporting bb
. There’s an issue and PR in the works.
https://github.com/noprompt/meander/issues/153#issuecomment-730255519
else I'm afraid it won't even work :)
I'm almost ready here, let me then push Iterable
I just added a :bb
clause without type hints. Feel free to adjust it.
Thank you both so much for that 🙂 I'll try to give it a go tomorrow.
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])))
I'll download your branch
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
The next issue is the 2 arg version of resolve. I'll have to fix that in sci (the interpreter backing babashka).
I'll get back to this, getting late now.