Ruby (programmeertaal)

Van Wikipedia, de gratis encyclopedie
Spring naar navigatie Spring naar zoeken
Robijn
logo
Officieel logo
Basis data
paradigma's : multiparadigmatische, diep geïntegreerde objectoriëntatie
Jaar van uitgave: 1995[1]
Ontwerper: Yukihiro Matsumoto
Ontwikkelaar: Yukihiro Matsumoto en anderen
Huidige versie 3.0.1[2] (5 april 2021)
Typen : sterk , dynamisch (" eendentypering ")
Belangrijke implementaties : MRI / CRRuby (YARV), JRuby , Rubinius (zie hieronder )
Beïnvloed door: Smalltalk , Perl , Python , Lisp , CLU , Eiffel , Ada , Dylan , JavaScript
Aangedaan: Kristal , D , [3] Elixer , Groovy , Roest , Swift
Besturingssysteem : platformonafhankelijk
Licentie : 2-clausule BSD en eigen (zie gebruiksvoorwaarden )
ruby-lang.org

Ruby (Engels voor ruby ) is een programmeertaal op hoog niveau die halverwege de jaren negentig werd ontworpen door de Japanner Yukihiro Matsumoto .

Ruby is objectgeoriënteerd , maar ondersteunt verschillende andere programmeerparadigma's (waaronder procedureel en functioneel programmeren en gelijktijdigheid ), biedt dynamisch typen , reflectie en automatische garbagecollection . Een Ruby-programma wordt tijdens runtime geïnterpreteerd . In 2012 is de Ruby-specificatie gestandaardiseerd als de internationale norm ISO/IEC 30170. [4]

Oorsprong en geschiedenis

Ruby Schepper, Yukihiro Matsumoto (2007)

Yukihiro "Matz" Matsumoto begon in 1993 aan zijn eigen taal te werken en bracht op 21 december 1995 de eerste versie van Ruby uit, 0.95. [5] Hij koos de naam afgeleid van de edelsteen robijn , als een zinspeling op de Perl programmeertaal taal . [6] Matsumoto's doel bij het creëren van de nieuwe taal was om elementen van de programmeertalen Perl , Smalltalk , Eiffel , Ada en Lisp te synthetiseren , die hij op prijs stelde, en om functionele en imperatieve programmeerparadigma's met elkaar te verzoenen. Bovendien moet de taal meer objectgeoriënteerd zijn dan Python en tegelijkertijd krachtiger dan Perl . Ook flexibiliteit, zeggingskracht en eenvoud speelden een belangrijke rol. [7]

Naast de technische eigenschappen was Matsumoto's bijzonder belangrijke aan Ruby de emotionele impact op gebruikers, mede-ontwikkelaars en hemzelf.Matsumoto's visie hierop is als volgt:

“Natuurlijk verschilt Ruby in veel opzichten van Perl of Python, dat is tenslotte de bestaansreden van Ruby. Primaire doel Ruby's is "vreugde". Voor zover ik weet, is er geen andere taal die zoveel op vreugde is gericht. Het uiteindelijke doel van Ruby is om te behagen - taalontwerpers, gebruikers, taalleerders, iedereen. Vreugde is echter niet alles. Ruby heeft ook veel toepassingen. Als je het niet zou kunnen gebruiken, zou het ook niet leuk zijn."

- Yukihiro Matsumoto : Voorwoord van de taalschepper in "Ruby プ ロ グ ラ ミ ン グ 入門" (vertaald)

In Japan verwierf Ruby al snel bekendheid na de release. In het westen van de programmering hielpen het boek Programming Ruby (2000) (bekend als het Pickaxe-boek als verwijzing naar de illustratie op de omslag) en het webframework Ruby on Rails (2004) doorbreken. In de daaropvolgende jaren nam de documentatie en literatuur in het Engels en Duits toe. De lingua franca van de kernontwikkelaars veranderde van Japans in Engels. Tegenwoordig wordt de taal in stand gehouden als een open source- project en is het onderwerp van verschillende publicaties en cursussen. Releases met nieuwe functies vinden meestal jaarlijks plaats in de kersttijd.

Een mijlpaal in de ontwikkeling van Ruby was versie 1.9 in 2007, die met veel veranderingen behoorlijk incompatibel werd met de vorige versies. De semantiek van sommige constructies is in deze versie gewijzigd. [8] De interpreter werd volledig herschreven, waardoor Ruby-programma's veel sneller werden. Strings kregen aparte karaktercoderingen , variabelen in blokken werden block-local, IPv6- ondersteuning en enkele syntactische vereenvoudigingen werden geïntroduceerd.

Met Ruby 2.0 zijn trefwoordparameters (bijv.: geïntroduceerd 0.step(by: 5, to: 20) ), (vooraan) de gordijnen van modules en vraaganalyse geïntroduceerd (luie-evaluatie) van iterators. Daarnaast is de standaard karaktercodering ingesteld op UTF-8 . Ruby 2.1 introduceerde verfijningen (een methode om klasseoverschrijvingen lokaal te beperken). In Ruby 2.2 werd de bestaande garbage collector vervangen door een incrementele. Met Ruby 2.3 is het mogelijk om automatisch alle tekenreeksen te maken die tegen schrijven zijn beveiligd en een nieuwe operator &. (Safe-Navigation-Operator) om Nijlcontroles te omzeilen is geïntroduceerd. In Ruby 2.4 zijn de klassen Fixnum en Bignum gestandaardiseerd. Vanaf Ruby 2.5 kunnen uitzonderingen worden opgevangen in do-end blokken zonder aparte subblokken. Ruby 2.6 leverde de eerste code voor een optionele JIT-compiler en voegde Bundler (zie hieronder ) toe aan de standaarddistributie. Ruby 2.7 voegde uitgebreide patroonafstemming en wat syntactisch reliëf toe aan de taalkern. Elke nieuwe Ruby-versie vanaf 1.9 bracht ook verschillende snelheidsoptimalisaties met zich mee. Bovendien breidde elke versie de standaardbibliotheek uit met handige methoden. Neerwaartse compatibiliteit was altijd verzekerd, maar niet altijd 100 procent.

