Fork me on GitHub
#specter
<
2018-05-19
>
sophiago00:05:58

I'm just trying to get a feel for picking out the roots by applying it to input that just uses literal variables, e.g. %1, rather than an actual literal. But having it also expand ->> is making me unsure whether I'm placing all the functions correctly. Regardless, they definitely should not be all stacked at the top in order of the transform calls like that.

nathanmarz01:05:31

it doesn't identify common roots

nathanmarz01:05:13

that snippet was just to show doing a transformation that wraps after identifying the expression to wrap

sophiago01:05:04

Okay, gotcha. I would think the way I'm recursing on it would at least update at the next level up, though. Right now they're at the top-level. I may just be confused by the expanded ->> though...

sophiago01:05:00

Yup, it's the expansion of ->> that's throwing me. I'll pay around with this and probably come back when I have something that works but seems could be more efficient. Thanks, @nathanmarz !

sophiago17:05:44

I'm still a bit confused about a navigator for this. I'm currently calling transform in multiple passes for each pattern and figure I can bypass having to find common root bindings by enforcing linearity but, e.g. (subselect TREE symbol? (selected? NAME pattern)), navigates to a vector containing the first symbol matching the pattern rather than the coll containing that symbol.

nathanmarz18:05:39

subselect navigates to the result of running select on that path

nathanmarz18:05:41

(select-any (subselect ALL :a even?) [{:a 1} {:a 2} {:a 4}])
;; => [2 4]

(transform (subselect ALL :a even?) reverse [{:a 1} {:a 2} {:a 4}])
;; => [{:a 1} {:a 4} {:a 2}]

sophiago18:05:46

Sorry, seems I misread the docs. Is there a navigator that will act like contains? on lists?

nathanmarz18:05:36

contains? doesn't work on lists

nathanmarz18:05:40

since it's not keyed

sophiago18:05:07

I know. I suppose like some

nathanmarz18:05:20

you mean something like (selected? ALL even?) ?

sophiago18:05:08

I suppose if I could replace even? with a pattern and then navigate to top-most coll containing the pattern?

sophiago18:05:46

I'm realizing using let bindings for linearity throws a wrench in that, but I should be able to figure it out. Seems easier than finding common roots.

sophiago18:05:13

I would think I could just do (collect TREE (selected? symbol? NAME pattern)) where TREE navigates to every coll, but then it just stops at the top level every time.

nathanmarz18:05:42

if TREE navigates to collections, then that selected? clause will always fail

sophiago18:05:06

Ah, well that does seem to be what's happening. You're implying I could have it navigate to every item? I was thinking maybe I should just use a zipper and then could specify relative paths once a pattern is matched.

nathanmarz18:05:12

user=> (setval (selected? symbol?) :replaced ['a 2 'b])
[a 2 b]
user=> (setval (selected? ALL symbol?) :replaced ['a 2 'b])
:replaced

sophiago18:05:27

If I can combine zipper navigators with regular ones then it would seem something like [TREE symbol? NAME pattern z/UP] might be the simplest way to do this.

sophiago18:05:22

Yup, reading now.

sophiago18:05:19

I'm just uncertain whether zipper navigators can be combined with regular ones. It'd be much easier in this case than using predfns.

sophiago18:05:46

The answer would seem to be no based on the examples

nathanmarz19:05:56

zipper navigators operate on zipper data structures

nathanmarz19:05:32

use navigators like VECTOR-ZIP and NODE to navigate in and out of zippers

sophiago19:05:44

The structure that zippers return doesn't seem to make them ideal for use with transform though. I'm having some luck with [ALL seq? (fn [x] some #(= % (symbol pattern)) x)]: on the first pass it at least matches the seq immediately above the pattern.

nathanmarz19:05:13

you generally don't navigate to a zipper data structure for the transform fn, you use NODE to navigate into the value the zipper is currently pointing at

sophiago19:05:17

If I use NODE then it again locates the pattern rather than the seq containing the pattern, though.

sophiago19:05:52

So (select [SEQ-ZIP (find-first #(= % (symbol "%"))) NODE] (list (list '% 'foo))) => [%] rather than (% foo)

sophiago19:05:46

And if I use (select [SEQ-ZIP (find-first #(= % (symbol "%"))) UP] (list (list '% 'foo))) then it's not really in a form that I can call transform on.

sophiago19:05:05

I really just want something like [TREE symbol? NAME #"%"] except navigating to the seq containing the pattern.

sophiago19:05:18

Obviously I can call ffirst on the zipper version, but that doesn't really help if I want to transform it preserving the structure it's in.

nathanmarz20:05:22

@sophiago how is [SEQ-ZIP (find-first #(= % (symbol "%"))) UP NODE] not exactly what you want?

nathanmarz20:05:32

it navigates to (% foo)

nathanmarz21:05:07

user=> (transform [SEQ-ZIP (find-first #(= % (symbol "%"))) UP NODE]
  #_=>   (fn [expr]
  #_=>     `(:wrapped ~expr))
  #_=>   '(+ 1 (% foo)))
(+ 1 (:wrapped (% foo)))

sophiago21:05:50

I think I neglected to try that combination 😕

sophiago21:05:59

One sec, I'm trying it in the transform

sophiago21:05:06

I think that's it 🙂

sophiago21:05:35

Oh, it's missing patterns inside let bindings. I knew that would be an issue when I decided on linearity

sophiago21:05:18

I think it may just work out that the bindings are at common roots as long as I call setval separately instead of from inside transform

nathanmarz21:05:05

fyi you can rewrite the transform like this:

(transform
  [SEQ-ZIP
   (find-first #(= % (symbol pattern)))
   UP
   NODE
   (transformed [TREE symbol? NAME (re-pattern pattern)]
     (fn [_] (str fresh-var)))]
  #(list `fn* [fresh-var] %)
  x)

👍 4
sophiago21:05:11

Yeah, the common roots issue is difficult and I can't get around it by using let bindings with linearity. But there's something deeper to say about what structures allow this navigator to finds them anyway and structures that cause trouble. Like I have one where a bound variable repeats and it's wrapped correctly and one where it's not. I tend to think the latter could be solved with destructuring in the example.

sophiago21:05:44

I think it actually comes down to currying. The one where it doesn't naturally find a root needs to be a binary function for map-indexed. Calling first and second after interleaving and partitioning to use plain map creates the same type of structure.