SlideShare une entreprise Scribd logo
1  sur  45
Télécharger pour lire hors ligne
Una historia de DSLs
     en Ruby




      Leo Soto M.
      Continuum
      Lenguajes Dinámicos, Enero 2013

Saturday, February 9, 13
DSLs?




Saturday, February 9, 13
Muchas libs Ruby son en el fondo, DSLs




Saturday, February 9, 13
Capistrano




namespace :deploy do
  task :start, :roles => :app, :except => { :no_release => true } do
    run "sudo monit start miapp_unicorn"
    run "sudo monit -g resque start all"
  end
end




Saturday, February 9, 13
RSpec



describe Math do
  describe "#pow" do
    it "computes the n-th-power of the receiver" do
      3.pow(3).should == 27
    end
  end
end




Saturday, February 9, 13
Bundler
gem       'rails', '3.2.11'
gem       'pg'
gem       'jquery-rails'
gem       "unicorn", ">= 4.3.1"
gem       "haml", ">= 3.1.7"
gem       "devise", ">= 2.1.2"
gem       "simple_form", ">= 2.0.4"
gem       "figaro", ">= 0.5.0"
gem       "foreigner", ">= 1.3.0"


group          :assets do
  gem          'sass-rails',   '~> 3.2.3'
  gem          'compass-rails'
  gem          'coffee-rails', '~> 3.2.1'
  gem          'uglifier', '>= 1.0.3'
end




Saturday, February 9, 13
Sinatra




require 'sinatra'

get '/hi' do
  "Hello World!"
end




Saturday, February 9, 13
Routing en Rails




Saturday, February 9, 13
Modelos en Rails




Saturday, February 9, 13
Casi todo en Rails




Saturday, February 9, 13
Lo que en J__A “resuelven” con X_L
                     en Ruby se suele hacer con DSLs internos




Saturday, February 9, 13
Enter Pharmmd Rules




Saturday, February 9, 13
age	
  >=	
  18	
  and	
  (drug_cat(“XYZ”)	
  or	
  
                    	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  drug_cat(“ABC”))
                    and	
  dosage(“PARACETAMOL”)	
  >	
  1000




Saturday, February 9, 13
Solución:




Saturday, February 9, 13
# patient_dsl.rb
class PatientDSL

   attr_reader :patient

   def initialize(patient)
     @patient = patient
   end

   delegate :age, :allergies, :gender, :labs, :medications,
            :prescriptions, :providers, :visits, :survey, :to => :patient

   def drug_cat(name)
     (1..6).to_a.reverse.detect do |level|
       medication = medications.detect do |m|
         m.send("lvl#{level}conceptname") == name
       end and break medication
     end
   end

   def dosage(name)
     drug(name).try(:dosage) || 0
   end

   # Many, many more methods

end




Saturday, February 9, 13
PatientDSL.new(patient).instance_eval(rule)




Saturday, February 9, 13
Recuerden, las reglas las ingresas usuarios, en una gran
           caja de texto en la interfaz web del sistema

        ¿Que problemas pueden ocurrir con la solución hasta
                            ahora?




Saturday, February 9, 13
age	
  >=	
  18	
  and	
  patient.destroy!




Saturday, February 9, 13
Patient.destroy_all




Saturday, February 9, 13
system(“rm	
  -­‐rf	
  /”)




Saturday, February 9, 13
PatientDSL.new(patient).instance_eval(rule)




Saturday, February 9, 13
“Cuando me equivoco en tipear la regla
              me aparece un error ‘No Method no se cuantito’”




Saturday, February 9, 13
Solución, versión 2:




Saturday, February 9, 13
# pharmmd_dsl.treetop

grammar PharmmdDsl
  rule expression
    spaces? boolean_expression spaces?
  end

    rule boolean_expression
      boolean_term (spaces logical_binary_operator spaces boolean_term)*
    end

    rule logical_binary_operator
      "and" /
      "&&" /
      "or" /
      "||"
    end

    rule boolean_term
      ("not " / "!") spaces? boolean_expression /
      (numeric_value spaces? boolean_operator spaces? numeric_value) /
      ("(" boolean_expression ")") /
      function_call
    end

    # ...