Ruby 3.0, uitgebracht op 25 december 2020, is de eerste versie die voldoet aan de vereisten genaamd "Ruby 3x3": drie keer hogere uitvoeringssnelheid dan Ruby 2.0 (via JIT-compiler), gelijktijdigheid zonder GIL (maar nog steeds experimenteel) en statische typeanalyse (optioneel). De daadwerkelijke update 3.0 is echter geen grotere sprong dan de vorige jaarlijkse releases en is neerwaarts compatibel met Ruby 2.x.

Kenmerken

Alles is een object

Ruby is een programmeertaal die, hoewel hij vele andere programmeerparadigma's ondersteunt, fundamenteel objectgeoriënteerd is. Concreet betekent dit dat in Ruby zonder uitzondering elke waarde een object is en elke functie een methode (dwz wordt toegewezen aan een klasse). Er zijn geen uitzonderingen voor primitieve gegevenstypen zoals in veel andere objectgeoriënteerde programmeertalen. Klassen zijn ook objecten. Objecten slaan instantievariabelen op en hebben een klasse. Klassen zijn objecten die methoden opslaan en een overervingshiërarchie hebben. Instantievariabelen zijn alleen toegankelijk met methoden.

 klasse test klasse
einde
test_object = testklasse . nieuwe

zet 1 . klasse # => geheel getal
zet "tekst" . klasse # => tekenreeks
zet test_object . class # => TestClass
zet TestClass . klasse # => Klasse
klasse zet . klasse # => Klasse

Als "functies" worden gedefinieerd in Ruby, dit zijn eigenlijk methoden die worden toegevoegd aan het object object. In Ruby erven alle objecten impliciet van Object , daarom zijn op deze manier gedefinieerde "functies" beschikbaar in elk object en zijn daarom alomtegenwoordig. Deze functies zijn echter gemarkeerd als privé , wat betekent dat ze niet van buitenaf op een object kunnen worden aangeroepen.

 # Definieer "functie"
def mijn_functie
  zet "Hier ben ik"
einde

# Kan in andere objecten worden gebruikt, zoals een functie
klasse ABC
  def output_my_function_
    mijn_functie
  einde
einde
mijn_abc = ABC . nieuwe
mijn_abc . give_my_function_out # => Hier ben ik
mijn_abc . my_function # => foutmelding, private methode `my_function 'aangeroepen'

Omdat objecten dynamisch zijn in Ruby, kunt u met Ruby ook prototype-gebaseerd programmeren. Dit betekent ruwweg dat objecten hun eigen methoden kunnen hebben (buiten die gespecificeerd door de klasse) en kunnen worden gekopieerd en gewijzigd (aangezien alleen klassen methoden kunnen bevatten, wordt een nieuwe verborgen klasse alleen op de achtergrond gemaakt voor dat ene object).

 auto1 = Object . nieuwe
def auto1 . versnellen
  zet "hum hum hum"
einde

auto1 . versnellen # => "hum brom brom"

auto2 = auto1 . kloon
def auto2 . rem
  zet "piepen"
einde

auto2 . versnellen # => "hum brom brom"
auto2 . rem # => "piepen"

blokken

In de meeste programmeertalen op hoog niveau is het mogelijk om functies in elke vorm als parameterlogica door te geven, of het nu gaat om eersteklas functies of eersteklas objecten (waarvan de methoden dan de logica leveren). Bij Ruby is dat niet anders, maar Ruby heeft het speciale geval waar precies één functie wordt doorgegeven, syntactisch (en ook qua rekenkracht) sterk geoptimaliseerd. Dit speciale geval wordt blok genoemd, bedoeld als een blokprogrammeerlogica die de functie moet gebruiken.

Blokken worden als afzonderlijke parameters aan functies doorgegeven en volgen als laatste argument, gescheiden door accolades of de trefwoorden do en end . Hierna wordt de times- methode van object 10 aangeroepen en een blok overgedragen. Beide oproepen zijn identiek.

 10 . keer {
  zet "Hallo wereld!"
}
10 . keer doen
  zet "Hallo wereld!"
einde

Daarnaast kunnen blokken parameters worden gegeven en hebben ze ook een retourwaarde. De trefwoordopbrengst wordt binnen de aangeroepen methode gebruikt om het doorgegeven blok aan te roepen. Als opbrengstparameters zijn opgegeven, worden deze doorgegeven aan het blok, dat ze aan het begin als lokale variabelen kan declareren of ze kan negeren. Blokken (evenals methoden) retourneren automatisch de laatste uitdrukking van het blok als een retourwaarde (maar je kunt ook terugspringen naar andere plaatsen met break en next ).

 def methode_die_block_aufruft (g bergebener_parameter)
  own_variable = "Hallo"
  retourneerbaar = opbrengst eigene_variabele, ü bergebener_parameter
  if return == "ok"
    zet "☺"
  einde
einde

# Telefoongesprek
method_the_block_calls ( "van Ruby" ) do | p1 , p2 | # de blokargumenten zijn binnen || geconverteerd naar blok-lokale variabelen
  zet p1 + "" + p2 + "!"
  "OK"
einde
# Eerst, "Hallo van Ruby!" Wordt uitgevoerd in het blok,
# dan in methode ☺, omdat de geretourneerde waarde "ok" was

Blokken kunnen ook worden omgezet in functieobjecten. Als een & voor de laatste parameter in de parameterlijst van een methode wordt geschreven, converteert Ruby het overgedragen blok naar een proc (een functieobject). Als alternatief kunnen procs ook handmatig worden aangemaakt met de trefwoorden proc , lambda en -> . Deze objecten worden aangeroepen met behulp van de methoden call , [] of .() . Omdat Ruby alleen ronde haakjes gebruikt voor groepering, kunnen procs niet (zoals gebruikelijk is in andere programmeertalen) worden aangeroepen met proc_name() .

 def make_block_to_proc & block
  blok # is de geretourneerde waarde, als de laatste uitdrukking
