Föreläsning 1

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