Presentation is loading. Please wait.

Presentation is loading. Please wait.

And other languages….  Writing programs that write programs (cool!)  Often used to create domain-specific languages (DSL) You’ve all heard of at least.

Similar presentations

Presentation on theme: "And other languages….  Writing programs that write programs (cool!)  Often used to create domain-specific languages (DSL) You’ve all heard of at least."— Presentation transcript:

1 and other languages…

2  Writing programs that write programs (cool!)  Often used to create domain-specific languages (DSL) You’ve all heard of at least one DSL written in Ruby. Can you guess what it is?

3 class Module private def readonly(*syms) # do nothing if no args return if syms.size == 0 # code starts as empty string code = "" # generate Ruby code to define # attr reader methods # Notice how the symbol is # interpolated into the code syms.each do |s| code << "def #{s}; @#{s}; end\n" end # use class_eval to create instance # methods class_eval code end # this method is like attr_accessor def readwrite(*syms) return if syms.size == 0 code = "" syms.each do |s| code << "def #{s}; @#{s}; end\n" code << "def #{s}=(value); @#{s} = value; end\n" end class_eval code end * from The Ruby Programming Language

4  Create a small class with a few instance variables  Use the code on the previous slide to create “setters” and “getters”  Hint: require_relative  Nothing to submit

5  Require is like include in other languages  It runs another file  Ensures it’s not required twice

6  Programming or specification language dedicated to a particular problem domain  Examples: html for web pages VHDL hardware description language Mathematica for symbolic mathematics GraphViz for graph layout YACC for creating parsers Regular expressions for lexers * from

7  Read specific_language  Read the Usage Patterns.  Read the Design Goals.  What’s the most interesting example of a DSL?

8  As defined by Martin Fowler: From: Program written in DSL Program that interprets DSL Grammar Interpretation

9 clear add 2 mult 6 sub 4 if “clear” x=0 if “add” x+= value if “sub” x-= value if “mult” x*= value

10  Also from Fowler Start with some implementation language, such as Ruby Bend that language into your DSL THE IDEA: anyone who writes a program in your small domain-specific language is actually writing a bit of Ruby – but without knowing it. What features of Ruby would make that possible?

11  Quiz program. Example interaction: From:

12  Users create their own question  BUT, we don’t parse as data… we execute! question 'Who was the first president of the USA?' wrong 'Fred Flintstone' wrong 'Martha Washington' right 'George Washington' wrong 'George Jetson' question 'Who is buried in Grant\'s tomb?' right 'U. S. Grant' wrong 'Cary Grant' wrong 'Hugh Grant' wrong 'W. T. Grant' question, right, and wrong are methods! This file is named questions.qm

13 def question(text) puts "Just read a question: #{text}" end def right(text) puts "Just read a correct answer: #{text}“ end def wrong(text) puts "Just read an incorrect answer: #{text}" end # The load command executes code! load 'questions.qm' # load is NOT the same as require! This file is questionsv1.rb

14 runs question “Who was the first president of the USA?” runs wrong “Fred Flintstone” runs wrong “Martha Washington” runs right “George Washington” Can we do this in Java? Other languages?

15  What should this quiz DSL really do? It doesn’t specify how to run a quiz It does specify the questions and related right/wrong answer – i.e., the program data.  So the question method should create a new entry in the list of questions  Then right and wrong methods set the “values” for that entry

16 require 'singleton' class Quiz include Singleton # here’s where we’ll store the questions def initialize @questions = [] end # add a question – question+right+wrong def add_question(question) @questions << question end # we sometimes need to update the last question def last_question @questions.last end end # we’ll add more in a minute This is in file quiz.rb

17  For now, let’s store it class Question #@text is the question, @answers holds all the answers def initialize( text ) @text = text @answers = [] end def add_answer(answer) @answers << answer end end # we’ll also add more here soon. Could be a separate file, but we’ll add it to quiz.rb

18  Need the answer text, also whether it is right or wrong Note: we’re mapping from two DSL statements (right and wrong) to one data type, with an attribute to distinguish class Answer attr_reader :text, :correct def initialize( text, correct ) @text = text @correct = correct end We’ll also add this class to quiz,rb

19 def question(text) # Quiz is singleton Quiz.instance.add_question end def right(text) Quiz.instance.last_question.add_answer,true) end def wrong(text) Quiz.instance.last_question.add_answer,false) end load 'questions.qm' We’ll also add these statements to quiz,rb But not in a class!

20 require './quiz.rb' require 'test/unit' class QuizTest < Test::Unit::TestCase def test_load_quiz # ensure that two questions were loaded questions = Quiz.instance.questions assert_equal(2, questions.length) # ensure that the last question has 4 answers question = Quiz.instance.last_question answers = question.answers assert_equal(4, answers.length) # check the text of the answers assert_equal("U. S. Grant", answers[0].text) assert_equal("Cary Grant", answers[1].text) assert_equal("Hugh Grant", answers[2].text) assert_equal("W. T. Grant", answers[3].text) # ensure right/wrong loaded correctly assert_equal(true, answers[0].correct) assert_equal(false, answers[1].correct) assert_equal(false, answers[2].correct) assert_equal(false, answers[3].correct) end *Ruby 1.9.3 syntax

21  In Quiz: def run_quiz count=0 @questions.each { |q| count += 1 if q.ask } puts "You got #{count} answers correct out of #{@questions.size}." end  In Question: def ask puts "" puts "Question: #{@text}" @answers.size.times do |i| puts "#{i+1} - #{@answers[i].text}" end print "Enter answer: " answer = gets.to_i - 1 return @answers[answer].correct end

22  in quiz_runner.rb: require './quiz.rb' Quiz.instance.run_quiz

23  Can use Proc to create a proc p = {|x,y| print x,y },2)  Can use instance_eval to evaluate Ruby code in the context of a given object. require 'singleton' class TryIt include Singleton def show_what n puts n end TryIt.instance_eval("TryIt.instance.show_what 22") We’ll do more of this after we study FP and Haskell!

Download ppt "And other languages….  Writing programs that write programs (cool!)  Often used to create domain-specific languages (DSL) You’ve all heard of at least."

Similar presentations

Ads by Google