meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
jose 2020-11-19T10:54:49.318500Z

Very interesting work to support babahska. Related to that, what is the current status of compiling a meander application with graalvm? It would be nice to use meander in a clojure compiled app. I didn't test it, but I suspect that currently, a clojure app will fail to compile if it depends on meander. But I also suspect that the changes to support babashka will help in compiling meander with graalvm.

borkdude 2020-11-19T10:56:54.318900Z

@jlle I'm not sure why it would fail in GraalVM, I don't see any obstacles

borkdude 2020-11-19T10:57:20.319300Z

I haven't tried and I'm not deeply familiar with the code.

borkdude 2020-11-19T10:59:03.321300Z

It's not hard to try it out though. Here is a small CLI: https://github.com/borkdude/puget-cli which should easily be changed to run a meander example.

jose 2020-11-19T11:02:23.322600Z

@borkdude maybe not, I didn't try myself neither. I supposed that if it fails with babashka, the compilation with graalvm will fail too, but I can easily be wrong

jose 2020-11-19T11:02:52.322900Z

Thanks for the suggestion, I don't have the time right now, but definitely I'll try to compile meander

borkdude 2020-11-19T11:05:34.324700Z

Babashka uses sci which is a Clojure interpreter which you can compile with GraalVM. Running code through sci is not the same as directly compiling it with GraalVM. Some things are support in one and not in the other and vice versa.

👍 1
jose 2020-11-19T11:08:22.324800Z

I see, good to know, I assumed that if some code runs in babashka, it will compile with graalvm

borkdude 2020-11-19T11:09:02.325100Z

One example: you cannot execute functions that use clojure.core/eval with graalvm, because eval needs compilation.

borkdude 2020-11-19T11:09:10.325300Z

But you can do this with sci.

borkdude 2020-11-19T11:09:31.325500Z

But some things like deftype, etc are not support in sci.

dominicm 2020-11-19T18:38:06.327300Z

Obviously term rewriting is good for direct optimizations. But if I had a constraint on size, and had to prevent certain things from nesting, I'm guessing that's out of bounds for term rewriting?

noprompt 2020-11-19T19:01:13.327800Z

@dominicm I don’t think that is necessarily true but maybe a little more context?

dominicm 2020-11-19T19:02:11.329100Z

@noprompt I'm thinking of writing a clojure minifier, because reasons.

dominicm 2020-11-19T19:02:37.330200Z

So can't nest #(#()) for example.

borkdude 2020-11-19T19:03:05.331200Z

@dominicm I'm working on extracting the uberscript functionality from babashka so it also works for JVM. Together with carve (cut out unused vars) this is also a kind of minifier.

noprompt 2020-11-19T19:03:16.331500Z

I’m thinking, for example, a pair of a peano number indicating the depth and the term

[0 ?term] = ?term
[(s ?nat) ?term] = (recur [?nat ?term*])

noprompt 2020-11-19T19:04:00.332100Z

> because reasons @dominicm sounds like how I arrived 🙂

noprompt 2020-11-19T19:05:01.333200Z

@borkdude I’m trying to grind out this interpreter code patch as fast as I can to try out.

noprompt 2020-11-19T19:05:48.334200Z

TBH, I could probably remove a lot of the internal use of match which is one part suck and another part not.

borkdude 2020-11-19T19:06:08.334500Z

sounds exciting :)

noprompt 2020-11-19T19:06:20.335Z

It would definitely improve the load time for every one.

borkdude 2020-11-19T19:08:28.338700Z

What's the use case and what are some of things you are thinking about?

dominicm 2020-11-19T19:09:23.340400Z

I'm thinking of building a code golfer, and this feels like a fair addition. Maybe it's not though. But it's no fun to be beaten by your colleague who strategically added #() after seeing your solution.

😆 1
noprompt 2020-11-19T19:09:27.340700Z

I’ve tried to speed up the compilation of the macros but at some point I’m comfortable with prioritizing the speed of the runtime code over the compiler speed. At the point is where the interpreter should fit in.

dominicm 2020-11-19T19:09:36.341200Z

Fun :)

noprompt 2020-11-19T19:09:37.341400Z

I am quite interesting Graal FWIW.

👍 1
noprompt 2020-11-19T19:10:36.342900Z

I’m interested to see how well the interpreter runs once the partial evaluation magic kicks in.

noprompt 2020-11-19T19:11:07.343600Z

Code golf is a young mans game. 😛

borkdude 2020-11-19T19:11:36.344300Z

There is an open issue for clj-kondo that would help LSP find locals for renaming. This could also be used for renaming locals to minify code

borkdude 2020-11-19T19:11:46.344700Z

e.g. rename foobar to F

markaddleman 2020-11-19T19:12:05.345100Z

Tangentially related to this discussion: I often use cata as a subroutine of sorts. When I do this, I've adopted an idiom along the lines of

(m/rewrite something
   ?n
   (m/cata {::number !n})

   [!n ...]
   [(m/cata {::number !n}) ...]

   {::number (m/pred number? ?n)}
   blah-blah)
I vaguely remember a conversation in this channel saying that this is a pretty common idiom and that meander might adopt first-class support for it. I'm just curious to follow up on that

noprompt 2020-11-19T19:12:32.345200Z

I need to find the time to look into these cool things. Long time fan of LSP though I’ve never made the time to put it to use in Emacs.

noprompt 2020-11-19T19:13:10.345400Z

Good place to stick rewriting.

borkdude 2020-11-19T19:13:11.345600Z

https://github.com/borkdude/clj-kondo/issues/982

borkdude 2020-11-19T19:14:11.346Z