einde
a = do_block_zu_proc { | een , b | een + b }
b = proc { | een , b | a - b } # a return binnen het blok verlaat de methode met daarin, breek alleen het blok
c = lambda { | een , b | a * b } # like proc, maar return binnen de lambda verlaat alleen dit blok
d = -> ( a , b ) { a / b } # nieuwe notatie voor lambda, ronde haakjes zijn optioneel
een . bel ( 1 , 2 ) # => 3
b [ 1 , 2 ] # => -1
c . ( 1 , 2 ) # => 2

# Voorbeeld van functioneel programmeren
e = d . kerrie . ( 8 ) # nieuwe procedure die de eerste parameter (of parameters) (de dividenden hier) instelt als 8
e . ( 2 ) # => 4
# met & je kunt Proc-objecten (eigenlijk elke klasse die een aanroepmethode heeft) terug naar blokken converteren
[ 8 , 4 , 2 , 1 ]. kaart ( & e ) # => [1, 2, 4, 8]

Alle blokken zijn sluitingen , zodat ze b.v. B. de status van lokale variabelen als ze permanent nodig zijn binnen het blok.

Mixins

Ruby beheerst bewust geen meervoudige overerving, maar biedt in plaats daarvan een concept genaamd mixins (Duits: hulpstoffen). Mixins zijn verzamelingen methoden die aan elke klasse kunnen worden toegevoegd . Een klasse kan een willekeurig aantal mixins bevatten. Mixins worden toegevoegd in de overervingshiërarchie tussen klasse en superklasse in de volgorde waarin ze zijn geschreven. Als alternatief is het ook mogelijk om mixins voor de eigenlijke klas te hangen (handig voor onder andere aspectgericht programmeren ). Om mixins te definiëren, worden in Ruby modules gebruikt, dit zijn quasi-klassen (dwz verzamelingen van methoden) die niet kunnen worden geïnstantieerd en naamruimten in één.

 klasse dier
  zeker zegt
    puts " # { self . class } zegt niets" # "text # {logic} text" is Ruby's tekstinterpolatie
  einde
einde

module KannSchwimmen # Module, dwz KannSchwimmen.new werkt niet
  zeker zwemt
    puts " # { self . class } floats" # self retourneert de instantie
  end # elk object heeft een .class-methode die het class-object retourneert
einde

module kan niet zwemmen
  zeker zwemt
    zet " # { self . class } goes under"
  einde
einde

class fish < tier # overerving wordt aangegeven door de operator kleiner dan
  inclusief CanSwimming # voeg CanSwimming toe tussen vis en dier
einde

klasse vogel < dier
  omvatten Kan niet zwemmen
  def zegt # gebruikelijke overerving, dekking zegt methode van dier
    zet " # { self . class } : piep"
  einde
einde

klasse mens < dier
  inclusief CanSwim
  zeker zegt
    zet " # { self . class } : ik kan mezelf beter uitdrukken"
  einde
einde

klasse niet-zwemmer < mens
  prepend Kan niet zwemmen # append Kan niet zwemmen op een niet-zwemmers,
end # dat wil zeggen, bedek de floats-methode

vis = vis . nieuwe
mens = mens . nieuwe
vogel = vogel . nieuwe
nicht_schwimmer = NietSwimmer . nieuwe

vissen . zegt # => vis zegt niets
vogel . zegt # => vogel: piep
mens . zegt # => mens: ik kan mezelf beter uitdrukken
niet_zwemmer . zegt # => geen zwemmers: ik kan mezelf beter uitdrukken
zet'
vissen . zwemt # => vis zwemt
vogel . zwemt # => vogel gaat onder
mens . zwemt # => man zwemt
niet_zwemmer . zwemt # => niet-zwemmer gaat onder

Open lessen

Alle klassen zijn open in Ruby, wat betekent dat alle methoden later in het programma kunnen worden uitgewisseld. Dit geldt ook voor alle ruby-interne klassen. Om methoden te overschrijven, hoeft u alleen maar een nieuwe klasse te maken met dezelfde naam als de klasse die moet worden overschreven. Ruby verwisselt of voegt dan de nieuw gedefinieerde methoden toe. Deze techniek is zeer krachtig, maar maakt ook moeilijk te vinden fouten mogelijk, vooral bij grotere projecten. Om deze reden wordt het ook wel licht pejoratieve apenpatching genoemd . Verfijningen bieden een oplossing voor de problemen die zich voordoen, een mogelijkheid om het overschrijven lokaal te beperken. Vorzuhängen de eerder gepresenteerde methode, de gewenste modules klassen (prepend), is meestal de veilige versie (en de mogelijkheid biedt ook de gedekte methode om direct aan te roepen).

 class Numeriek # ruby-interne klasse
  def inverse # nieuwe methode, bereken de reciproke
    Eerst 0 / zelf
  einde
einde

5 . inverse # => 0.2

Domeinspecifieke taal

Ruby wordt vaak gebruikt om domeinspecifieke talen te maken . Dit zijn tekstmodules die minder op programmacode lijken en meer op een opmaaktaal , maar eigenlijk normale Ruby-code zijn. Dit wordt enerzijds mogelijk gemaakt door de flexibele notatie van Ruby, bijvoorbeeld haakjes na methodeaanroepen of puntkomma's aan het einde van de regel zijn optioneel. Aan de andere kant biedt Ruby veel mogelijkheden voor metaprogrammering , die het mogelijk maken om overbodige uitdrukkingen te laten verdwijnen en het programma achter de schermen te veranderen. Als voorbeeld de configuratie van een testfabriek voor FactoryBot :

 Fabrieksbot . definieer doen
  fabriek : gebruiker doen
    voornaam "Max"
    achternaam "Mustermann"
    admin false
  einde
  fabriek : admin , klasse : gebruiker do
    voornaam "Beheerder"
    achternaam "Root"
    beheerder waar
  einde
einde

Krachtige standaardbibliotheek