Saturday, February 9, 13
# pharmmd_dsl.treetop (cont.)

    rule boolean_operator
      ">=" /
      "<=" /
      ">" /
      "<" /
      "==" /
      "!="
    end

  rule function_call
    function_name:([a-zA-Z_] [a-zA-Z_0-9]*) arguments:("(" argument
("," spaces? argument)* ")")? <FunctionNode>
  end

    rule argument
      string /
      date /
      numeric_value
    end




Saturday, February 9, 13
# pharmmd_dsl.treetop (cont.)

    rule numeric_value
      function_call /
      number /
      "(" spaces? numeric_value spaces? ")"
    end

    rule number
      float /
      integer
    end

    rule integer
      "-"? digits
    end

    rule float
      "-"? (digits)? "." digits
    end

    rule digits
      [0-9]+
    end


Saturday, February 9, 13
# pharmmd_dsl.treetop (cont.)

    rule spaces
      [sn]+
    end

    rule string
     ['"] [^'"]* ['"]
    end

    rule date
      [0-9]+ "." time_unit "s"? ".ago"
    end

    rule time_unit
      "day" /
      "month" /
      "year"
    end

end




Saturday, February 9, 13
Por cierto, el lenguaje de gramáticas de
                    treetop es un DSL “externo”




Saturday, February 9, 13
Treetop hace el parsing extremadamente natural.

                           ¡Sigamos el proceso a mano!

                           (si es que tenemos pizarra a mano)




Saturday, February 9, 13
age	
  >=	
  18	
  and	
  (drug_cat(“XYZ”)	
  or	
  
                    	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  	
  drug_cat(“ABC”))
                    and	
  dosage(“PARACETAMOL”)	
  >	
  1000




Saturday, February 9, 13
¿Pero qué ganamos?




Saturday, February 9, 13
age	
  >=	
  18	
  and	
  patient.destroy	
  #	
  invalido
      Patient.destroy_all	
  #	
  invalido
      system(“rm	
  -­‐rf	
  /”)	
  #	
  valido!




Saturday, February 9, 13
eval(“Patient.destroy_all”)	
  #	
  oops




Saturday, February 9, 13
¡Rara vez la validación sintáctica es suficiente!




“Saltarina casa llovió perros perrunos”
                             (¡Español sintácticamente válido!)




Saturday, February 9, 13
rule function_call
      function_name:([a-zA-Z_] [a-zA-Z_0-9]*)
      arguments:("(" argument ("," spaces? argument)* ")")?
      <FunctionNode>
    end




Saturday, February 9, 13
require 'treetop'; require 'pharmmd_dsl'

class FunctionNode < Treetop::Runtime::SyntaxNode; end

class PharmmdDslValidator
  attr_accessor :dsl, :errors

    def initialize(dsl)
      @dsl = dsl; @errors = []
    end

    def valid_dsl?
      parser = PharmmdDslParser.new
      parse_tree = parser.parse(@dsl)
      if parse_tree.nil?
        errors << "You have a syntax error: #{parser.failure_reason}"
      else
        validate_functions(parse_tree)
      end
      errors.empty?
    end
    def valid_functions
      @valid_functions ||=
        (PatientDSL.instance_methods - Object.instance_methods)
    end