@noprompt Also check out https://github.com/borkdude/carve for deleting unused vars.

noprompt 2020-11-19T19:19:58.346400Z

Do you remember what was connected to that? I vaguely remember that but my memory these days, eh, is bad.

markaddleman 2020-11-19T19:28:45.346600Z

heh I sympathize

markaddleman 2020-11-19T19:28:55.346800Z

No, I don't recall much else about the conversation.

markaddleman 2020-11-19T19:29:18.347Z

It is not a big issue for me.

markaddleman 2020-11-19T19:30:49.347200Z

I imagine that direct support could yield better runtime performance but my use case is not performance sensitive

noprompt 2020-11-19T19:39:00.347400Z

cata compilation will get better in time. I’m just barely starting to get time in my life back for hacking on Meander.

noprompt 2020-11-19T19:39:16.347600Z

The paste few months have been hard on me.

markaddleman 2020-11-19T19:46:04.347800Z

I'm sorry. I hope you don't take my comments as critical. Meander has been a HUGE boon to my productivity and I appreciate all your efforts

noprompt 2020-11-19T19:49:58.348Z

> I hope you don’t take my comments as critical Not at all! 🙂

noprompt 2020-11-19T19:50:55.348200Z

I love this project, this channel, and the little community of we’ve established here around this stuff. I like making people happy and get sad when I can’t. 🙂

markaddleman 2020-11-19T19:53:15.348400Z

In general, the Clojure community is very friendly. Meander community is even more so 🙂

noprompt 2020-11-19T21:04:39.349100Z

OK I’m like 80% done with an initial interpreter worthy of kicking around.

dominicm 2020-11-19T21:06:06.349700Z

So just 80% left to go? :)

noprompt 2020-11-19T21:06:49.350Z

LOL

noprompt 2020-11-19T21:07:46.350700Z

I just meant that I have a rough draft that is sturdy enough to use at your own risk. 🙂

noprompt 2020-11-19T21:08:09.351100Z

I’m trying to minimize the at your own risk part as a courtesy, however. 😂

noprompt 2020-11-19T22:08:50.351400Z

(ns scratch
  (:require [meander.interpreter.epsilon :as m]))

(def search-a
  (m/searcher
   '(m/re #"(.)(.)(.)" (m/and [?0 ?1 ?2 ?2] [!0 ...]))
   (fn [{:syms [?0 !0]}]
     [?0 !0])

   '(m/re #"f(.*)" [!0 ?0 . !0 ...])
   (fn [{:syms [?0 !0]}]
     [?0 !0])))
  
(search-a "foo")
;; => (["foo" ["foo" "f" "o" "o"]] ["oo" ["foo"]])
(search-a "foe")
;; => (["oe" ["foe"]])

noprompt 2020-11-19T22:09:05.351600Z

Seems like this could work

noprompt 2020-11-19T22:09:16.351800Z

What do y’all think?

noprompt 2020-11-19T23:40:46.352500Z

JHOLDBRO-M-C65T.jholdbro=> rlwrap bb --classpath src
Babashka v0.2.3 REPL.
Use :repl/quit or :repl/exit to quit the REPL.
Clojure rocks, Bash reaches.

user=> (require '[meander.interpreter.epsilon :as m])
nil
user=> (def s1 (m/searcher '(m/re #"f(.)(.)" [_ ?x ?x]) #(get % '?x)))
#'user/s1
user=> (s1 "foo")
("o")
user=> (s1 "faa")
("a")
user=> (s1 "f11")
("1")
@borkdude works

noprompt 2020-11-19T23:42:28.353Z

It appears to be very fast.

❌ 1
noprompt 2020-11-19T23:45:12.353400Z

Well, sort of.

noprompt 2020-11-19T23:45:47.353700Z

;; Clojure
(with-out-str (time (dotimes [_ 10000] (doall (search-a "foe")))))
"\"Elapsed time: 253.965799 msecs\"\n"
;; Babashka
(with-out-str (time (dotimes [_ 10000] (doall (search-a "foe")))))
"\"Elapsed time: 3284.494238 msecs\"\n

noprompt 2020-11-19T23:46:02.353900Z

Not sure what’s going on here.

noprompt 2020-11-19T23:47:13.354200Z

;; Clojure
(with-out-str (time (doall (search-a "foe"))))
"\"Elapsed time: 0.012454 msecs\"\n"
;; Babashka
(with-out-str (time (doall (search-a "foe"))))
"\"Elapsed time: 0.814953 msecs\"\n"

noprompt 2020-11-19T23:55:08.356Z

In terms of performance, for this example, interpretation is going to be slower over all, however, it’s also going to be more flexible.

(defn search-b [s]
  (me/search s
    (me/re #"(.)(.)(.)" (me/and [?0 ?1 ?2 ?2] [!0 ...]))
    [?0 !0]

    (me/re #"f(.*)" [!0 ?0 . !0 ...])
    [?0 !0]))

[(with-out-str (time (dotimes [_ 10000] (doall (search-a "foe")))))
 (with-out-str (time (dotimes [_ 10000] (doall (search-b "foe")))))]
;;=>
["\"Elapsed time: 120.945113 msecs\"\n"
 "\"Elapsed time: 15.265521 msecs\"\n"]

noprompt 2020-11-19T23:56:09.356600Z

It’s likely possible to close that gap on this a bit using, say, an approach similar to Egison.

noprompt 2020-11-19T23:57:42.357600Z

Or using ye olde matrix style pattern matching compilation but, of course, to functions instead of code.

noprompt 2020-11-19T23:59:11.358100Z

Variables would need to have their names changed to protect the innocent.