Skip to content

Instantly share code, notes, and snippets.

@niquola
Last active November 2, 2020 15:56
Show Gist options
  • Save niquola/de9abfeb14071038a38d588191431246 to your computer and use it in GitHub Desktop.
Save niquola/de9abfeb14071038a38d588191431246 to your computer and use it in GitHub Desktop.

sem(antic)p(atc)h

semantic diff/patch library.

Key features:

  • user defined diff schemas (vector as set, vector with key)
  • user defined conflict resolution in patch (last right win, author priorities)
  • good default settiings
  1. Keep old value in a diff for safe patch
{:a 1} => {:a 2}
{:a [::change 1 2]}

{:a 1} => {}
{:a [::delete 1]}

{:b {:a 1} :rest 2} => {:b {:a 2} :rest 2}
{:b {:a [::change 1 2]}}

``

2. Use schema for semantic of diff/patcch


```clj
{:a {:type ::set, :schema {...}}}
{:a [1 2]} => {:a [1 3]}
{:a [::set [::conj 3]
           [::disj 2]]}


{:a {:type ::key :key :system, :schema {...}}}
{:a [{:system "phone" :value 1} {:system "fax" :value 2}]} => {:a [{:system "fax" :value 2}]}
{:a [::key [::match {:system "fax"} [::patch {:value [::change 1 2]}]]
           [::match {:system "phone"} [::delete {:system "phone" :value 1}]]]}
(diff schema old new) => diff
(patch old diff {::safe? boolean})

Pluggable custom conflict resolution and differs

Basic operations

patch

Apply patch recursively

[::patch <patch-expression>]

change

[::change old-value new-value]

While patch in ::safe mode check old-value

delete

[::delete old-value]

While patch in ::safe mode check old-value

set (conj, disj)

If schema :type ::set produce set semantic operatiions

[::set [::conj 1 2] [::disj 3 4]]

key

If schema :type = ::key inerpret collection as map by key In safe mode verfy assumption for only one key per collectio

[::key
  [::match {:key "value1"} [::patch ...]]
  [::match {:key "value2"} [::delete ...]]]

https://github.com/PawelStroinski/pabloware.diff

=> (require '[pabloware.diff :as p])

=> (def band
     {:id     1
      :name   "Esbjörn Svensson Trio"
      :active {:from 1993}
      :genres #{:jazz :instrumental-music}
      :albums [{:title "When Everyone Has Gone", :year  1993}
               {:title "EST Plays Monk"          :year  1996}]})

=> (-> band
       (dissoc :id)
       (assoc-in [:active :to] 2008)
       (update :genres conj :bepop)
       (update :albums conj {:title "Winter in Venice", :year 1997}))

=> (p/diff band *1)
{:id     ::p/-
 :active {:to 2008}
 :genres #{:bepop}
 :albums [::p/+ {:title "Winter in Venice", :year 1997}]}

=> (= *2 (p/patch band *1))
true

https://github.com/lambdaisland/deep-diff2

(ddiff/diff {:a 1 :b 2} {:a 1 :b 3})

{:a 1, :b #lambdaisland.deep_diff.diff.Mismatch{:- 2, :+ 3}}

https://github.com/google/diff-match-patch

https://neil.fraser.name/writing/diff/myers.pdf

sempatch

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment