|
1 | 1 | window.__HL_SECTIONS = window.__HL_SECTIONS || {}; |
2 | 2 | window.__HL_SECTIONS['zaawansowane'] = ` |
3 | | -<!-- ─ UNSAFE + ARENA ─────────────────────────────────────────────────────── --> |
4 | 3 | <div class="section" id="unsafe"> |
5 | 4 | <div class="sec-header"><span class="sec-num">16</span><h2>Unsafe & Arena Allocator</h2></div> |
6 | | -<p>Bloki <code>unsafe</code> pozwalają na niskopoziomowe operacje poza systemem bezpieczeństwa pamięci. <code>unsafe arena(N)</code> daje arena allocator — wszystkie alokacje wewnątrz bloku pochodzą z puli N bajtów i są zwalniane en-bloc po wyjściu z bloku.</p> |
| 5 | +<p>Bloki <code>unsafe is...end</code> wyłączają sprawdzanie pamięci. <code>arena(N)</code> daje pulę N bajtów — wszystkie alokacje z bloku zwalniane en-bloc.</p> |
7 | 6 | <table class="ref-table"> |
8 | 7 | <tr><th>Składnia</th><th>Opis</th></tr> |
9 | | -<tr><td><span class="td-syntax">unsafe do...end</span></td><td class="td-desc">Blok bez arena — niskopoziomowe operacje</td></tr> |
10 | | -<tr><td><span class="td-syntax">unsafe arena do...end</span></td><td class="td-desc">Blok z arena allocatorem (domyślny rozmiar 1MB)</td></tr> |
11 | | -<tr><td><span class="td-syntax">unsafe arena(65536) do...end</span></td><td class="td-desc">Arena o konkretnym rozmiarze w bajtach</td></tr> |
12 | | -<tr><td><span class="td-syntax">fn unsafe nazwa() do...end</span></td><td class="td-desc">Funkcja oznaczona jako unsafe</td></tr> |
| 8 | +<tr><td class="td-syntax">unsafe is...end</td><td class="td-desc">Blok bez arena — niskopoziomowe operacje</td></tr> |
| 9 | +<tr><td class="td-syntax">unsafe arena is...end</td><td class="td-desc">Arena 1MB (domyślnie)</td></tr> |
| 10 | +<tr><td class="td-syntax">unsafe arena(N) is...end</td><td class="td-desc">Arena N bajtów</td></tr> |
| 11 | +<tr><td class="td-syntax">unsafe manual is...end</td><td class="td-desc">Ręczne malloc/free</td></tr> |
13 | 12 | </table> |
14 | 13 | <div class="code-block"> |
15 | 14 | <div class="code-header"><span class="code-filename">unsafe.h#</span><button class="copy-btn">Copy</button></div> |
16 | | -<div class="code-body"><div class="line-nums"><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span><span>21</span><span>22</span><span>23</span><span>24</span><span>25</span></div> |
17 | | -<div class="code-inner"><pre><span class="t-comment"># ── Arena na domyślnym rozmiarze ─────────────────</span> |
18 | | -<span class="t-kw">fn</span> <span class="t-func">process_buffer</span>() <span class="t-kw">do</span> |
19 | | -<span class="t-kw">unsafe</span> arena <span class="t-kw">do</span> |
20 | | -<span class="t-comment"># alokacje tu z puli 1MB</span> |
21 | | -<span class="t-kw">let</span> buf: bytes = [<span class="t-num">0</span>, <span class="t-num">1</span>, <span class="t-num">2</span>, <span class="t-num">3</span>] |
22 | | -println(buf.to_hex()) |
23 | | -<span class="t-kw">end</span> |
24 | | -<span class="t-comment"># buf automatycznie zwolniony — cała arena razem</span> |
| 15 | +<div class="code-body"><div class="code-inner"><pre><span class="t-kw">fn</span> <span class="t-func">process_packet</span>(data: bytes) <span class="t-kw">is</span> |
| 16 | + <span class="t-comment">;; Arena 64KB — alokacje zwalniane po wyjściu z bloku</span> |
| 17 | + <span class="t-kw">unsafe</span> arena(<span class="t-num">65536</span>) <span class="t-kw">is</span> |
| 18 | + <span class="t-kw">let</span> buf: string = <span class="t-str">"DE AD BE EF"</span> |
| 19 | + write(<span class="t-str">"Packet: "</span> + buf) |
| 20 | + <span class="t-kw">end</span> |
| 21 | + <span class="t-comment">;; buf automatycznie zwolniony</span> |
25 | 22 | <span class="t-kw">end</span> |
26 | 23 |
|
27 | | -<span class="t-comment"># ── Arena z konkretnym rozmiarem (64KB) ──────────</span> |
28 | | -<span class="t-kw">fn</span> <span class="t-func">analyze_packet</span>(data: bytes) <span class="t-kw">do</span> |
29 | | -<span class="t-kw">unsafe</span> arena(<span class="t-num">65536</span>) <span class="t-kw">do</span> |
30 | | -<span class="t-kw">let</span> raw: bytes = data |
31 | | -println(<span class="t-str">"Dane: "</span> + raw.to_hex()) |
32 | | -<span class="t-comment"># przetwarzaj pakiet...</span> |
33 | | -<span class="t-kw">end</span> |
| 24 | +<span class="t-kw">fn</span> <span class="t-func">raw_ops</span>() <span class="t-kw">is</span> |
| 25 | + <span class="t-kw">unsafe</span> <span class="t-kw">is</span> |
| 26 | + <span class="t-kw">let</span> ptr_val: u64 = <span class="t-num">0xDEADBEEF</span> |
| 27 | + write(<span class="t-str">"raw ptr: "</span> + to_string(ptr_val)) |
| 28 | + <span class="t-kw">end</span> |
34 | 29 | <span class="t-kw">end</span> |
35 | 30 |
|
36 | | -<span class="t-comment"># ── Unsafe bez areny ──────────────────────────────</span> |
37 | | -<span class="t-kw">fn</span> <span class="t-func">raw_op</span>() <span class="t-kw">do</span> |
38 | | -<span class="t-kw">unsafe</span> <span class="t-kw">do</span> |
39 | | -<span class="t-comment"># niskopoziomowe operacje bez sprawdzania granic</span> |
40 | | -<span class="t-kw">let</span> ptr_val: u64 = <span class="t-num">0xDEADBEEF</span> |
41 | | -println(<span class="t-str">"Raw: "</span> + to_string(ptr_val)) |
42 | | -<span class="t-kw">end</span> |
| 31 | +<span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">is</span> |
| 32 | + process_packet([]) |
| 33 | + raw_ops() |
| 34 | +
|
| 35 | + <span class="t-comment">;; Dla cybersec: przetwarzanie pakietów w arena</span> |
| 36 | + <span class="t-kw">unsafe</span> arena(<span class="t-num">1048576</span>) <span class="t-kw">is</span> |
| 37 | + write(<span class="t-str">"1MB arena dla buforów sieciowych"</span>) |
| 38 | + <span class="t-kw">end</span> |
43 | 39 | <span class="t-kw">end</span></pre></div></div> |
44 | 40 | </div> |
45 | | -<div class="callout c-danger"><div class="ci">⚠</div><div class="cb"><strong>Uwaga:</strong> Bloki <code>unsafe</code> wyłączają sprawdzanie bezpieczeństwa pamięci kompilatora. Używaj tylko gdy wiesz co robisz — np. przy FFI z bibliotekami C lub przy krytycznej optymalizacji wydajności.</div></div> |
| 41 | +<div class="callout c-danger"><div class="ci">⚠</div><div class="cb"><strong>Uwaga:</strong> Bloki <code>unsafe</code> wyłączają sprawdzanie granic i ownership. Używaj tylko przy FFI z C lub przy krytycznej optymalizacji.</div></div> |
46 | 42 | </div> |
47 | 43 |
|
48 | | -<!-- ─ OPTIONAL / PROPAGACJA BŁĘDÓW ─────────────────────────────────────── --> |
49 | 44 | <div class="section" id="optional"> |
50 | | -<div class="sec-header"><span class="sec-num">17</span><h2>Optional & propagacja błędów</h2></div> |
51 | | -<p>H# używa <code>T?</code> dla typów opcjonalnych i operatora <code>?</code> do propagacji nil w górę callstack. Podobnie jak <code>?</code> w Rust dla <code>Option</code>.</p> |
| 45 | +<div class="sec-header"><span class="sec-num">17</span><h2>Optional & propagacja nil</h2></div> |
52 | 46 | <div class="code-block"> |
53 | 47 | <div class="code-header"><span class="code-filename">optional.h#</span><button class="copy-btn">Copy</button></div> |
54 | | -<div class="code-body"><div class="line-nums"><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span><span>21</span><span>22</span><span>23</span><span>24</span><span>25</span><span>26</span><span>27</span><span>28</span></div> |
55 | | -<div class="code-inner"><pre><span class="t-comment"># ── Funkcja zwracająca optional ───────────────────</span> |
56 | | -<span class="t-kw">fn</span> <span class="t-func">find_user</span>(id: int) -> string? <span class="t-kw">do</span> |
57 | | -<span class="t-kw">if</span> id <= <span class="t-num">0</span> <span class="t-kw">do</span> |
58 | | -return <span class="t-kw">nil</span> |
59 | | -<span class="t-kw">end</span> |
60 | | -return <span class="t-str">"user_"</span> + to_string(id) |
| 48 | +<div class="code-body"><div class="code-inner"><pre><span class="t-kw">fn</span> <span class="t-func">find_user</span>(id: int) -> string? <span class="t-kw">is</span> |
| 49 | + <span class="t-kw">if</span> id <= <span class="t-num">0</span> <span class="t-kw">is</span> |
| 50 | + return <span class="t-kw">nil</span> |
| 51 | + <span class="t-kw">end</span> |
| 52 | + return <span class="t-str">"user_"</span> + to_string(id) |
61 | 53 | <span class="t-kw">end</span> |
62 | 54 |
|
63 | | -<span class="t-comment"># ── parse_int zwraca int? ─────────────────────────</span> |
64 | | -<span class="t-kw">fn</span> <span class="t-func">safe_parse</span>(s: string) -> int? <span class="t-kw">do</span> |
65 | | -return parse_int(s) <span class="t-comment"># nil jeśli nie da się sparsować</span> |
66 | | -<span class="t-kw">end</span> |
67 | | -
|
68 | | -<span class="t-comment"># ── Sprawdzanie nil ───────────────────────────────</span> |
69 | | -<span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">do</span> |
70 | | -<span class="t-kw">let</span> user: string? = find_user(<span class="t-num">5</span>) |
71 | | -<span class="t-kw">if</span> user != <span class="t-kw">nil</span> <span class="t-kw">do</span> |
72 | | -println(<span class="t-str">"Znaleziono: "</span> + user) |
73 | | -<span class="t-kw">else</span> <span class="t-kw">do</span> |
74 | | -println(<span class="t-str">"Nie znaleziono"</span>) |
75 | | -<span class="t-kw">end</span> |
76 | | -
|
77 | | -<span class="t-comment"># ── Operator ? — propagacja nil w górę ──────────</span> |
78 | | -<span class="t-kw">let</span> n: int? = parse_int(<span class="t-str">"42"</span>) |
79 | | -<span class="t-kw">let</span> val: int = n? <span class="t-comment"># jeśli nil — funkcja zwraca nil</span> |
80 | | -println(to_string(val)) |
81 | | -
|
82 | | -<span class="t-comment"># ── Łańcuch z ? ──────────────────────────────────</span> |
83 | | -<span class="t-kw">let</span> u = find_user(<span class="t-num">10</span>)? <span class="t-comment"># propaguj nil dalej</span> |
| 55 | +<span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">is</span> |
| 56 | + <span class="t-comment">;; Sprawdzenie nil</span> |
| 57 | + <span class="t-kw">let</span> u: string? = find_user(<span class="t-num">5</span>) |
| 58 | + <span class="t-kw">if</span> u != <span class="t-kw">nil</span> <span class="t-kw">is</span> |
| 59 | + write(<span class="t-str">"Znaleziono: "</span> + u) |
| 60 | + <span class="t-kw">else</span> <span class="t-kw">is</span> |
| 61 | + write(<span class="t-str">"Brak użytkownika"</span>) |
| 62 | + <span class="t-kw">end</span> |
| 63 | +
|
| 64 | + <span class="t-comment">;; Propagacja nil — operator ?</span> |
| 65 | + <span class="t-kw">let</span> n: int? = parse_int(<span class="t-str">"42"</span>) |
| 66 | + <span class="t-kw">let</span> val = n? <span class="t-comment">;; jeśli nil — funkcja zwraca nil</span> |
| 67 | + write(to_string(val)) |
84 | 68 | <span class="t-kw">end</span></pre></div></div> |
85 | 69 | </div> |
86 | 70 | </div> |
87 | 71 |
|
88 | | -<!-- ─ GENERICS ────────────────────────────────────────────────────────────── --> |
89 | 72 | <div class="section" id="generics"> |
90 | 73 | <div class="sec-header"><span class="sec-num">18</span><h2>Generics</h2></div> |
91 | | -<p>Typy i funkcje generyczne — parametryzowane typem T. Składnia: <code>struct Nazwa<T></code>, <code>fn nazwa<T></code>. Dostępne standardowe kontenery generyczne: <code>Vec<T></code>, <code>Map<K,V></code>.</p> |
92 | 74 | <div class="code-block"> |
93 | 75 | <div class="code-header"><span class="code-filename">generics.h#</span><button class="copy-btn">Copy</button></div> |
94 | | -<div class="code-body"><div class="line-nums"><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span><span>21</span><span>22</span><span>23</span><span>24</span><span>25</span></div> |
95 | | -<div class="code-inner"><pre><span class="t-comment"># ── Generyczna struct ─────────────────────────────</span> |
96 | | -<span class="t-kw">struct</span> Pair<A, B> <span class="t-kw">do</span> |
97 | | -<span class="t-kw">pub</span> first: A |
98 | | -<span class="t-kw">pub</span> second: B |
| 76 | +<div class="code-body"><div class="code-inner"><pre><span class="t-comment">;; Generyczna struct</span> |
| 77 | +<span class="t-kw">struct</span> Pair<A, B> <span class="t-kw">is</span> |
| 78 | + <span class="t-kw">pub</span> first: A |
| 79 | + <span class="t-kw">pub</span> second: B |
99 | 80 | <span class="t-kw">end</span> |
100 | 81 |
|
101 | | -<span class="t-comment"># ── Generyczna funkcja ────────────────────────────</span> |
102 | | -<span class="t-kw">fn</span> <span class="t-func">first</span><T>(arr: [T]) -> T? <span class="t-kw">do</span> |
103 | | -<span class="t-kw">if</span> len(arr) == <span class="t-num">0</span> <span class="t-kw">do</span> |
104 | | -return <span class="t-kw">nil</span> |
| 82 | +<span class="t-comment">;; Generyczna funkcja</span> |
| 83 | +<span class="t-kw">fn</span> <span class="t-func">first</span><T>(arr: [T]) -> T? <span class="t-kw">is</span> |
| 84 | + <span class="t-kw">if</span> len(arr) == <span class="t-num">0</span> <span class="t-kw">is</span> return <span class="t-kw">nil</span> <span class="t-kw">end</span> |
| 85 | + return arr[<span class="t-num">0</span>] |
105 | 86 | <span class="t-kw">end</span> |
106 | | -return arr[<span class="t-num">0</span>] |
107 | | -<span class="t-kw">end</span> |
108 | | -
|
109 | | -<span class="t-comment"># ── Typy generyczne std ───────────────────────────</span> |
110 | | -<span class="t-comment"># Vec<T> — dynamiczna tablica</span> |
111 | | -<span class="t-kw">let</span> v: Vec<int> = Vec::new() |
112 | | -
|
113 | | -<span class="t-comment"># Map<K,V> — mapa klucz-wartość</span> |
114 | | -<span class="t-kw">let</span> m: Map<string, int> = Map::new() |
115 | 87 |
|
116 | | -<span class="t-comment"># ── Użycie Pair ─────────────────────────────────</span> |
117 | | -<span class="t-kw">let</span> addr: Pair<string, int> = Pair { |
118 | | - first: <span class="t-str">"192.168.1.1"</span>, |
119 | | - second: <span class="t-num">8080</span> |
120 | | -} |
121 | | -println(addr.first + <span class="t-str">":"</span> + to_string(addr.second))</pre></div></div> |
| 88 | +<span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">is</span> |
| 89 | + <span class="t-kw">let</span> addr: Pair<string, int> = Pair { |
| 90 | + first: <span class="t-str">"192.168.1.1"</span>, |
| 91 | + second: <span class="t-num">8080</span> |
| 92 | + } |
| 93 | + write(addr.first + <span class="t-str">":"</span> + to_string(addr.second)) |
| 94 | +<span class="t-kw">end</span></pre></div></div> |
122 | 95 | </div> |
123 | 96 | </div> |
124 | 97 |
|
125 | | -<!-- ─ CLOSURES ────────────────────────────────────────────────────────────── --> |
126 | 98 | <div class="section" id="closures"> |
127 | | -<div class="sec-header"><span class="sec-num">19</span><h2>Closures (domknięcia)</h2></div> |
128 | | -<p>Funkcje anonimowe. Składnia: <code>|params| -> typ do...end</code> lub skrótowo <code>|params| wyrażenie</code>. Domykają zmienne z otaczającego zakresu.</p> |
| 99 | +<div class="sec-header"><span class="sec-num">19</span><h2>Closures</h2></div> |
129 | 100 | <div class="code-block"> |
130 | 101 | <div class="code-header"><span class="code-filename">closures.h#</span><button class="copy-btn">Copy</button></div> |
131 | | -<div class="code-body"><div class="line-nums"><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>10</span><span>11</span><span>12</span><span>13</span><span>14</span><span>15</span><span>16</span><span>17</span><span>18</span><span>19</span><span>20</span></div> |
132 | | -<div class="code-inner"><pre><span class="t-comment"># ── Prosta closure ────────────────────────────────</span> |
133 | | -<span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">do</span> |
134 | | -<span class="t-kw">let</span> podwoj = |x: int| -> int <span class="t-kw">do</span> |
135 | | -return x * <span class="t-num">2</span> |
136 | | -<span class="t-kw">end</span> |
137 | | -
|
138 | | -println(to_string(podwoj(<span class="t-num">21</span>))) <span class="t-comment"># 42</span> |
139 | | -
|
140 | | -<span class="t-comment"># ── Domknięcie zmiennej zewnętrznej ──────────────</span> |
141 | | -<span class="t-kw">let</span> mnoznik: int = <span class="t-num">3</span> |
142 | | -<span class="t-kw">let</span> trojkrotnosc = |x: int| -> int <span class="t-kw">do</span> |
143 | | -return x * mnoznik <span class="t-comment"># domknięcie mnoznik</span> |
144 | | -<span class="t-kw">end</span> |
145 | | -println(to_string(trojkrotnosc(<span class="t-num">7</span>))) <span class="t-comment"># 21</span> |
146 | | -
|
147 | | -<span class="t-comment"># ── Przekazywanie jako argument ───────────────────</span> |
148 | | -<span class="t-kw">let</span> porty: [int] = [<span class="t-num">22</span>, <span class="t-num">80</span>, <span class="t-num">443</span>] |
149 | | -<span class="t-kw">for</span> p <span class="t-kw">in</span> porty <span class="t-kw">do</span> |
150 | | -println(to_string(podwoj(p))) |
151 | | -<span class="t-kw">end</span> |
| 102 | +<div class="code-body"><div class="code-inner"><pre><span class="t-kw">fn</span> <span class="t-func">main</span>() <span class="t-kw">is</span> |
| 103 | + <span class="t-comment">;; Prosta closure</span> |
| 104 | + <span class="t-kw">let</span> double = |x: int| -> int <span class="t-kw">is</span> |
| 105 | + return x * <span class="t-num">2</span> |
| 106 | + <span class="t-kw">end</span> |
| 107 | + write(to_string(double(<span class="t-num">21</span>))) <span class="t-comment">;; 42</span> |
| 108 | +
|
| 109 | + <span class="t-comment">;; Domknięcie zmiennej zewnętrznej</span> |
| 110 | + <span class="t-kw">let</span> mult: int = <span class="t-num">3</span> |
| 111 | + <span class="t-kw">let</span> triple = |x: int| -> int <span class="t-kw">is</span> |
| 112 | + return x * mult |
| 113 | + <span class="t-kw">end</span> |
| 114 | + write(to_string(triple(<span class="t-num">7</span>))) <span class="t-comment">;; 21</span> |
| 115 | +
|
| 116 | + <span class="t-comment">;; Użycie w pętli</span> |
| 117 | + <span class="t-kw">let</span> ports: [int] = [<span class="t-num">22</span>, <span class="t-num">80</span>, <span class="t-num">443</span>] |
| 118 | + <span class="t-kw">for</span> p <span class="t-kw">in</span> ports <span class="t-kw">is</span> |
| 119 | + write(to_string(double(p))) |
| 120 | + <span class="t-kw">end</span> |
152 | 121 | <span class="t-kw">end</span></pre></div></div> |
153 | 122 | </div> |
154 | 123 | </div> |
|
0 commit comments