Saturday, February 9, 13
# (cont.)

   def validate_functions(parse_tree)
     element = parse_tree
     if element.is_a? FunctionNode
       name = element.function_name.text_value
       unless valid_functions.include? name
         errors << ("Function name #{element.text_value} is not a
 valid function call")
       end
     end
     if element.elements
       parse_tree.elements.each do |element|
         validate_functions(element)
       end
     end
   end
 end




Saturday, February 9, 13
age	
  >=	
  18	
  and	
  patient.destroy	
  #	
  invalido
      Patient.destroy_all	
  #	
  invalido
      system(“rm	
  -­‐rf	
  /”)	
  #	
  invalido!




Saturday, February 9, 13
Errores amigables:
                           “Se esperaba ‘(‘ en linea X, columna Y”

                           “La función ‘system’ no es válida”




Saturday, February 9, 13
Y mucho más: ¡Solucion v3!
          (Sólo una mirada rápida, que se nos acaba el tiempo)




Saturday, February 9, 13
¡DSL híbrido!




Saturday, February 9, 13
quantity("lipitor") > 10 or drug("vicodin")

                 treetop, parse trees
                                                                  (PharmdDSLValidator)
External
  DSL


                                         quantity("lipitor") > 10 or drug("vicodin")


                                                                 (PharmdDSLPreProcessor)

                                        (quantity("lipitor") > 10).or(drug("vicodin"))
                 ruby objs/metodos




                                                                  (PharmdDSL)
Internal
  DSL




                                        (NumericExpr(20, ["Lipitor 50mg"]) > 10).or(
                                          BooleanExpr(true, ["Vicodin 20mg"]))



Saturday, February 9, 13
quantity("lipitor") > 10 or drug("vicodin")

                 treetop, parse trees
                                                                  (PharmdDSLValidator)
External
  DSL


                                         quantity("lipitor") > 10 or drug("vicodin")


                                                                 (PharmdDSLPreProcessor)

                                        (quantity("lipitor") > 10).or(drug("vicodin"))
                 ruby objs/metodos




                                                                 (DenominatorQuery)
Internal
  DSL




                                        (OrCondition(
                                          Condition('lipitor', {'$gt' => '10'}),
                                          Condition('vicodin', {'$exists' => true}))



Saturday, February 9, 13
...y mas
               MongoDB no tenía OR en esa época,
      por lo que optimizabamos el árbol de expresiones para
               dejar los ORs lo mas “arriba” posible.

                                          Ejemplo:

                                 ((X	
  or	
  Y)	
  and	
  (Z)

                                                      (Condition#optimize)

                           ((X	
  and	
  Z)	
  or	
  (Y	
  and	
  Z))
Saturday, February 9, 13
Conclusión
                     • Parsing, árboles de expresiones,
                           compiladores, etc no fue tiempo perdido en
                           la U :)
                     • Pero siempre hay tradeoffs
                     • Probar un DSL interno primero. La solución
                           más simple que podría funcionar
                     • Luego un DSL externo, treetop lo hace fácil
                     • Finalmente un híbrido, si no queda otra
Saturday, February 9, 13

Contenu connexe

Similaire à Una historia de ds ls en ruby

Standing on the shoulders of giants with JRuby
Standing on the shoulders of giants with JRubyStanding on the shoulders of giants with JRuby
Standing on the shoulders of giants with JRubyTheo Hultberg
 
Ruby new wheels_condensed
Ruby new wheels_condensedRuby new wheels_condensed
Ruby new wheels_condensedosake
 
Perl Sucks - and what to do about it
Perl Sucks - and what to do about itPerl Sucks - and what to do about it
Perl Sucks - and what to do about it2shortplanks
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitRebecca Murphey
 
Redis for the Everyday Developer
Redis for the Everyday DeveloperRedis for the Everyday Developer
Redis for the Everyday DeveloperRoss Tuck
 
Innovative Specifications for Better Performance Logging and Monitoring
Innovative Specifications for Better Performance Logging and MonitoringInnovative Specifications for Better Performance Logging and Monitoring
Innovative Specifications for Better Performance Logging and MonitoringCary Millsap
 
What did you miss in Java from 9-13?
What did you miss in Java from 9-13?What did you miss in Java from 9-13?
What did you miss in Java from 9-13?relix1988
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Kang-min Liu
 
Hidden treasures of Ruby
Hidden treasures of RubyHidden treasures of Ruby
Hidden treasures of RubyTom Crinson
 
An introduction to Raku
An introduction to RakuAn introduction to Raku
An introduction to RakuSimon Proctor
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2rubyMarc Chung
 
Stored Procedures and MUMPS for DivConq
 Stored Procedures and  MUMPS for DivConq  Stored Procedures and  MUMPS for DivConq
Stored Procedures and MUMPS for DivConq eTimeline, LLC
 
Redis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your applicationRedis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your applicationrjsmelo
 
Defensive programming in Javascript and Node.js
Defensive programming in Javascript and Node.jsDefensive programming in Javascript and Node.js
Defensive programming in Javascript and Node.jsRuben Tan
 
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013Mike Desjardins
 

Similaire à Una historia de ds ls en ruby (20)

Data Types Master
Data Types MasterData Types Master
Data Types Master
 
Standing on the shoulders of giants with JRuby
Standing on the shoulders of giants with JRubyStanding on the shoulders of giants with JRuby
Standing on the shoulders of giants with JRuby
 
Ruby new wheels_condensed
Ruby new wheels_condensedRuby new wheels_condensed
Ruby new wheels_condensed
 
Perl Sucks - and what to do about it
Perl Sucks - and what to do about itPerl Sucks - and what to do about it
Perl Sucks - and what to do about it
 
Mulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development ToolkitMulberry: A Mobile App Development Toolkit
Mulberry: A Mobile App Development Toolkit
 
Redis for the Everyday Developer
Redis for the Everyday DeveloperRedis for the Everyday Developer
Redis for the Everyday Developer
 
Innovative Specifications for Better Performance Logging and Monitoring
Innovative Specifications for Better Performance Logging and MonitoringInnovative Specifications for Better Performance Logging and Monitoring
Innovative Specifications for Better Performance Logging and Monitoring
 
Regexp Master
Regexp MasterRegexp Master
Regexp Master
 
CoffeeScript
CoffeeScriptCoffeeScript
CoffeeScript
 
What did you miss in Java from 9-13?
What did you miss in Java from 9-13?What did you miss in Java from 9-13?
What did you miss in Java from 9-13?
 
Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)Good Evils In Perl (Yapc Asia)
Good Evils In Perl (Yapc Asia)
 
Hidden treasures of Ruby
Hidden treasures of RubyHidden treasures of Ruby
Hidden treasures of Ruby
 
An introduction to Raku
An introduction to RakuAn introduction to Raku
An introduction to Raku
 
Master perl io_2011
Master perl io_2011Master perl io_2011
Master perl io_2011
 
Hacking with ruby2ruby
Hacking with ruby2rubyHacking with ruby2ruby
Hacking with ruby2ruby
 
Stored Procedures and MUMPS for DivConq
 Stored Procedures and  MUMPS for DivConq  Stored Procedures and  MUMPS for DivConq
Stored Procedures and MUMPS for DivConq
 
Redis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your applicationRedis & ZeroMQ: How to scale your application
Redis & ZeroMQ: How to scale your application
 
Defensive programming in Javascript and Node.js
Defensive programming in Javascript and Node.jsDefensive programming in Javascript and Node.js
Defensive programming in Javascript and Node.js
 
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
Rails Sojourn: One Man's Journey - Wicked Good Ruby Conference 2013
 
Dig1108 Lesson 3
Dig1108 Lesson 3Dig1108 Lesson 3
Dig1108 Lesson 3
 

Plus de Leonardo Soto

El arte oscuro de estimar v3
El arte oscuro de estimar v3El arte oscuro de estimar v3
El arte oscuro de estimar v3Leonardo Soto
 
Mapas en la web con Cloudmade
Mapas en la web con CloudmadeMapas en la web con Cloudmade
Mapas en la web con CloudmadeLeonardo Soto
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsLeonardo Soto
 
Sounds.gd lighting talk (RubyConf Uruguay)
Sounds.gd lighting talk (RubyConf Uruguay)Sounds.gd lighting talk (RubyConf Uruguay)
Sounds.gd lighting talk (RubyConf Uruguay)Leonardo Soto
 
Un tour por Java, Scala, Python, Ruby y Javascript
Un tour por Java, Scala, Python, Ruby y JavascriptUn tour por Java, Scala, Python, Ruby y Javascript
Un tour por Java, Scala, Python, Ruby y JavascriptLeonardo Soto
 
Lo que odiamos de la agilidad
Lo que odiamos de la agilidadLo que odiamos de la agilidad
Lo que odiamos de la agilidadLeonardo Soto
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Leonardo Soto
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Leonardo Soto
 
Django on Jython, PyCon 2009
Django on Jython, PyCon 2009Django on Jython, PyCon 2009
Django on Jython, PyCon 2009Leonardo Soto
 
Participando Summer of Code
Participando Summer of CodeParticipando Summer of Code
Participando Summer of CodeLeonardo Soto
 
Django, el framework web para perfeccionistas con deadlines
Django, el framework web para perfeccionistas con deadlinesDjango, el framework web para perfeccionistas con deadlines
Django, el framework web para perfeccionistas con deadlinesLeonardo Soto
 

Plus de Leonardo Soto (20)

El arte oscuro de estimar v3
El arte oscuro de estimar v3El arte oscuro de estimar v3
El arte oscuro de estimar v3
 
Caching tips
Caching tipsCaching tips
Caching tips
 
Dos Años de Rails
Dos Años de RailsDos Años de Rails
Dos Años de Rails
 
Mapas en la web con Cloudmade
Mapas en la web con CloudmadeMapas en la web con Cloudmade
Mapas en la web con Cloudmade
 
Startechconf
StartechconfStartechconf
Startechconf
 
RabbitMQ
RabbitMQRabbitMQ
RabbitMQ
 
Decent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivarsDecent exposure: Controladores sin @ivars
Decent exposure: Controladores sin @ivars
 
The Hashrocket Way
The Hashrocket WayThe Hashrocket Way
The Hashrocket Way
 
Sounds.gd lighting talk (RubyConf Uruguay)
Sounds.gd lighting talk (RubyConf Uruguay)Sounds.gd lighting talk (RubyConf Uruguay)
Sounds.gd lighting talk (RubyConf Uruguay)
 
Un tour por Java, Scala, Python, Ruby y Javascript
Un tour por Java, Scala, Python, Ruby y JavascriptUn tour por Java, Scala, Python, Ruby y Javascript
Un tour por Java, Scala, Python, Ruby y Javascript
 
Lo que odiamos de la agilidad
Lo que odiamos de la agilidadLo que odiamos de la agilidad
Lo que odiamos de la agilidad
 
Oss
OssOss
Oss
 
App Engine
App EngineApp Engine
App Engine
 
Introducción a Git
Introducción a GitIntroducción a Git
Introducción a Git
 
Tres Gemas De Ruby
Tres Gemas De RubyTres Gemas De Ruby
Tres Gemas De Ruby
 
Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)Jython: Python para la plataforma Java (EL2009)
Jython: Python para la plataforma Java (EL2009)
 
Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)Jython: Python para la plataforma Java (JRSL 09)
Jython: Python para la plataforma Java (JRSL 09)
 
Django on Jython, PyCon 2009
Django on Jython, PyCon 2009Django on Jython, PyCon 2009
Django on Jython, PyCon 2009
 
Participando Summer of Code
Participando Summer of CodeParticipando Summer of Code
Participando Summer of Code
 
Django, el framework web para perfeccionistas con deadlines
Django, el framework web para perfeccionistas con deadlinesDjango, el framework web para perfeccionistas con deadlines
Django, el framework web para perfeccionistas con deadlines
 

Dernier

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxKatpro Technologies
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptxLBM Solutions
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking MenDelhi Call girls
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAndikSusilo4
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptxHampshireHUG
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountPuma Security, LLC
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking MenDelhi Call girls
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationSafe Software
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsMemoori
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?XfilesPro
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Dernier (20)

Factors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptxFactors to Consider When Choosing Accounts Payable Services Providers.pptx
Factors to Consider When Choosing Accounts Payable Services Providers.pptx
 
Key Features Of Token Development (1).pptx
Key  Features Of Token  Development (1).pptxKey  Features Of Token  Development (1).pptx
Key Features Of Token Development (1).pptx
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 
Azure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & ApplicationAzure Monitor & Application Insight to monitor Infrastructure & Application
Azure Monitor & Application Insight to monitor Infrastructure & Application
 
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
04-2024-HHUG-Sales-and-Marketing-Alignment.pptx
 
Breaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path MountBreaking the Kubernetes Kill Chain: Host Path Mount
Breaking the Kubernetes Kill Chain: Host Path Mount
 
Pigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food ManufacturingPigging Solutions in Pet Food Manufacturing
Pigging Solutions in Pet Food Manufacturing
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men08448380779 Call Girls In Greater Kailash - I Women Seeking Men
08448380779 Call Girls In Greater Kailash - I Women Seeking Men
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
AI as an Interface for Commercial Buildings
AI as an Interface for Commercial BuildingsAI as an Interface for Commercial Buildings
AI as an Interface for Commercial Buildings
 
How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?How to Remove Document Management Hurdles with X-Docs?
How to Remove Document Management Hurdles with X-Docs?
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

Una historia de ds ls en ruby

  • 1. Una historia de DSLs en Ruby Leo Soto M. Continuum Lenguajes Dinámicos, Enero 2013 Saturday, February 9, 13
  • 3. Muchas libs Ruby son en el fondo, DSLs Saturday, February 9, 13
  • 4. Capistrano namespace :deploy do task :start, :roles => :app, :except => { :no_release => true } do run "sudo monit start miapp_unicorn" run "sudo monit -g resque start all" end end Saturday, February 9, 13
  • 5. RSpec describe Math do describe "#pow" do it "computes the n-th-power of the receiver" do 3.pow(3).should == 27 end end end Saturday, February 9, 13
  • 6. Bundler gem 'rails', '3.2.11' gem 'pg' gem 'jquery-rails' gem "unicorn", ">= 4.3.1" gem "haml", ">= 3.1.7" gem "devise", ">= 2.1.2" gem "simple_form", ">= 2.0.4" gem "figaro", ">= 0.5.0" gem "foreigner", ">= 1.3.0" group :assets do gem 'sass-rails', '~> 3.2.3' gem 'compass-rails' gem 'coffee-rails', '~> 3.2.1' gem 'uglifier', '>= 1.0.3' end Saturday, February 9, 13
  • 7. Sinatra require 'sinatra' get '/hi' do "Hello World!" end Saturday, February 9, 13
  • 8. Routing en Rails Saturday, February 9, 13
  • 9. Modelos en Rails Saturday, February 9, 13
  • 10. Casi todo en Rails Saturday, February 9, 13
  • 11. Lo que en J__A “resuelven” con X_L en Ruby se suele hacer con DSLs internos Saturday, February 9, 13
  • 13. age  >=  18  and  (drug_cat(“XYZ”)  or                                drug_cat(“ABC”)) and  dosage(“PARACETAMOL”)  >  1000 Saturday, February 9, 13
  • 15. # patient_dsl.rb class PatientDSL attr_reader :patient def initialize(patient) @patient = patient end delegate :age, :allergies, :gender, :labs, :medications, :prescriptions, :providers, :visits, :survey, :to => :patient def drug_cat(name) (1..6).to_a.reverse.detect do |level| medication = medications.detect do |m| m.send("lvl#{level}conceptname") == name end and break medication end end def dosage(name) drug(name).try(:dosage) || 0 end # Many, many more methods end Saturday, February 9, 13
  • 17. Recuerden, las reglas las ingresas usuarios, en una gran caja de texto en la interfaz web del sistema ¿Que problemas pueden ocurrir con la solución hasta ahora? Saturday, February 9, 13
  • 18. age  >=  18  and  patient.destroy! Saturday, February 9, 13
  • 22. “Cuando me equivoco en tipear la regla me aparece un error ‘No Method no se cuantito’” Saturday, February 9, 13
  • 24. # pharmmd_dsl.treetop grammar PharmmdDsl rule expression spaces? boolean_expression spaces? end rule boolean_expression boolean_term (spaces logical_binary_operator spaces boolean_term)* end rule logical_binary_operator "and" / "&&" / "or" / "||" end rule boolean_term ("not " / "!") spaces? boolean_expression / (numeric_value spaces? boolean_operator spaces? numeric_value) / ("(" boolean_expression ")") / function_call end # ... Saturday, February 9, 13
  • 25. # pharmmd_dsl.treetop (cont.) rule boolean_operator ">=" / "<=" / ">" / "<" / "==" / "!=" end rule function_call function_name:([a-zA-Z_] [a-zA-Z_0-9]*) arguments:("(" argument ("," spaces? argument)* ")")? <FunctionNode> end rule argument string / date / numeric_value end Saturday, February 9, 13
  • 26. # pharmmd_dsl.treetop (cont.) rule numeric_value function_call / number / "(" spaces? numeric_value spaces? ")" end rule number float / integer end rule integer "-"? digits end rule float "-"? (digits)? "." digits end rule digits [0-9]+ end Saturday, February 9, 13
  • 27. # pharmmd_dsl.treetop (cont.) rule spaces [sn]+ end rule string ['"] [^'"]* ['"] end rule date [0-9]+ "." time_unit "s"? ".ago" end rule time_unit "day" / "month" / "year" end end Saturday, February 9, 13
  • 28. Por cierto, el lenguaje de gramáticas de treetop es un DSL “externo” Saturday, February 9, 13
  • 29. Treetop hace el parsing extremadamente natural. ¡Sigamos el proceso a mano! (si es que tenemos pizarra a mano) Saturday, February 9, 13
  • 30. age  >=  18  and  (drug_cat(“XYZ”)  or                                drug_cat(“ABC”)) and  dosage(“PARACETAMOL”)  >  1000 Saturday, February 9, 13
  • 32. age  >=  18  and  patient.destroy  #  invalido Patient.destroy_all  #  invalido system(“rm  -­‐rf  /”)  #  valido! Saturday, February 9, 13
  • 34. ¡Rara vez la validación sintáctica es suficiente! “Saltarina casa llovió perros perrunos” (¡Español sintácticamente válido!) Saturday, February 9, 13
  • 35. rule function_call function_name:([a-zA-Z_] [a-zA-Z_0-9]*) arguments:("(" argument ("," spaces? argument)* ")")? <FunctionNode> end Saturday, February 9, 13
  • 36. require 'treetop'; require 'pharmmd_dsl' class FunctionNode < Treetop::Runtime::SyntaxNode; end class PharmmdDslValidator attr_accessor :dsl, :errors def initialize(dsl) @dsl = dsl; @errors = [] end def valid_dsl? parser = PharmmdDslParser.new parse_tree = parser.parse(@dsl) if parse_tree.nil? errors << "You have a syntax error: #{parser.failure_reason}" else validate_functions(parse_tree) end errors.empty? end def valid_functions @valid_functions ||= (PatientDSL.instance_methods - Object.instance_methods) end Saturday, February 9, 13
  • 37. # (cont.) def validate_functions(parse_tree) element = parse_tree if element.is_a? FunctionNode name = element.function_name.text_value unless valid_functions.include? name errors << ("Function name #{element.text_value} is not a valid function call") end end if element.elements parse_tree.elements.each do |element| validate_functions(element) end end end end Saturday, February 9, 13
  • 38. age  >=  18  and  patient.destroy  #  invalido Patient.destroy_all  #  invalido system(“rm  -­‐rf  /”)  #  invalido! Saturday, February 9, 13
  • 39. Errores amigables: “Se esperaba ‘(‘ en linea X, columna Y” “La función ‘system’ no es válida” Saturday, February 9, 13
  • 40. Y mucho más: ¡Solucion v3! (Sólo una mirada rápida, que se nos acaba el tiempo) Saturday, February 9, 13
  • 42. quantity("lipitor") > 10 or drug("vicodin") treetop, parse trees (PharmdDSLValidator) External DSL quantity("lipitor") > 10 or drug("vicodin") (PharmdDSLPreProcessor) (quantity("lipitor") > 10).or(drug("vicodin")) ruby objs/metodos (PharmdDSL) Internal DSL (NumericExpr(20, ["Lipitor 50mg"]) > 10).or( BooleanExpr(true, ["Vicodin 20mg"])) Saturday, February 9, 13
  • 43. quantity("lipitor") > 10 or drug("vicodin") treetop, parse trees (PharmdDSLValidator) External DSL quantity("lipitor") > 10 or drug("vicodin") (PharmdDSLPreProcessor) (quantity("lipitor") > 10).or(drug("vicodin")) ruby objs/metodos (DenominatorQuery) Internal DSL (OrCondition( Condition('lipitor', {'$gt' => '10'}), Condition('vicodin', {'$exists' => true})) Saturday, February 9, 13
  • 44. ...y mas MongoDB no tenía OR en esa época, por lo que optimizabamos el árbol de expresiones para dejar los ORs lo mas “arriba” posible. Ejemplo: ((X  or  Y)  and  (Z) (Condition#optimize) ((X  and  Z)  or  (Y  and  Z)) Saturday, February 9, 13
  • 45. Conclusión • Parsing, árboles de expresiones, compiladores, etc no fue tiempo perdido en la U :) • Pero siempre hay tradeoffs • Probar un DSL interno primero. La solución más simple que podría funcionar • Luego un DSL externo, treetop lo hace fácil • Finalmente un híbrido, si no queda otra Saturday, February 9, 13