<https://youtu.be/9fhnJpCgtUw> really thought prov...
# thinking-together
g

https://youtu.be/9fhnJpCgtUw

really thought provoking talk on using pattern matching for better data transforms, and then for better debugging, and then for better core generation
i
Eve was effectively our exploration of "what would programming look like if it were only declarative data transformation? 🙂
g
oh i suspected as much
didn’t want to become known as “that guy who keeps spamming me in slack”
d
Onex is only declarative data transformation.
Anyone else here have that approach?
Of the projects circulating around this community I see - Kayia/Kaya @David Broderick @David - Hilltop @Dan Swirsky - Infusion @Bosmon - Maraca @jon - Mech @Corey That may be similar to Eve and Onex in this regard. Perhaps the authors could comment? 😄
d
In Hilltop I use blocks (order not important) to define application objects based on predefined object types. Each object definition has predefined typed attributes (including one for the object's value if it's a data-type object) which vary according to object type. The programmer assigns constant values or spreadsheet-like formulas to each attribute. As in a spreadsheet, the formulas are automatically recalculated when the value of any dependency changes. Up to this point it's FRP and declarative. However, each attribute has an optional sub-attribute that can include imperative code for determining the parent attribute's value. Thus, for example, if defining an attribute's value would require a nested formula, the programmer can instead express it imperatively (e.g., with intermediate local variables, If statements, etc.) within the sub-attribute. This code is reactive and is evaluated whenever the value of any of its dependencies changes. Each attribute also has an optional "watcher" sub-attribute that can include imperative code that is evaluated whenever the value of the parent attribute changes. This code is not reactive and can do whatever the programmer wants, including changing the values of other attributes of its parent object or of other objects.
d
OK, but what pain would be caused by enforcing declarative only, no imperative feature?
d
Or conversely, what is the downside of mostly declarative, but with a dash of imperative? I'm working on the assumption that if it's OK for spreadsheets (using VBA's imperative for custom formulas), then it's OK for my approach as I'm targeting programmers. But see https://arxiv.org/abs/1211.6781
p
d
Yup, that's it! And that's how the Object Network and Onex work.
k
Just a quick "me too" concerning rewriting approaches: my Leibniz project (https://github.com/khinsen/leibniz) is at its core a term rewriting system.
d
Onex (in so far as it will re-implement its predecessor, NetMash) is/will be a term rewriting system, more indeed than it is a pure functional language
p
For people building systems based on term rewriting, how important has knowledge of the literature been to you? Are you just motivated by the idea of TW, or have you gotten deeper into it?
d
Maybe link that post to #C5T9GPWFL ?
k
@Peter Abrahamsen I started by looking at specification languages, and found several that are based on term rewriting, in particular the OBJ family. Then I remembered that rewriting is also heavily used in computer algebra, a technology related to my intended application domains in computational science. ai ended up reading quite a bit of the literature, and found it useful.
👍 1
d
Still hoping to hear what these folk think about this thread: - Kayia/Kaya @David Broderick @David - Infusion @Bosmon - Maraca @jon - Mech @Corey
@Peter Abrahamsen What I'm doing probably doesn't fit the academic definition of term rewriting. Could you post some links to top pages on the subject?
I settled on a .. let's say "structure rewriting" programming model very early on - in the 80s. I had a brief detour to using unification instead of one-sided matching in the 90s, but went back to simpler rewrites since.
k
I just watched OP. I kept waiting for the speaker to mention SQL, but he never did. He mentioned joins several times, but not SQL. Lots of people know SQL, and while I often complain about it it does show the input and output pretty well. Why not start from SQL syntax? Original:
Copy code
(m/search game-info
  {:player (m/scan  {name ?name class ?class})
   :weapons (m/scan {:name ?weapon :allowed-classes #{?class} :standard-upgrade !upgrades})
   :stats (?weapon {:attack-power ?attack-power :upgrades [!upgrades ...]})
   :third-party (m/not #{?weapon})}
  {:name ?name
   :weapon ?weapon
   :class ?class
   :attack-power ?attack-power
   :upgrades !upgrades})
SQL on steroids:
Copy code
select {:name         player.name
        :weapon       weapons.name
        :class        player.class
        :attack-power stats.attack-power 
        :upgrades     weapons.standard-upgrade ++ stats.upgrades}
  from player, weapons, stats
  where weapons.class = player.class
    and weapon not in third-party
Not homoiconic, tho 😄
👍🏼 1
p
@Duncan Cragg Yeah, should have posted to #C5T9GPWFL but whatevs. I checked out Term Rewriting And All That from my library today. So far it’s concerned with (equational, i.e. first order) term rewriting as computation: normal forms, confluence, termination. Concepts that seemed important if I wanted to write optimizations for a compiler, say, or to prove things about programs written in a term rewriting system. It wasn’t clear to me that I needed to know much while I prototype and build simple applications.
@Kartik Agaram yeah, it would make SQL much, much more pleasant to use. Also reminds me of Datomic’s pull api
g
it’s definitely super similar to datomic pull—which, given the rise of graphql, seems to be an emerging meme
d
Well, here's the Onex version:
Copy code
{ is: game-view rule
  game: {
    players: { 
      name: *  
      class: * 
    }
    weapons: { 
      name: *
      allowed-classes: @game:players:class  
      standard-upgrade: * 
    }
    stats: { 
      @game:weapons:name: { 
        attack-power: *  
        upgrades: * 
      } 
    }
    third-party: not @game:weapons:name
  }
  results: =>
    { name: @game:players:name
      weapon: @game:weapons:name
      class: @game:players:class
      attack-power: @game:stats:(@game:weapons:name):attack-power
      upgrades: @game:weapons:standard-upgrade 
                @game:stats:(@game:weapons:name):upgrades
    }
}
Have to say the SQL one looks better. 😄
But of course Onex has Other Powers that SQL doesn't..
Onex is a distributed structure rewrite language, not a query language.
Plus I agree with Mr Meander that our approaches feel like you're looking at the actual data
k
The big difference between queries and rewriting is that rewrite rules are applied recursively, until there is no more rule that matches.
k
But that's an implementation detail? The stated goal is declarativeness, code expressing the shape of inputs and outputs. Here the memory variables actually compromise the goal. Rewrite rules need to sometimes be uncoiled in your head.
k
Recursive application makes rewriting Turing-complete. Not a detail for me.
d
well, iterative does too: applying until convergence or no more LHS matches
not a(n implementation) detail for me either!