De kernklassen (string, integer, float, array, hash, range, regexp) hebben een schat aan methoden die direct in elk ruby-programma kunnen worden gebruikt. Vooral door het veelvuldig gebruik van blokken kunnen lange programma's met deze methodes worden teruggebracht tot een paar regels, waardoor Ruby zeer geschikt is voor het tonen van proof-of-concepts . Vooral de Enumerable- module, die veel functionele programmeerconcepten rechtstreeks in de Ruby-kern brengt, valt op. Enumerable kan worden geïntegreerd in elk object dat een itereerbare container vertegenwoordigt en elke methode implementeert, bijvoorbeeld de klassen Array, Hash en Range. For-loops zijn daarom meestal niet nodig in Ruby. De hieronder getoonde methoden reduce , count , sort_by , each_slice en map zijn allemaal methoden van Enumerable en kunnen daarom eenvoudig worden toegevoegd aan klassen die u zelf heeft gemaakt.

 # tel de getallen 1 tot 100 bij elkaar op (zonder somformule), verkleinen komt overeen met vouwen uit de functionele programmering
( 1 .. 100 ) . verminderen { | teller , nummer | teller + nummer } # (1..100) .som werkt ook
# Array van de getallen van 0 tot 30 in stappen van 5
( 0 .. 30 ) . stap ( 5 ) . naar een
# Aantal regels in een bestand dat leeg is (zonder het bestand volledig in het geheugen te laden)
IO . foreach ( "bestandsnaam" ) . tel { | lijn | regel = ~ / ^ \ s * $ / }
# Sorteer array op lengte van achternaam
[ "Max Mustermann" , "John Doe" , "Tarou Yamada" ]. sort_by { | naam | naam . splitsen . laatste . lengte }
# Zet elk derde woord in de zin met een hoofdletter
"Franz jaagt in compleet vervallen taxi door Beieren." . splitsen . elke_slice ( 3 ) . kaart { | drie_woorden | drie_woorden . laatste . upcase! ; drie_woorden } . afvlakken . meedoen ( " " )

Naast de geïntegreerde modules wordt Ruby standaard met veel modules geleverd. Zo is ondersteuning voor bijvoorbeeld JSON , YAML , HTTP , benchmarks, priemgetallen, beveiligde willekeurige getallen, OpenSSL en logging direct beschikbaar.

Metaprogrammering

Ruby biedt uitgebreide mogelijkheden voor metaprogrammering . Het is dus z. B. mogelijk om methoden te genereren, instantievariabelen uit te wisselen, de overervingshiërarchie te wijzigen of constanten te bewerken. Het is echter niet mogelijk om de syntaxis te wijzigen of extra operators toe te voegen. Een methode voor het automatisch genereren van setters en getters wordt hier als voorbeeld gegeven (reeds in de standaard opgenomen onder de namen attr_reader , attr_writer , attr_accessor ).

 class Object # Monkey patchen van alle klassen
  def zelf . getter * args # self is Object hier, er wordt een klassenmethode gemaakt
    argumenten . elk doen | argument | # doorloopt alle parameters
      define_method arg do # define_method (arg) {block} creëert een nieuwe methode met de naam arg met het inhoudsblok
        instance_variable_get ( "@ # { arg } " . to_sym ) # instance_variable get geeft de waarde van de instantievariabele van de opgegeven naam
      end # \ - "@ # {arg}" plaatst een @ voor de inhoud van arg, to_sym zet de string om in een symbool
    einde
  einde
  def zelf . setter * args # * args verpakt alle parameters in een array genaamd args
    argumenten . elk doen | argument |
      define_method : " # { arg } =" doe | nieuwe_waarde | # define_method draagt ​​de parameters over die aan het blok zijn doorgegeven
        instantie_variabele_set ( "@ # { arg } " . to_sym , new_value ) # \ -setter- methoden eindigen op =
      einde
    einde
  einde
einde

klassenpaar met 2
  def initialiseer links # constructor
    @links = links # Instantievariabelen worden automatisch gegenereerd wanneer ze in een methode worden vermeld
    @rechts = 2
  einde
  getter: links: rechts
  setter : links
einde

paar = paar met2 . new ( 4 ) # new roept altijd de constructor aan
paar . links # => 4
paar . rechts # => 2
paar . links = 9 # => 9
paar . links # => 9
paar . rechts = 8 # => fout: NoMethodError (ongedefinieerde methode `right = ')

Deze technieken zijn ook goed voor het debuggen van applicaties of het analyseren van slecht gedocumenteerde applicaties of bibliotheken. Wanneer bijvoorbeeld de methods methode wordt aangeroepen, antwoordt elk object met een lijst van al zijn methoden, instance_variables retourneert een lijst met alle instantievariabelen.

Integratie in Unix

Net als Perl kan Ruby direct worden geïntegreerd in de pijplijn van de Unix-shell. Dit wordt mogelijk gemaakt door de opdrachtregelparameters van de Ruby-interpreter, waarmee de programmalogica en het gebruikelijke programmagedrag kunnen worden gedefinieerd (meestal dezelfde bewerking die op elke regel wordt uitgevoerd). Ruby breidt de standaard Unix-tools uit met geavanceerde methoden voor tekstanalyse en tekstverwerking.

Ruby biedt ook de mogelijkheid om processen gemakkelijk binnen een programma te starten, hun invoer te regelen en uitvoer- en retourwaarden uit te lezen. Code binnen `` wordt direct doorgegeven aan de Unix-shell. Het commando os_string = `uname -a` de naam van het besturingssysteem rechtstreeks op in een Ruby-variabele. De retourwaarde van de laatste programma-oproep wordt automatisch opgeslagen in de globale variabele $? opgeslagen. Signaalverwerking, sockets en threads worden ook rechtstreeks ondersteund door de taalkern zonder extra bibliotheken. Om de verwerking te versnellen is er een module in Ruby genaamd FileUtils , die een groot deel van de functionaliteit van veel Unix-bestandsbeheerprogramma 's ( rm , cp , chmod ) rechtstreeks in Ruby in kaart brengt.

Syntaxis en basis

Naamgeving

Ruby volgt de gebruikelijke conventie voor namen van methoden en variabelen, een naam moet beginnen met een kleine letter of een underscore, daarna kunnen eventuele letters (volgens Unicode ), cijfers en underscores volgen. Methoden kunnen ook eindigen met een uitroepteken of vraagteken. Volgens de gebruikelijke conventie dient de eerste als een indicatie dat deze methode een scherpere versie is van dezelfde methode zonder uitroepteken (verandert de status van het object, gooit fouten, ...), de laatste betekent dat de functie retourneert een Boolean (waar of onwaar). Als een variabelenaam met een hoofdletter begint, is het een constante. Variabelen kunnen ook beginnen met een speciaal teken dat het geldigheidsgebied beschrijft.

