meander

All things about https://github.com/noprompt/meander Need help and no one responded? Feel free to ping @U5K8NTHEZ
wilkerlucio 2021-04-13T01:51:27.113Z

if I have a structure of data that has a bunch of attributes that are optional, what’s the best way to express this in the current meander epsilon?

noprompt 2021-04-13T21:04:01.120200Z

Yes. The reason epsilon and prior versions have never had m/or on the right side was because I did not have a notion of “substitution failure”. In the near future, for rewriting, it will be legal to use m/or on the right and relax restrictions on variables needing to be bound. If you use a variable on the right side which is was not bound then that will fail.

(m/rewrite [1]
  [?x & (m/or [?y ?z] _)]
  [?x (m/or ?y 2) (m/or ?z 3)])
;; =>
[1 2 3]

noprompt 2021-04-13T21:05:41.120400Z

To me, this makes sense because, in practice, the time we actually care about a variable being unbound is when we need to “use” it.

noprompt 2021-04-13T21:06:17.120600Z

And people sort of do this kind of thing all the time with nil except the semantics of failure is rather ad-hoc.

noprompt 2021-04-13T21:16:25.120800Z

So here we get something that feels both dynamic and static. Dynamic in the sense that we can build things we accept and return different shapes of data, and static in the sense that these constraints provide some very nice properties in exchange for giving up some control.

noprompt 2021-04-13T21:18:27.121Z

I’m inspired by Haskell and Peyton Jones: steadily growing the language to accept more and more programs without compromising on core value propositions.

wilkerlucio 2021-04-13T21:27:34.121200Z

sounds great, looking forward to it 👍

wilkerlucio 2021-04-13T01:51:36.113100Z

this is my example:

{:address {:zipCode      ?zipcode
           :city         ?city
           :stateAcronym ?state-abbr
           :state        ?state
           :streetNumber ?street-number
           :street       ?street
           :complement   ?address-complement
           :point        {:lon ?lon
                          :lat ?lat}
           :confidence   ?address-confidence
           :neighborhood ?neighborhood
           :country      ?country-abbr}}

wilkerlucio 2021-04-13T01:51:59.113300Z

right side:

{:listing/zipcode            ?zipcode
 :listing/city               ?city
 :listing/state-abbr         ?state-abbr
 :listing/state              ?state
 :listing/street-number      ?street-number
 :listing/street             ?street
 :listing/address-complement ?address-complement
 :geo.point/lon              ?lon
 :geo.point/lat              ?lat}

wilkerlucio 2021-04-13T01:53:19.113500Z

in my case, every attribute match there is optional, is this an applicable usage? and if so, how should I do it?

noprompt 2021-04-13T02:23:29.114Z

Without being too assumptive about your goals, I will say that for a situation like this, if you’re used to the destructure first ask questions later approach, then it’ll feel frustrating.

noprompt 2021-04-13T02:27:21.114200Z

Probably the best tool for situations like this would be m/search where each clause addresses a particular concern.

wilkerlucio 2021-04-13T02:27:21.114400Z

the goal is to extract the information I can find, if my assumption is right that meander is caring a lot about matching all, these would be the opposite, a more relaxed way to do “match whatever you can”, and them nullify everything else (that can’t be matched), makes sense?

noprompt 2021-04-13T02:28:09.114600Z

Yes, for this situation, I recommend using m/search where each clause can be as strict or as loose as you want.

wilkerlucio 2021-04-13T02:29:52.114800Z

I think I don’t understand m/search well enough, can you show me what it looks like? (with my address template for example)

noprompt 2021-04-13T02:31:01.115100Z

Yeah. I’ll make a quick example but then I have to drop and take care of my kids. If my example doesn’t help, you can leave me some more requirements and I will try and reply in a couple hours. One second.

wilkerlucio 2021-04-13T02:31:22.115300Z

(from the docs I understand search returns many outputs, in my case I still want a single map on the output)

wilkerlucio 2021-04-13T02:31:34.115500Z

no worries, whenever you have the time, thanks 👍

wilkerlucio 2021-04-13T02:38:07.115800Z

I’m playing with search to try it out, this looks good:

(m/search {:a 1}
    {:a ?a :b ?b :c ?c}
    [?a ?b ?c])
=> ([1 nil nil])

wilkerlucio 2021-04-13T02:38:56.116Z

but if the query goes a bit deeper like:

(m/search {:a 1}
    {:a ?a :b [?b]  :c ?c}
    [?a ?b ?c])
=> nil
Then I got just nil

wilkerlucio 2021-04-13T02:40:02.116200Z

similar to matching nested maps, if the parent is there its ok (even if the map is only partially matched):

(m/search {:a 1 :c {:d "d"}}
    {:a ?a :b ?b :c {:d ?d :e ?e}}
    [?a ?b ?d ?e])
=> ([1 nil "d" nil])

wilkerlucio 2021-04-13T02:40:30.116400Z

but goes nil if :c is out:

(m/search {:a 1}
    {:a ?a :b ?b :c {:d ?d :e ?e}}
    [?a ?b ?d ?e])
=> nil

wilkerlucio 2021-04-13T02:41:22.116600Z

I can totally understand if my case is out of scope, but what I’m looking for is something that can just ignore everything that can’t be matched, and just return whatever was possible to match, hope these examples can help to understand the situation 🙏

noprompt 2021-04-13T02:43:22.116900Z

Sorry, I keep getting interrupted by kids but here’s a silly example of what I meant.

(let [address {:zipCode "12345"}]
  (into {:point? false
         :zip-code? false}
        (me/search address
          {:point {:lon _, :lat _}}
          [:coordinates? true]

          {:zipCode (me/pred string? ?zip)}
          [:zip-code? true])))
;; =>
{:point? false, :zip-code? true}
(I’m using me as the my alias instead of m). But the idea is to search for what you’re looking and if you’re making a map then the right sides return pairs.

wilkerlucio 2021-04-13T02:43:48.117100Z

I just got to this code here too 🙂

(m/search {:a 1 :b [3]}
    {:a ?a} {:aa ?a}

    {:b [?b]} {:bb ?b}
    
    {:c {:d ?d :e ?e}} {:dd ?d :ee ?e})

wilkerlucio 2021-04-13T02:44:15.117700Z

cool, I think makes sense

wilkerlucio 2021-04-13T02:44:31.117900Z

thanks!

noprompt 2021-04-13T02:45:16.118100Z

NP. This would probably be a good thing to stick in the cookbook.

👍 4
noprompt 2021-04-13T02:47:48.118400Z

You can use this approach in different ways, validation is one example where you can return a sequence of errors, etc.

noprompt 2021-04-13T02:49:56.118600Z

Anyway, if you have more questions ask them here or in the main channel. Also, I’m keen to hear your frustrations as well. I’ve been working on the next version of the library and I’m trying to address all of the negative feedback, pain, and suffering I’ve gotten over the years. 🙂

wilkerlucio 2021-04-13T02:50:48.118800Z

no worries, I found meander one of the most amazing things to data transformation, really great job here!

wilkerlucio 2021-04-13T02:51:30.119Z

I love the clarity of being able to look at the source and target structures in a simple way, and excited for the next gen that’s is coming 🙂

👍 1
noprompt 2021-04-13T02:54:55.119200Z

Me too! 😅 The support from folks in this channel has been inspiring.

wilkerlucio 2021-04-13T02:56:40.119400Z

I believe you saw you saying something about allowing (m/or) in the right side for the next version, I guess with that I would be able to just put m/or in each output option to solve this case, did I get it right?