Introduktion till Ruby TDP007 Konstruktion av datorspråk Föreläsning 1 Peter Dalenius Institutionen för datavetenskap 2015-01-19 Översikt över dagens föreläsning • Vad går kursen ut på? • Hur kommer vi arbeta? • schemat i grova drag • förutsättningar för laborationer och seminarier • Introduktion till programspråket Ruby Övergripande frågor • Hur konstruerar man ett datorspråk? • Vad är ett datorspråk egentligen? • Varför skulle man vilja konstruera ett nytt språk? • Hur vet man om ett språk är bättre än ett annat? Lärandemål • Förklara och använda reguljära uttryck • Använda verktyg för hantering av uppmärkningsspråk (t.ex. XML) • Använda och modifiera en tolk för ett enklare programspråk • Redogöra för och tillämpa grundläggande principer för design av datorspråk Kursens upplägg • Introduktion till Ruby • Strukturerad text och XML • Domänspecifika språk och parsning • Alternativa beräkningsmodeller och constraint propagation Arbetssätt • För var och en av kursens fyra delar: • föreläsningar • laborationer • inlämning av uppgifter (hårda deadlines!) • förberedelser inför seminarier (kort tid!) • seminarium (obligatorisk närvaro!) Laborationer inför seminarierna • Uppgifterna finns på kurswebben under Seminarier. • Labbassistent: Torbjörn Lönnemark. Labbar i Studio IP1. • Labbar genomförs i slumpmässigt hopsatta par. (Se indelning i Webreg.) • Se till att få kontakt med din labbpartner så snart som möjligt! • Uppgifterna skickas in via hemsidan senast en viss deadline. • Förutom svar på uppgifterna ska även enhetstester och en utvecklarblogg bifogas. Utvecklarblogg • Reflektioner kring hur det är att lära sig ett nytt språk (Ruby): • • • • • Hur har ni gått tillväga för att lära er Ruby? Vilka fel och misstag har ni gjort under tiden? Vad finns det för nya konstruktioner i Ruby som ni inte sett förut? Vad finns det för konstruktioner som ni känner igen men som ser lite annorlunda ut? Finns det något som ni irriterar er på eller tycker om i Ruby? • Reflektioner kring de olika tekniker som ni stöter på: • • • Hur användbart verkar detta vara? Hur lätt/svårt är det att sätta sig in i? Har ni hittat alternativa källor för att ta reda på nya saker? • Dokumentation av hur ni har tänkt när ni arbetat fram era lösningar: • • • Vad arbetade ni med (i grova drag) vid varje labbpass? Hur har ni tolkat uppgiften? Vad var svårt eller lätt med uppgiften? Seminarier • Förbered opposition av annan grupps lösningsförslag • Utvalda grupper presenteras vid seminariets början • Opposition i labbpar: • presentation av lösningen i grova drag • kommentarer kring tolkning av uppgiften och användning av tekniker • kommentarer kring kodningsstil, tester och utvecklarblogg • Obligatorisk närvaro vid seminarier! Varje labbpar opponerar minst en gång, antagligen två. Seminarieschema • v.5 onsdag 28/1 8-10 • v.7 onsdag 11/2 8-10 • v.9 onsdag 25/2 10-12 • v.11 måndag 9/3 13-15 Deadline för inlämning är två dagar innan seminariet kl 24.00. Examination • Labbar och seminarier utgör den ena delen av kursen (LAB1, 2hp) • Duggor och/eller tenta utgör den andra delen av kursen (DAT1, 4hp) och ligger till grund för individuellt betyg. • Två duggor, två timmar vid dator, två gånger under kursen. Om man inte blir godkänd finns en fyratimmars datortenta efter kursen. Tidigare utvärderingar och förändringar 12 År Betyg Förändringar som gjordes efter kursen 2014 4,00 Inga större förändringar 2013 4,46 Inga större förändringar 2012 3,78 Inga större förändringar 2011 4,29 Ny uppgift inför seminarie 3 2010 3,91 Bättre instruktioner angående enhetstester och utvecklarbloggar 2009 3,50 Förtydligande av ett flertal seminarieuppgifter 2008 2,69 Byte av lärare, delvis andra typer av tentauppgifter Några fler detaljer • Kurslitteratur: Programming Ruby 1.9 & 2.0 av Dave Thomas • Läs instruktioner på kursens webbsidor! Introduktion till Ruby • Hur man startar och använder Ruby. • En icke heltäckande snabbgenomgång av några utvalda detaljer i Ruby. Ruby • konstruerades 1993 av japanen Yukihiro "Matz" Matsumoto. • är ett objektorienterat språk med influenser från bl. a. Perl, Smalltalk, Eiffel, Ada och Lisp. • är interpreterat. • har kommit att bli ett populärt språk, inte minst tack vare webbramverket Ruby on Rails. www.ruby-lang.org Hur man använder Ruby • I våra Linux-PUL finns Ruby 1.9 förinstallerat och kan startas direkt. • Man kan komma åt interpretatorn på i princip två olika sätt: • Starta interaktiv Ruby med kommandot irb • Kör Ruby-interpretator via Emacs med M-x run-ruby om man är i Ruby-läge Interaktiv Ruby irb(main):001:0> Hello! => nil irb(main):002:0> => 19 irb(main):003:0> irb(main):004:1> irb(main):005:1> => nil irb(main):006:0> => 29 puts "Hello!" 14+5 def fun(a) a+2 end fun(27) Starta med irb --simple-prompt för en mindre ”pratig” prompt. Ruby via Emacs Ruby som scriptspråk zaza9 <1> cat hello.rb #!/bin/env ruby –w puts ”Hello, world!” zaza9 <2> hello.rb Hello, world! zaza9 <3> Övning • Starta en Ruby-intepretator och testa lite enkel Ruby-kod: • irb • Lägg till Ruby-inställningar i Emacs genom att lägga till följande rader i inställningsfilen .emacs • (nconc load-path ’(”/home/TDP007/www-pub/material/ruby-1.9-emacs”)) • (require ’ruby-site) • Starta Emacs och därefter en Ruby-interpretator inifrån Emacs, antingen med menyn Ruby Run Ruby eller med C-c C-s. (Funkar bara om man är i ”Ruby-läge”, d.v.s. om man har öppnat en Rubyfil.) Testa lite enkel Ruby-kod. Allting i Ruby är objekt Uttryck Resultat 7.class (3.14).class (3.14).round Fixnum Float 3 ′gurka′.length ′gurka′.class ′krämen växer′.gsub(′r′, ′j′) ′banan′.gsub(′a′, ′ur′).length 5 String ′kjämen växej′ 7 [′apa′, ′banan′, ′lime′].length [′apa′, ′banan′, ′lime′].reverse 3 [′lime′, ′banan′, ′apa′] 1.+(2) 1+2 3 3 Klasser och arv Basklass class Person def initialize(name) @name = name end Underklass class Matz < Person def initialize super(′Yukihiro Matsumoto′) end end def greet "Hello, my name is #{@name}." end end >> brian = Person.new(’Brian’) => #<Person:0x1a3760 @name=”Brian”> >> puts brian.greet Hello, my name is Brian. => nil >> puts Matz.new.greet Hello, my name is Yukihiro Matsumoto. => nil Exempel på grundläggande syntax def multi_foo(count = 3) ’foo’ * count end Metoder definieras med def och argumenten kan ha defaultvärden. >> multi_foo(4) => ”foofoofoofoo” >> puts ”Hello, world!” Hello, world! => nil Man kan utelämna parenteser runt argument, om det inte blir tvetydigt. >> => >> => ’This is #{multi_foo(2)}.’ ”This is #{multi_foo(2)}.” ”This is #{multi_foo(2)}.” ”This is foofoo.” Konstanta strängar som definierats med dubbelt citationstecken kan innehålla undantag med programkod. Mer om namngivning och syntax • Variabler, metoder: i, max_count, db_connect • Konstanter: MAX_AGE, LAST_THING • Klasser: StudentList, ResultThing • Instansvariabler: @name, @last_time • Klassvariabler: @@lookup_table • Globala variabler: $glob, $1, $count • Symboler: :name, :age Arrayer >> => >> => >> => >> => >> => >> => >> => >> => >> => >> => [3, ’little', ”pigs"].join(' ') "3 little pigs" a = Array.new [] a << 'some' << 'things' << 'appendend' ["some", "things", "appendend"] a[1] "things" a[0] = 17 17 a [17, "things", "appendend"] Array.new(5,0) [0, 0, 0, 0, 0] a = Array.new(2, 'Kalle') ["Kalle", "Kalle"] a[0] << ' Karlsson' "Kalle Karlsson" a ["Kalle Karlsson", "Kalle Karlsson"] Exempel på array Skapa en array Åtkomst av enskilda element Array med defaultvärden Se upp med vad det är du pushar! Arrayer som stackar eller köer print 'Array as stack: ' stack = Array.new() stack.push('a') stack.push('b') stack.push('c') print stack.pop until stack.empty? print "\n" print 'Array as queue: ' queue = Array.new() queue.push('a').push('b').push('c') print queue.shift until queue.empty? Array as stack: cba Array as queue: abc => nil Arrayen kan användas både som en stack och som en kö, beroende på vilka metoder man använder. Hashtabeller >> => >> => h1={'one'=>1, 'two'=>2, 'three'=>3} {"three"=>3, "two"=>2, "one"=>1} h1['one'] 1 Med hashtabeller kan man enkelt slå upp information. >> => >> => >> => >> => h2=Hash.new {} h2['gemstone']='ruby' "ruby" h2['fruit']='banana' "banana" h2 {"gemstone"=>"ruby", "fruit"=>"banana"} Hur man skapar en hash och fyller den med innehåll. >> => >> => h2={:june=>'perl', :july=>'ruby'} {:july=>"ruby", :june=>"perl"} h2[:july] "ruby" Ofta används symboler som nycklar. Block och iteratorer En metod kan ta ett block som argument. Ett block är en bit kod som även innehåller den aktuella omgivningen. En iterator är en metod som tar ett block och kör det för varje element i t.ex. en array. >> ['i', 'am', 'a', 'donkey'].each do | entry | print entry, ' ' end i am a donkey => ["i", "am", "a", "donkey"] >> => >> => >> => fac = 1 1 1.upto(5) do | i | fac *= i end 1 fac 120 >> [1, 2, 3, 4, 5].map { | entry | entry * entry } => [1, 4, 9, 16, 25] >> (0..100).inject(0) { | result, entry | result + entry } => 5050 Olika sätt att skriva block [1,2,3,4,5].each do | e | puts e end [1,2,3,4,5].map { | e | e * e } Använd block med do … end när sidoeffekterna (t.ex. utskrift) är det viktiga, eller när koden upptar flera rader. Använd block med { … } när returvärdet är det viktiga. Hur man skriver egna iteratorer def f(count, &block) value = 1 1.upto(count) do | i | value = value * i block.call(i, value) end end f(5) do | i, f_i | puts "f(#{i}) = #{f_i}" end f(1) = 1 f(2) = 2 f(3) = 6 f(4) = 24 f(5) = 120 => nil Blocket anges som sista argument och föregås av &. Blocket anropas med metoden call. Blocket kan sparas undan class Repeater def initialize(&block) @block = block @count = 0 end def repeat @count += 1 @block.call(@count) end end repeater = Repeater.new do | count | puts "You called me #{count} times" end 3.times do repeater.repeat end Blocket anges som argument till konstruktorn och sparas i en instansvariabel. Blocket körs genom att anropa repeat, vilket också ökar på räknaren. Tilldelning >> => >> => a=4 4 a=b=4 4 >> => >> => >> => file=File.open('c:\prov.txt') #<File:c:\prov.txt> linecount=0 0 linecount+=1 while (line=file.gets) nil >> => >> => a+=2 6 a=a+2 8 >> a,b=b,a => [4, 8] >> => >> => array=[1,2] [1, 2] a,b=*array [1, 2] En tilldelning returnerar alltid det tilldelade värdet, vilket gör att man kan koppla ihop dem. Tilldelningar kan användas som villkorsuttryck. Det finns genvägar för enkla tilldelningar. Parallell tilldelning Uppdelning av array Villkor if (1 + 1 == 2) "Like in school." else "What a surprise!" end Normal villkorssats "Like in school." if (1 + 1 == 2) "Surprising!" unless (1 + 1 == 2) Villkoret efter ett uttryck (1 + 1 == 2) ? ’Working’ : ’Defect’ Snabbval spam_probability = rand(100) case spam_probability when 0...10 then "Lowest probability" when 10...50 then "Low probability" when 50...90 then "High probability" when 90...100 then "Highest probability" end Flera alternativ Endast nil och false är falska, alla andra värden är sanna, inklusive konstanten true. Upprepning while (i<10) i*=2 end i*=2 while (i<100) begin i*=2 end while (i<100) Normal upprepning med test innan Upprepning efter uttryck Upprepning med test efter i*=2 until (i>=1000) loop do break i if (i>=4000) i*=2 end Uthopp ur loop vid godtycklig punkt 4.times do i*=2 end Iterator r=[] for i in 0..7 next if i%2==0 r<<i end Upprepning med for, samt överhoppning av vissa varv (0..7).select { |i| i%2!=0 } Klassdefinitioner class Cell def initialize @state = :empty end end class Board def initialize(width, height) @width = width; @height = height @cells = Array.new(height) { Array.new(width) { Cell.new } } end end Åtkomst av egenskaper class Cell def state @state end end class Cell def state=(new_state) @state=new_state end end class Cell attr_reader :state end class Cell attr_writer :state end class Board def size self.width * self.height end end class Cell attr_accessor :state end Array-liknande åtkomstmetoder class Board def [](col, row) @cells[col][row] end end >> => >> => >> => board = Board.new(8, 8) #<Board:... @height=8...> board[0, 0] #<Cell:... @state=:e...> board[0, 0] = Cell.new() #<Cell:... @state=:e...> class Board def []=(col, row, cell) @cells[col][row] = cell end end >> => >> => >> => >> => >> => board = Board.new(8, 8) #<Board:... @height=8...> board[0, 0] #<Cell:... @state=:e...> board[0, 0] = Cell.new() #<Cell:... @state=:e...> board[0, 0].state = :tower :tower board[0, 0].state :tower www.liu.se
© Copyright 2024