Identificatie variabele

Ruby onderscheidt vijf geldigheidsgebieden:

  • Meestal is een variabele lokaal geldig binnen het omringende blok of de methode.
  • Een @ voor variabelen declareert instantievariabelen, ze worden dan permanent toegewezen aan de instantie en zijn alleen hierin zichtbaar. Instantievariabelen zijn alleen toegankelijk van buitenaf met behulp van methoden. Toegang tot niet-bestaande instantievariabelen geeft geen fout, maar retourneert nul
  • Een voorafgaande @@ maakt variabelen klassevariabelen die bij de omringende klasse horen.
  • Met $ worden variabelen globaal en zijn dus zichtbaar in het hele programma.
  • Het geldigheidsbereik voor constanten is afhankelijk van de lokale nestdiepte en kan worden gespecificeerd met ::

Methode-aanroepen en -expressies

In Ruby worden methodeaanroepen niet noodzakelijkerwijs gemarkeerd met de volgende haakjes. gets.chomp is daarom gelijk aan gets().chomp() . Als methoden parameters vereisen, moeten deze tussen haakjes worden geplaatst als een andere bewerking op het resultaat moet worden uitgevoerd. "a,b,c".split "," is ok, "a,b,c".split(",").join(" ") vereist het eerste "a,b,c".split(",").join(" ") haakjes. Omdat haakjes ook worden gebruikt voor groeperen, mag er nooit een spatie worden geplaatst tussen de naam van de methode en het haakje wanneer de methode wordt aangeroepen ( [1,2].join␣("|") * 2 != [1,2].join("|") * 2 => [1,2].join(("|") * 2) != ([1,2].join("|")) * 2 => "1||2" != "1|21|2" ).

Elke instructie vormt een uitdrukking die aan een variabele kan worden toegewezen. Afzonderlijke instructies worden gescheiden door regeleinden of puntkomma's. De laatste uitdrukking binnen een methode vormt automatisch de retourwaarde. Het is echter ook mogelijk om eerder terug te springen met het trefwoord return .

Gegevenstypen

De elementaire gegevenstypen hebben handigere constructors dan de gebruikelijke Klasse.new

  • Tekenreeks: "Text" , 'Text' of %{Text} tekst
  • Integer: 3 (tientallensysteem), 0775 of 0o775 (octaal systeem), 0xFF (hexadecimaal systeem) 0b1001 (binair systeem) geheel getal (onbeperkte grootte)
  • Float: 3.0 drijvende-kommagetal (beperkte precisie)
  • Rationeel: 1/2r rationaal getal
  • Complex: 1 + 1i complex getal
  • Array: [1,2,3] Verzameling, kan een willekeurig aantal verschillende gegevenstypen bevatten
  • Hash: { 1 => "eins", 2 => "zwei" } Toewijzing, wijst precies één waarde toe aan elke waarde voor de pijlen (toets)
  • Regexp: /\A(eins|zwei)\z/ of %r{\A(eins|zwei)\z} Reguliere expressie
  • Bereik: 1..3 of 1...4 (exclusief rechter element) interval
  • Symbool :zeichen symbool, zie hieronder

Dynamische snaren

Standaard kunnen tekenreeksen worden gewijzigd in Ruby, dwz dat een String-object zijn waarde tijdens runtime kan wijzigen. text = "Felar"; text[2..3] = "hle"; puts text verandert de waarde van text direct (en drukt fouten af ). Veel tekenreeksmethoden zijn beschikbaar, zowel in een wijzigende variant als in een variant die een nieuw tekenreeksobject maakt.

 een = "ABC"
b = een . kleine letter
zet a , b # => ABC abc
een . onderkast!
zet a , b # => abc abc

Zoals elk Ruby-object, kunnen strings worden bevroren door de freeze methode aan te roepen ( "ABC".freeze ) en kunnen ze vervolgens niet worden gewijzigd.

symbolen

Dit ietwat ongebruikelijke en ook controversiële datatype is een soort mengsel van integer en string. Het dient voornamelijk als geheugensteun voor sleutels van hashes, aangezien dynamische strings hier onpraktisch zijn en gehele getallen weinig geheugen nodig hebben. Symbolen hebben niet de tekstmanipulatiemethoden van String, maar kunnen op elk moment naar strings worden geconverteerd. Als symbolen in hashes als sleutels worden gebruikt, kan een vereenvoudigde notatie worden gebruikt. In plaats van { :a => 1, :b => 2 } kan ook { a: 1, b: 2 } worden geschreven. Symbolen worden ook intern vaak gebruikt in Ruby, dus methoden kunnen ook worden aangeroepen met hun symboolnaam: 1 < 4 kan ook worden geschreven als 1.send(:<, 4) . Eenvoudige blokken die slechts één methode van het overgedragen object aanroepen, kunnen op een vereenvoudigde manier worden geschreven met behulp van symbolen, waarbij het symbool de aan te roepen methode aangeeft. [1,2,3].map{|i| i.to_s} kan ook worden geschreven als [1,2,3].map(&:to_s) (& zet het symbool om in een blok).

Waarheidswaarden

Er zijn drie verschillende waarheidswaarden in Ruby, true , false en nil . Nil staat voor een ontbrekend resultaat en wordt, net als false, geëvalueerd als false . True en alle andere objecten worden als true geëvalueerd. puts "Ja!" if 0 waar is , wordt "Ja!" uitgevoerd.

Foutafhandeling

In de meeste programmeertalen moet het programmagedeelte dat op fouten moet worden gecontroleerd, expliciet worden gemarkeerd (meestal met behulp van de trefwoorden try and catch ); in Ruby omvat het programmagedeelte in de meest voorkomende gevallen de volledige methode of het hele blok, geen extra gebied moet worden gemarkeerd. Indien een afbakening nodig mocht zijn, kan het gebied worden gemarkeerd met begin en einde .

 def give_sum_from arg1 , arg2
  # Methode logica
  tenzij arg1 . is een? ( Numeriek ) && arg2 . is een? ( Numeriek )
    hef ArgumentError op . new ( "Voer alleen cijfers in" ) # raise throws errors
  einde
  zet arg1 + arg2
