Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code as data

Code as data

Given at RUG::B’s July 2018 edition (http://www.rug-b.de/topics/code-as-data-606).

Denis Defreyne

July 05, 2018
Tweet

More Decks by Denis Defreyne

Other Decks in Technology

Transcript

  1. CODE AS DATA
    DENIS DEFREYNE / RUG-.B / 2018-07-05

    View full-size slide

  2. def total_price
    200 + volume * distance
    end

    View full-size slide

  3. def total_price
    200 + volume * distance
    end
    sum

    View full-size slide

  4. def total_price
    200 + volume * distance
    end
    sum
    product

    View full-size slide

  5. def total_price
    200 + volume * distance
    end
    sum
    product
    variable

    View full-size slide

  6. def total_price
    200 + volume * distance
    end
    sum
    product
    constant
    variable

    View full-size slide

  7. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    end

    View full-size slide

  8. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    end
    class Product
    def initialize(left, right)
    @left = left
    @right = right
    end
    end

    View full-size slide

  9. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    end
    class Product
    def initialize(left, right)
    @left = left
    @right = right
    end
    end
    class Constant
    def initialize(value)
    @value = value
    end
    end

    View full-size slide

  10. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    end
    class Product
    def initialize(left, right)
    @left = left
    @right = right
    end
    end
    class Constant
    def initialize(value)
    @value = value
    end
    end
    class Variable
    def initialize(name)
    @name = name
    end
    end

    View full-size slide

  11. def price_formula
    Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Fvolume),
    Variable.new(Fdistance),
    )
    )
    end

    View full-size slide

  12. input = {
    volume: 20,
    distance: 200,
    }
    price_formula.evaluate(input)

    View full-size slide

  13. class Variable
    def initialize(name)
    @name = name
    end
    def evaluate(input)
    input.fetch(@name)
    end
    end

    View full-size slide

  14. class Constant
    def initialize(value)
    @value = value
    end
    def evaluate(_input)
    @value
    end
    end

    View full-size slide

  15. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    def evaluate(input)
    @left.evaluate(input) + @right.evaluate(input)
    end
    end

    View full-size slide

  16. class Product
    def initialize(left, right)
    @left = left
    @right = right
    end
    def evaluate(input)
    @left.evaluate(input) * @right.evaluate(input)
    end
    end

    View full-size slide

  17. def price_formula
    Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Fvolume),
    Variable.new(Fdistance),
    ),
    )
    end



    View full-size slide

  18. def price_formula
    Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Fvolume),
    Variable.new(Fdistance),
    )
    )
    end
    def price_formula
    Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance)
    end

    View full-size slide

  19. class AbstractExpr
    def +(other)
    Sum.new(self, other)
    end
    def *(other)
    Product.new(self, other)
    end
    end

    View full-size slide

  20. class Sum < AbstractExpr
    # …
    end
    class Product < AbstractExpr
    # …
    end
    class Constant < AbstractExpr
    # …
    end
    class Variable < AbstractExpr
    # …
    end

    View full-size slide

  21. def price_formula
    Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance)
    end

    View full-size slide

  22. Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance)








    View full-size slide

  23. Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance)




    + UV> 4200
    const UV> 200
    * UV> 4000
    var volume UV> 20
    var distance UV> 200

    View full-size slide

  24. class Node
    def initialize(name, value, children)
    @name = name
    @value = value
    @children = children
    end
    end

    View full-size slide

  25. + UV> 4200
    const UV> 200
    * UV> 4000
    var volume UV> 20
    var distance UV> 200

    View full-size slide

  26. + UV> 4200
    const UV> 200
    * UV> 4000
    var volume UV> 20
    var distance UV> 200
    Node.new("+", 4200, [const_node, product_node])

    View full-size slide

  27. + UV> 4200
    const UV> 200
    * UV> 4000
    var volume UV> 20
    var distance UV> 200
    Node.new("+", 4200, [const_node, product_node])
    Node.new("var volume", 20, [])

    View full-size slide

  28. class Variable < AbstractExpr
    def initialize(name)
    @name = name
    end
    def evaluate(input)
    Node.new(
    "var #{@name}",
    input.fetch(@name),
    [],
    )
    end
    end

    View full-size slide

  29. class Constant
    def initialize(value)
    @value = value
    end
    def evaluate(_input)
    Node.new(
    'const',
    @value,
    [],
    )
    end
    end

    View full-size slide

  30. class Sum
    def initialize(left, right)
    @left = left
    @right = right
    end
    def evaluate(input)
    left_node = @left.evaluate(input)
    right_node = @right.evaluate(input)
    Node.new(
    '+',
    left_node.value + right_node.value,
    [left_node, right_node],
    )
    end
    end

    View full-size slide

  31. class Product
    def initialize(left, right)
    @left = left
    @right = right
    end
    def evaluate(input)
    left_node = @left.evaluate(input)
    right_node = @right.evaluate(input)
    Node.new(
    '*',
    left_node.value * right_node.value,
    [left_node, right_node],
    )
    end
    end

    View full-size slide

  32. class Node
    def to_s
    "#{@name} UV> #{@value}\n" +
    @children.map { |c| indent(c.to_s) }.join('')
    end
    private
    def indent(s)
    s.lines.map { |l| ' ' + l }.join('')
    end
    end

    View full-size slide

  33. puts price_formula.evaluate(input)






    View full-size slide

  34. puts price_formula.evaluate(input)
    + ./> 4200
    const ./> 200
    * ./> 4000
    var volume ./> 20
    var distance ./> 200

    View full-size slide

  35. puts price_formula.evaluate(input).value


    View full-size slide

  36. puts price_formula.evaluate(input).value


    4200

    View full-size slide

  37. + UV> 4200
    const UV> 200
    * UV> 4000
    var volume UV> 20
    var distance UV> 200

    View full-size slide

  38. +
    (= 4200)
    const
    (= 200)
    *
    (= 4000)
    var distance
    (= 200)
    var volume
    (= 20)

    View full-size slide

  39. IDEA: translate to SQL

    View full-size slide

  40. IDEA: compile with LLVM

    View full-size slide

  41. What about input?

    View full-size slide

  42. BACKEND formula

    View full-size slide

  43. BACKEND
    PARSE +
    SERIALIZE
    formula

    View full-size slide

  44. PARSING:

    parse("200 + volume * distance")










    View full-size slide

  45. PARSING:

    parse("200 + volume * distance")
    D> Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Kvolume),
    Variable.new(Kdistance),
    )
    )




    View full-size slide

  46. SERIALIZING:
    formula =
    Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Fvolume),
    Variable.new(Fdistance),
    )
    )
    serialize(formula)

    View full-size slide

  47. SERIALIZING:
    formula =
    Sum.new(
    Constant.new(200),
    Product.new(
    Variable.new(Fvolume),
    Variable.new(Fdistance),
    )
    )
    serialize(formula)
    D> ["sum", ["constant", 200], ["product",
    ["var", "volume"], ["var", "distance"]]

    View full-size slide

  48. BACKEND
    PARSE +
    SERIALIZE
    formula

    View full-size slide

  49. BACKEND
    PARSE +
    SERIALIZE
    DESERIALIZE
    + UNPARSE
    formula

    View full-size slide

  50. formula A (stable)
    formula B (testing)

    View full-size slide

  51. formula A (old)
    formula B (stable)

    View full-size slide

  52. Is this over-engineering?

    View full-size slide

  53. * It’s much easier to reason about data

    than to reason about code.


    View full-size slide

  54. * It’s much easier to reason about data

    than to reason about code.
    * Try novel approaches; they can

    reveal new opportunities.

    View full-size slide