Code as data

Code as data

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

Be732ee41fd3038aa98a0a7e7b7be081?s=128

Denis Defreyne

July 05, 2018
Tweet

Transcript

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

  2. None
  3. $$$

  4. <disclaimer>

  5. $$$

  6. def total_price 200 + volume * distance end

  7. def total_price 200 + volume * distance end sum

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

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

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

    constant variable
  11. None
  12. class Sum def initialize(left, right) @left = left @right =

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

    right end end class Product def initialize(left, right) @left = left @right = right end end
  14. 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
  15. 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
  16. def price_formula Sum.new( Constant.new(200), Product.new( Variable.new(Fvolume), Variable.new(Fdistance), ) ) end

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

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

    input.fetch(@name) end end
  19. class Constant def initialize(value) @value = value end def evaluate(_input)

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

    right end def evaluate(input) @left.evaluate(input) + @right.evaluate(input) end end
  21. class Product def initialize(left, right) @left = left @right =

    right end def evaluate(input) @left.evaluate(input) * @right.evaluate(input) end end
  22. def price_formula Sum.new( Constant.new(200), Product.new( Variable.new(Fvolume), Variable.new(Fdistance), ), ) end

    
 
 

  23. 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
  24. class AbstractExpr def +(other) Sum.new(self, other) end def *(other) Product.new(self,

    other) end end
  25. class Sum < AbstractExpr # … end class Product <

    AbstractExpr # … end class Constant < AbstractExpr # … end class Variable < AbstractExpr # … end
  26. def price_formula Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance) end

  27. THE POINT

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


    
 

  29. Constant.new(200) + Variable.new(Fvolume) * Variable.new(Fdistance)
 
 
 
 + UV>

    4200 const UV> 200 * UV> 4000 var volume UV> 20 var distance UV> 200
  30. class Node def initialize(name, value, children) @name = name @value

    = value @children = children end end
  31. + UV> 4200 const UV> 200 * UV> 4000 var

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

    volume UV> 20 var distance UV> 200 Node.new("+", 4200, [const_node, product_node])
  33. + 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, [])
  34. class Variable < AbstractExpr def initialize(name) @name = name end

    def evaluate(input) Node.new( "var #{@name}", input.fetch(@name), [], ) end end
  35. class Constant def initialize(value) @value = value end def evaluate(_input)

    Node.new( 'const', @value, [], ) end end
  36. 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
  37. 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
  38. 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
  39. puts price_formula.evaluate(input)
 
 
 
 
 


  40. puts price_formula.evaluate(input) + ./> 4200 const ./> 200 * ./>

    4000 var volume ./> 20 var distance ./> 200
  41. puts price_formula.evaluate(input).value
 


  42. puts price_formula.evaluate(input).value
 
 4200

  43. + UV> 4200 const UV> 200 * UV> 4000 var

    volume UV> 20 var distance UV> 200
  44. + (= 4200) const (= 200) * (= 4000) var

    distance (= 200) var volume (= 20)
  45. IDEA: translate to SQL

  46. IDEA: compile with LLVM

  47. What about input?

  48. BACKEND

  49. BACKEND formula

  50. BACKEND PARSE + SERIALIZE formula

  51. PARSING:
 parse("200 + volume * distance") 
 
 
 


    
 
 
 
 
 

  52. PARSING:
 parse("200 + volume * distance") D> Sum.new( Constant.new(200), Product.new(

    Variable.new(Kvolume), Variable.new(Kdistance), ) )
 
 
 

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

    serialize(formula) 

  54. 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"]]
  55. BACKEND PARSE + SERIALIZE formula

  56. BACKEND PARSE + SERIALIZE DESERIALIZE + UNPARSE formula

  57. formula

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

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

  60. Is this over-engineering?

  61. TAKE-AWAYS

  62. * It’s much easier to reason about data
 than to

    reason about code. 
 

  63. * It’s much easier to reason about data
 than to

    reason about code. * Try novel approaches; they can
 reveal new opportunities.
  64. None