redding ArgumentError => e # Catch ArgumentError
  zet "Er is een fout opgetreden bij het overzetten van parameters"
redding => e # Vang alle verdere fouten
  zet e . bericht
zorg ervoor dat # in ieder geval wordt uitgevoerd
  zet 'einde methode'
einde

Alternatieve voorwaarden / lussen

Voorwaarden en lussen bieden zowel postfix-notatie als hun eigen sleutelwoord voor de inverse (geïnspireerd door Perl ).

 een = 5
als a < 10 ; zet een ; einde
zet a als een < 10 # achtervoegselvorm
tenzij a > = 10 ; zet een ; einde # inverse
zet a tenzij a > = 10 # inverse + achtervoegselvorm

terwijl een < 10 ; zet een ; een + = 1 ; einde
( zet a ; a + = 1 ) terwijl a < 20 # achtervoegselvorm
tot a > = 30 ; zet een ; een + = 1 ; einde # inverse
( zet a ; a + = 1 ) tot a > = 40 # inverse + achtervoegselvorm

Normale uitdrukkingen

Ruby bevat reguliere expressies direct in de taalkern. Ruby gebruikt zijn eigen regex-engine genaamd Onigmo , waarvan de syntaxis en functionaliteit voor het grootste deel compatibel is met PCRE . Bovendien is het mogelijk om Ruby-variabelen rechtstreeks in reguliere expressies te interpoleren en om elke programmalogica te gebruiken via blokken voor zoeken en vervangen. Het volgende commando telt bijvoorbeeld alle getallen in een tekst met één op: puts "test, 1, 2, 3".gsub(/(\d+)/){|zahl| zahl.to_i + 1} # => test, 2, 3, 4

constanten

In Ruby zijn constanten alle variabelen die beginnen met een hoofdletter. Alle klassen en modules zijn daarom constanten. Het bijzondere aan constanten in Ruby is hun nesting. Constanten binnen constanten kunnen worden aangeroepen met :: en zijn niet onderworpen aan toegangsrechten (zoals methoden of instantievariabelen). Deswegen können Module als Namensräume benutzt werden, alle Variablen bleiben darin versteckt, auf alle Konstanten (wie bspw. Klassen) kann über den Modulnamen qualifiziert zugegriffen werden (bspw. MeinModul::MeineKlasse.new ).

Bestandteile

Interaktive Ruby-Shell

Interactive Ruby ( irb ) ist eine Read-Eval-Print Loop (REPL), mit welcher der Anwender interaktiv Ruby programmieren kann. Irb wird mit dem Ruby-Interpreter ausgeliefert und kann zum Analysieren und Testen eingesetzt werden:

 irb(main):001:0> ( 5 + 7 ) * 2
=> 24
irb(main):002:0> (( 5 + 7 ) * 2 ) . to_s . reverse
=> "42"
irb(main):003:0> "Ein Beispielstring" . size
=> 18

Als Alternative zu Irb gibt es Pry , eine REPL, welche weitaus tiefgreifendere Möglichkeiten zur Introspektion und zum Debuggen mitbringt.

RDoc und ri

RDoc ist ein Software-Dokumentationswerkzeug , welches aus Ruby- und C-Quelltexten automatisch HTML -Dokumentationsdateien erstellt. Weiterhin wird eine Datenbank aufgebaut, die mit dem Tool ri durchsucht werden kann. RDoc und ri sind Bestandteil der Standarddistribution und werden zusammen mit dem Interpreter ausgeliefert.

Rake

Rake steht für Ruby-Make und ist eine Alternative zu Make aus C . Da es in Ruby keine Kompilationsphase gibt, dienen Rakefiles zum Automatisieren repetitiver Aufgaben, bspw. dem Generieren von Dokumentation, dem Upload von Dateien oder dem Packen von Projekten. Rake kann wie Make Abhängigkeiten auflösen, wenn für Aufgabe B erst Aufgabe A erfüllt sein muss, so führt Rake automatisch Aufgabe A aus. Rake ist eine domänenspezifische Sprache , dh, es lässt sich bequem wie eine Auszeichnungssprache lesen, bietet aber die vollen Möglichkeiten die Ruby bietet.

Paketverwaltung

Ruby-Bibliotheken werden üblicherweise als Gems (RubyGems) gepackt und auf rubygems.org, dem zentralen Gem-Register, veröffentlicht. RubyGems löst bei der Installation oder bei Updates die im Paket angegebenen Abhängigkeiten eigenständig rekursiv auf und bietet dabei sogar die Möglichkeit Pakete gleichzeitig in unterschiedlichen Versionen bereitzustellen. Seit Ruby 1.9 ist Rubygems Bestandteil der Standardbibliothek von Ruby. Heute wird es meist zusammen mit Bundler benutzt (ebenfalls Teil der Standardbibliothek, seit Ruby 2.6), einem Programm welches Schnappschüsse aus einer Kollektion von Gems erstellt und diese Anordnung auf anderen Maschinen (oder andern Projektordnern) wiederherstellen kann.

Implementierungen

Referenzimplementierung

