Skip to content
Ridgun
English

Ridgun

The language itself: a compiler that compiles itself, the stable project tool, the specification and the book

05-zerrendak-tuplak-eta-sekuentziak.md167 lines · 8.4 KBRaw
1# 05. kapitulua: Zerrendak, Tuplak eta Sekuentzien ninja trikimailua
2
3Aldi bakoitzean zenbaki bat edo testu bat bakarrik mugitzen duen programa batek ezer gutxirako balio du. Bizitza errealean fitxategi-zerrendak, datu-base bateko errenkadak, sare-paketeak edo koordenatuak erabiltzen dituzu.
4
5Horretarako, Ridgunek hiru ontzi desberdin ematen dizkizu, bakoitza lan oso zehatz baterako pentsatua:
61. **Zerrendak (`[T]`)**: *"Mota bereko elementu asko ditut (edo bat ere ez) eta zeharkatu egin nahi ditut"*.
72. **Tuplak (`(A, B)`)**: *"Gauza desberdinen bikote edo hirukote bat elkarrekin itzuli nahi dut mota berri bat sortu gabe"*.
83. **Sekuentziak eta maskarak (`s(_ + _)`, `(+ _ _ +)`)**: *"Argumentuak hegaldian iragazi edo berrantolatu nahi ditut iragazki matematiko bat banu bezala"*.
9
10Goazen banan-banan.
11
12---
13
14## 5.1. Zerrendak (`[T]`): Eguneroko ogia
15
16Ridgunen, mota baten inguruan kortxeteak jartzen badituzu, mota horretako zerrenda bat duzu:
17- `[Int]` osokoen zerrenda bat da: `[10, 20, 30]`.
18- `[String]` testuen zerrenda bat da: `["sagarra", "udarea"]`.
19- `[]` zerrenda hutsa da (edozein `[T]`-rekin bat datorren komodina).
20
21> *"Aizu, sar ditzaket zenbaki bat eta testu bat elkarrekin `[1, "bi"]` moduko zerrenda berean?"*
22> Bere horretan, **ez** (eta eskerrak eman konpiladoreari hori eragozteagatik, horrela ez zaizulako inoiz batuketa bat lehertuko ekoizpenean ezusteko testu batekin topo egitean). 06. kapituluan ikusiko dugu nola ebatzi `[1, "bi"]` kasua dotorezia osoz Datu-Mota Aljebraiko bat erabiliz (Haskellek egiten duen bezalaxe).
23
24### Nola zatitzen den zerrenda bat `i`, `j`, `k` indizeak erabili gabe: `[]` eta `(x:xs)`
25Lengoaia inperatiboetan, zerrenda bat zeharkatzeak `for (int i = 0; i < zerrenda.size(); i++)` ekarri ohi du, batez pasatzeko (*off-by-one*) arrisku klasikoarekin.
26
27Ridgunen ez dituzu indizeak zenbatzen; **zerrenda burutik desmuntatzen duzu**:
28- `[]`: zerrenda hutsik badago bat dator.
29- `(x:xs)`: zerrendak gutxienez elementu bat badu bat dator. Lehenengo elementua `x`-n sartzen du (**burua**) eta gainerako zerrenda `xs`-n (**isatsa**).
30
31Begira zein gozamena den zerrenda bat batzea edo zenbat elementu dituen zenbatzea:
32
33```ridgun
34batu zerrenda [Int] => Int
35batu zerrenda [] = 0
36batu zerrenda (x:xs) = x + (batu zerrenda xs)
37
38zenbatu elementuak [A] => Int
39zenbatu elementuak [] = 0
40zenbatu elementuak (_:xs) = 1 + (zenbatu elementuak xs)
41```
42
43Eta eguna alaituko dizun xehetasun tekniko bat: Ridgunen, `(x:xs)` ereduan `xs` isatsa ateratzeak **ez du gainerako zerrenda memorian kopiatzen**. Barnean bektore beraren gaineko ikuspegi bat da, hasierako erakuslea `1`ean aurreratzen duena soilik (berehalako $O(1)$).
44
45### Hainbat elementu kolpe batez agerian utz ditzakezu
46`:` ereduak joko handia ematen du komandoak edo protokoloak analizatzen ari zarenean:
47
48```ridgun
49interpretatu komandoa [String] => String
50interpretatu komandoa [] = "Ez duzu ezer idatzi"
51interpretatu komandoa ("laguntza":_) = "Laguntza erakusten..."
52interpretatu komandoa ("kopiatu":jatorria:helm:[]) = "{jatorria}-tik {helm}-ra kopiatzen"
53interpretatu komandoa (cmd:_) = "Komando ezezaguna: {cmd}"
54```
55
56Begira hirugarren errenkadari: `("kopiatu":jatorria:helm:[])` ereduak kolpe bakar batez egiaztatzen du zerrendak **zehazki 3 elementu** dituela, lehenengoa `"kopiatu"` dela, eta bigarrena eta hirugarrena erretiluan zerbitzatuta uzten dizkizu `jatorria` eta `helm` aldagaietan. Saiatu hori C edo Javan idazten eta ikusiko duzu zenbat `args.length == 3 && args[0].equals("kopiatu")` lerro ateratzen zaizkizun.
57
58### Zerrendak bi puntu bikoitzekin (`::`) lotzea
59`=` ikurraren eskuinaldean zaudenean (adierazpen batean) eta bi zerrenda itsatsi nahi dituzunean, **`::`** erabiltzen duzu:
60
61```ridgun
62itsatsi zerrendak [Int] [Int] => [Int]
63itsatsi zerrendak a b = a :: b
64
65gehitu atzean [Int] Int => [Int]
66gehitu atzean xs x = xs :: [x]
67```
68
69*(Erregela mnemotekniko azkarra: `:` bakar batek ereduetan zerrenda desmuntatzen du; bi `::`-k adierazpenetan bi zerrenda itsasten dituzte).*
70
71Eta benetan 5. elementua zuzenean atera nahi baduzu ezer zeharkatu gabe? Erabili izenari itsatsitako kortxeteak: `nire_zerrenda[5]`.
72
73---
74
75## 5.2. Funtzio bariadikoak (`T...`): "Pasa iezazkidazu nahi dituzun guztiak!"
76
77Batzuetan nahi duzu zure funtzioari deitzen dionak `maximoa 4 19 2 88 7` eroso idatzi ahal izatea, zenbakiak `[4, 19, 2, 88, 7]` kortxete artean biltzera behartu gabe.
78
79Jarri hiru puntu **`...`** zure sinadurako azken motaren atzean, eta zure funtzioaren barruan zerrenda gisa paketatuta jasoko duzu automatikoki:
80
81```ridgun
82batu hainbat Int... => Int
83batu hainbat zenb = batu zerrenda zenb
84
85main => ()
86main =
87 echo (batu hainbat 10 20 30) -- 60 inprimatzen du
88 echo (batu hainbat 1 2 3 4 5 6 7) -- 28 inprimatzen du
89```
90
91---
92
93## 5.3. Tuplak: Funtzio batek gauza bat baino gehiago itzuli nahi duenean
94
95Lengoaia askotan funtzio batetik bi gauza itzultzea buruko mina da: edo `EmaitzaPosizioarekin` klase laguntzaile lelo bat sortzen duzu, edo irteerako erakusleak erreferentziaz pasatzen dituzu.
96
97Ridgunen `(A, B)` **tupla** bat itzultzen duzu:
98
99```ridgun
100zatitu eta hondarra Int Int => (Int, Int)
101zatitu eta hondarra a b = (a / b, a % b)
102```
103
104Parentesiak ere aurrez ditzakezu sinaduraren lerroan garbiago iruditzen bazaizu:
105`zatitu eta hondarra Int Int => Int Int`.
106
107### Nola ireki tupla bat
108`(a, b)`-rekin sortzen duzun bezalaxe, edozein funtzioren argumentuetan `(zatidura, hondarra)`-rekin irekitzen duzu:
109
110```ridgun
111azaldu zatiketa (Int, Int) => String
112azaldu zatiketa (zatidura, hondarra) = "{zatidura} aldiz sartzen da eta {hondarra} geratzen dira"
113```
114
115### Xehetasun izarra: Despaketatze automatikoa funtzioen artean
116Demagun `zatitu eta hondarra` (2 osokoko tupla bat itzultzen duena) eta beste funtzio bat `batu bikotea Int Int => Int` (2 osoko solte espero dituena) dituzula. Ridgunen ez duzu tupla eskuz ireki behar tarteko aldagai batean; funtzio bat bestearen barruan zuzenean entxufatu dezakezu:
117
118```ridgun
119batu bikotea Int Int => Int
120batu bikotea x y = x + y
121
122main => ()
123main =
124 -- zatitu eta hondarra 17 5 deiak (3, 2) itzultzen du, eta batu bikotea-k 3 eta 2 zuzenean jasotzen ditu:
125 echo (batu bikotea (zatitu eta hondarra 17 5)) -- 5 inprimatzen du
126```
127
128---
129
130## 5.4. Ninja trikimailua: Sekuentziak eta Maskara Posizionalak (`s(_ + _)`, `(+ _ _ +)`)
131
132Hemen dator Ridgunen bitxirik originalenetako bat, J eta APL bezalako lengoaia bektorialetatik zuzenean oinordetzan hartua.
133
134Imajinatu argumentu-sorta bat jasotzen duzula **`(s)`** sekuentzia-ereduarekin eta batzuekin bakarrik geratu nahi duzula eta besteak baztertu, asmatutako izenak dituzten bost aldagai deklaratu gabe (`_a`, `b`, `_c`, `d`...).
135
136`s`-ri **`+` (geratu horrekin) eta `_` (baztertu) tupla-maskara bat** aplikatzen diozu:
137
138- **`s(_ + _)`**: 3 elementutik, baztertu lehenengoa (`_`), geratu bigarrenarekin (`+`) eta baztertu hirugarrena (`_`).
139- **`s(+ _ +)`**: geratu lehenengoarekin eta hirugarrenarekin; itzuli bi horiek dituen sekuentzia.
140- **`s(_ _ +...)`**: baztertu lehenengo biak (`_ _`) eta aplikatu `+...` **atzetik datozen gainerako guztiei**, edozein izanda ere haien kopurua.
141
142Begira nola funtzionatzen duen:
143
144```ridgun
145erdikoa Int Int Int => Int
146erdikoa (s) = s(_ + _)
147
148baztertu lehen biak Int... => [Int]
149baztertu lehen biak (s) = s(_ _ +...)
150
151main => ()
152main =
153 echo (erdikoa 100 42 999) -- 42 inprimatzen du
154 echo (baztertu lehen biak 1 2 10 20 30) -- [10, 20, 30] inprimatzen du
155```
156
157Eta onena: **`(+ _ _ +)`** maskara posizional bat **zuzenean `->` hodi baten erdian** tartean sar dezakezu! Funtzio batek hainbat baliotako tupla bat itzultzen badu eta hurrengo funtzioak horietako bi bakarrik behar baditu, tupla hegaldian iragazten duzu eta Ridgunek bizirik atera diren elementuak hurrengo urratseko argumentu bereizi gisa desegituratuko ditu:
158
159```ridgun
160-- parseatu paketea-k 4 balio itzultzen ditu: (Int, Int, [String String], String)
161-- (+ _ _ +)-k 1.a (code) eta 4.a (msg) gordetzen ditu, eta konbinatu kodea-ri pasatzen dizkio:
162parseatu paketea "v0.9.9" -> (+ _ _ +) -> konbinatu kodea -> laburpena
163```
164
165Gainera, parentesietatik kanpo `,` koma eragilea erabiltzen baduzu (`zerrenda1 , zerrenda2`), Ridgunek bi bildumak sekuentzia jarraitu bakar batean lautzen ditu.
166
167**06. kapituluan** programatzaile funtzional bat lehen mailako arkitekto bihurtzen duen urratsa emango dugu: **zure Datu-Mota Aljebraikoak (ADTak) sortzea, `A`..`Z`-rekin funtzio polimorfikoak idaztea eta neurrira egindako zure eragile propioak fabrikatzea**.