Die Referenzimplementierung von Ruby wurde von Yukihiro „Matz“ Matsumoto als Interpreter in C entworfen. Dieser wird meist als MRI (Matz's Ruby Interpreter) oder auch als CRuby bezeichnet und ist derzeit am weitesten verbreitet. Den Kern bildet YARV (Yet Another Ruby VM) , eine virtuelle Maschine . Statt ein Rubyprogramm direkt auszuführen, wird es zunächst in Bytecode übersetzt und dann von YARV interpretiert, wodurch sich ein Geschwindigkeitsvorteil ergibt. Weiterhin enthält diese Version eine leistungsstarke Regexp -Maschine namens Oniguruma und unterstützt Multibyte-Zeichensätze wie UTF-8 .

Der offizielle Interpreter läuft auf den folgenden Betriebssystemen:

Alternative Implementierungen

Es gibt zahlreiche alternative Ruby-Implementierungen mit unterschiedlichem Umfang und Zielen:

  • JRuby , eine Neuimplementierung des Ruby-Interpreters in Java mit dem Ziel, Ruby nahtlos in die Java-Plattform zu integrieren. JRuby ist fast vollständig kompatibel zu Ruby 2.3. JRuby ist zudem kompatibel zu einigen Ruby-Erweiterungen von Rubinius (Foreign Function Interface, Multi-VM-API), allerdings nicht mit C -Erweiterungen von CRuby.
  • Rubinius , eine von Smalltalk-80 inspirierte Implementierung. Abgesehen von der virtuellen Maschine ist Rubinius vollständig in Ruby geschrieben. Rubinius ist nahezu vollständig kompatibel zu Ruby 2.3. Rubinius nutzt die Low Level Virtual Machine (LLVM) und ist kompatibel mit C -Erweiterungen der Referenzimplementierung.
  • Mruby ist eine weitere Ruby-Implementierung erschaffen vom Ruby-Schöpfer Yukihiro Matsumoto. Mruby ist eine auf eingebettete Systeme zugeschnittene Version von Ruby, welche sich durch geringen Speicherbedarf und hohe Modularisierung auszeichnet. Mruby stellt nicht die vollständige Funktionalität von CRuby bereit. Mruby kann den Quellcode in Bytecode übersetzen, welcher dann ohne Kompilationsschritt interpretiert oder in C -Programme eingebettet werden kann.
  • Opal ist ein Compiler von Ruby nach JavaScript. Es handelt sich um eine Implementierung der Ruby-Corelib und Stdlib, sowie den zugehörige Gems. Mit Opal lassen sich clientseitige Webanwendungen in Ruby realisieren. Es gibt einige Einschränkungen, die der Umsetzung nach JavaScript geschuldet sind.
  • TruffleRuby ist eine Ruby-Implementierung die auf der GraalVM läuft. Ziel der Implementierung ist es die Vorteile der GraalVM mittels Ruby nutzbar zu machen. Diese sind Geschwindigkeit (Start- und Laufzeit), Parallelisierung und das kontrollierte Ausführen von C-Erweiterungen. TruffleRuby wird maßgeblich von Oracle entwickelt.
  • Fullstaqruby ist eine auf der MRI-basierende Implementierung, die für den Einsatz auf Webservern ausgelegt ist. Im Vergleich zur Referenzimplementierung verspricht Fullstaqruby eine bessere Performance bei geringerem Speicherverbrauch.

Historische Ruby-Implementierungen:

  • IronRuby ist eine Implementierung, die Ruby ins .NET Framework integriert und in C# implementiert ist.
    Das Projekt ist seit 13. März 2011 inaktiv und wird nicht mehr weiterentwickelt.
  • Cardinal , ein Interpreter für die virtuelle Maschine Parrot . Das Projekt ist seit Juni 2013 inaktiv.
  • MagLev ist eine Implementierung des Unternehmens Gemstone für deren proprietäre Smalltalk VM. Das Projekt ist seit 2015 inaktiv.
  • MacRuby ist eine Implementierung in Objective-C von Apple , die bis Version 0.4, wie Ruby 1.9, YARV nutzt, ab Version 0.5 allerdings, wie Rubinius , auf die LLVM setzt. Die Weiterentwicklung wurde mit dem 5. Januar 2015 eingestellt.
  • Ruby Enterprise Edition ist eine modifizierte Version der Referenzimplementierung, bei der im Wesentlichen der Garbage Collector neu implementiert wurde. REE ist lediglich mit Ruby 1.8 kompatibel, die aktuellste Version stammt aus dem Jahr 2012.

Die Kompatibilität zur Referenzimplementierung wird durch das RubySpec-Projekt überprüft. Es stellt dabei sowohl eine Testsuite als auch eine Spezifikation für Ruby dar. RubySpec war ursprünglich ein Teil von Rubinius, wurde aber ausgelagert und danach auch von einer Vielzahl anderer Entwickler vorangetrieben. Es wird in vielen Ruby-Implementierungen verwendet.

Mit Hilfe des Ruby Version Managers [9] oder Rbenv [10] besteht die Möglichkeit, mehrere Ruby-Implementierungen und Gem-Versionen parallel zu betreiben.

Ein wichtiges Merkmal der Implementierungen ist, ob sie in der Lage sind, Ruby on Rails auszuführen. Derzeit können dies neben der Referenzimplementierung nur JRuby [11] und Rubinius [12] .

Verbreitung und Einsatz

Ruby ist für alle gängigen Desktop-Betriebssysteme frei erhältlich, in den meisten Linux-Distributionen ist es in den mitgelieferten Paketquellen enthalten, unter macOS sogar vorinstalliert.

Größte Verbreitung findet Ruby im Einsatz als Webserver-Skriptsprache. Das verbreitetste Framework hierbei ist Ruby on Rails , wobei es aber zahlreiche Alternativen verschiedener Größen gibt (bspw. Sinatra und Hanami). Die Liste großer Railsprojekte ist lang, am bekanntesten sind möglicherweise kommerzielle Webseiten wie GitHub , Airbnb oder Shopify oder Gemeinschaftsprojekte wie Diaspora , Redmine und Discourse . In Ruby geschriebene Webtechnologien wie Sass und Haml finden auch außerhalb des Ruby-Ökosystems Verwendung.
Weiter große Verbreitung findet Ruby als Skriptsprache zum Verwalten und Automatisieren von Serveraufgaben, angefangen als Ersatz für komplexere Bash -Skripte, als auch für größere Anwendungen, bspw. Puppet (Serverkonfiguration über das Netzwerk), Metasploit ( Penetrationstests ), YaST ( OpenSUSE -Serveradminstration) und Vagrant (Verwaltung virtueller Maschinen).
Ruby wird wegen der flexiblen Syntax ebenfalls gerne als domänenspezifische Sprache benutzt. Mit mruby gibt es auch eine Ruby-Variante, die sich auf Eingebette Systeme spezialisiert. Vereinzelt wird Ruby auch als Skript-Sprache in Spielen verwendet, bspw. im RPG Maker .

Kritik

Kritik an der Sprache wurde aus verschiedenen Gründen geübt:

  • Da Variablen vor Gebrauch nicht deklariert werden müssen, können bei Tippfehlern unerwartete Laufzeitfehler auftreten. Statische Codeanalyse, welche mit Ruby 3.0 hinzugefügt wurde, kann einige dieser Probleme verhindern.
  • Metaprogrammierung und Monkeypatching erlauben es einem Codestück, alle Klassen und Objekte des Prozesses, in dem es ausgeführt wird, zu ändern. [13]

Auch an der Referenzimplementierung bemängeln Kritiker mehrere Aspekte:

  • YARVs Global Interpreter Lock führt dazu, dass mehrere Threads eines Prozesses nicht gleichzeitig auf verschiedenen Prozessorkernen ausgeführt werden können. [14] [15] Seit Ruby 3.0 gibt es ein alternatives System für Nebenläufigkeit, genannt Ractor , welches ohne GIL auskommt. Allerdings muss vorhandener Code dafür umgeschrieben werden.

Sonstiges

Nutzungsbedingungen

Ruby ist eine freie Software . Deshalb ist es kostenlos nutzbar und im Quelltext verfügbar. Dadurch ergibt sich die Möglichkeit, die Sprache an seine eigenen Bedürfnisse anzupassen oder sie in eigene Programme einzubinden.

Der Interpreter und die Standardbibliothek von Ruby sind grundsätzlich unter den Bedingungen der 2-clause BSD-Lizenz nutzbar. Des Weiteren besteht die Möglichkeit, Ruby unter einer eigenen freien Lizenz zu verwenden. [16] Die Ruby-Lizenz ist GPL-kompatibel und wird von der Free Software Foundation als „frei“ akzeptiert. [17]

Ältere Versionen von Ruby (1.9.2 und früher) verwendeten anstatt der BSD-Lizenz die GPL V2 . Als Begründung für den Wechsel wurden Inkompatibilitäten der alten Lizenzierung mit der GPL V3 angeführt. [18] [19]

RubyForge

RubyForge war ein kollaborativer Filehosting - Dienst für in Ruby geschriebene Softwareprojekte. Er wurde im Jahr 2003 von Ruby Central gestartet, um der Ruby-Community eine Heimat für ihre Open-Source -Projekte zur Verfügung zu stellen.

Am 29. November 2009 wurden dort über 9.300 Projekte und mehr als 94.683 Benutzer geführt [20] , am 15. Mai 2014 wurde der Dienst schließlich eingestellt. [21]

Literatur

Für Programmieranfänger

Einstieg für Programmierer

Vertiefung für Programmierer

  • David A. Black: The Well-Grounded Rubyist . 2. Auflage. Manning, Shelter Island 2014, ISBN 978-1-61729-169-2 (englisch, Errata , Quellcode ).
  • Hal Fulton, André Arko: The Ruby Way. Solutions and Techniques in Ruby Programming . 3. Auflage. Addison-Wesley, Upper Saddle River, ua 2015, ISBN 978-0-321-71463-3 (englisch, Auszug [PDF]).

Gesamtdarstellungen

  • David Flanagan, Yukihiro Matsumoto: Die Programmiersprache Ruby . O'Reilly Media, 2008, ISBN 978-3-89721-874-1

Für Fortgeschrittene

  • Lucas Carlson, Leonard Richardson: Ruby Cookbook . O'Reilly Media, 2. Auflage 2015, ISBN 1-4493-7371-2 (englisch)
  • Pat Shaughnessy: Ruby Under a Microscope . No Starch Press, 1. Auflage 2013, ISBN 1-59327-527-7 (englisch)
  • Russ Olsen: Eloquent Ruby . Addison-Wesley Professional, 2011, ISBN 978-0-321-58410-6 (englisch)
  • Russ Olsen: Design Patterns in Ruby . Addison-Wesley Professional, 2007, ISBN 978-0-321-49045-2 (englisch)

Normen und Standards

  • ISO/IEC 30170 (englisch; standardisiert Ruby auf über 317 Seiten). Erste Version April 2012.

Weblinks

Commons : Ruby – Sammlung von Bildern, Videos und Audiodateien
Wikibooks: Ruby-Programmierung – Lern- und Lehrmaterialien

Einzelnachweise

  1. www.ruby-lang.org .
  2. www.ruby-lang.org .
  3. D Programming Language 1.0 , Intro. Digital Mars
  4. iso.org
  5. RubyConf: History of Ruby
  6. Ein Interview mit dem Schöpfer von Ruby
  7. About Ruby. Abgerufen am 4. Oktober 2018 .
  8. Ruby 1.9 released. Abgerufen am 5. September 2020 (englisch).
  9. RVM: Ruby Version Manager – RVM Ruby Version Manager - Documentation. Abgerufen am 4. Oktober 2018 .
  10. rbenv/rbenv. Abgerufen am 4. Oktober 2018 (englisch).
  11. JRuby Wiki. Abgerufen am 23. Februar 2017 (englisch).
  12. Evan Phoenix: Rails on Rubinius. 17. Mai 2008, archiviert vom Original am 22. März 2016 ; abgerufen am 23. Februar 2017 (englisch).
  13. Avdi Grimm: Monkeypatching is Destroying Ruby. 23. Februar 2008, abgerufen am 23. Februar 2017 (englisch).
  14. infoq.com
  15. igvita.com
  16. Rubys Lizenzbedingungen. Abgerufen am 23. Februar 2017 .
  17. Liste der GPL-kompatiblen Lizenzen. Abgerufen am 23. Februar 2017 .
  18. Mailinglistendiskussion zum Lizenzwechsel. Archiviert vom Original am 11. Juni 2015 ; abgerufen am 8. Juli 2012 .
  19. Beschluss zum Lizenzwechsel auf dem Ruby Developers Meeting 2010. Abgerufen am 23. Februar 2017 .
  20. RubyForge ( Memento vom 31. Mai 2014 im Internet Archive )
  21. Twitter-Nachricht von Evan Phoenix. Abgerufen am 28. März 2014 .