Skip to content

Commit 1d208e8

Browse files
authored
Update FinalExam.md
1 parent b81d95f commit 1d208e8

File tree

1 file changed

+165
-4
lines changed

1 file changed

+165
-4
lines changed

FinalExam.md

Lines changed: 165 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,6 @@ impl Draw for Player {
9090
Bu tasarıma göre **draw** davranışını uygulamış belli sayıda nesne için tek bir **for** döngüsü üzerinden işlem yapan ve gelen nesnelerin **draw** fonksiyonlarını işleten bir metot yazılması istenmektedir. Aşağıdaki metotlardan hangisi doğrudur?
9191

9292
**a)**
93-
9493
```rust
9594
fn draw_shapes(shapes: &Vec<&dyn Draw>) {
9695
for shape in shapes.iter() {
@@ -100,7 +99,6 @@ fn draw_shapes(shapes: &Vec<&dyn Draw>) {
10099
```
101100

102101
**b)**
103-
104102
```rust
105103
fn draw_shapes(shapes: &Vec<Draw>) {
106104
for shape in shapes.iter() {
@@ -110,7 +108,6 @@ fn draw_shapes(shapes: &Vec<Draw>) {
110108
```
111109

112110
**c)**
113-
114111
```rust
115112
fn draw_shapes(shapes: [&dyn Draw]) {
116113
for shape in shapes.iter() {
@@ -120,7 +117,6 @@ fn draw_shapes(shapes: [&dyn Draw]) {
120117
```
121118

122119
**d)**
123-
124120
```rust
125121
fn draw_shapes(shapes: &Vec<&Draw>) {
126122
for shape in shapes.iter() {
@@ -172,3 +168,168 @@ Yukarıdaki kod parçası derleme zamanında **Value used after being moved [E03
172168

173169
## Soru 5
174170

171+
**Trait** ve **closure**’lar sıklıkla bir arada ele alınır. Bir **closure** anonim fonksiyon olarak da ifade edilir. Özellikle fonksiyonel dillerde yaygın olarak kullanılan closure'lar, bir değişkene atanabilir ve bu sayede fonksiyonlara parametre olarak kod bloklarının taşınması sağlanabilir. Benzer şekilde fonksiyonlardan dönüş türü olarak da kullanılabilir. Böylece nesne toplulukları üzerinde aynı kod bloğunu işleten fonksiyonları geliştirmek oldukça kolaylaşır. Tüm iteratif fonksiyonlar bu tekniğe göre geliştirilmiştir. Rust, closure kullanımlarında kısıtlar _(Constraints)_ da kullanır ve bunu üç farklı **trait** ile sağlar.
172+
173+
- **Fn:** Closure, dışarıdan yakaladığı değişkenleri salt okunur _(read only)_ şekilde kullanır.
174+
- **FnMut:** Closure, dış değişkenleri değiştirerek _(mutable)_ kullanabilir.
175+
- **FnOnce:** Closure, dış değişkenleri sahiplenir _(move eder)_ ve yalnızca bir kez çağrılabilir.
176+
177+
Geliştirdiğimiz örnekte bir oyun sahasındaki nesneler üzerinde parametre olarak gönderilen kod bloğunu işletecek genel bir fonksiyon yazmak istediğimizi düşünelim.
178+
179+
```rust
180+
pub fn main() {
181+
let mut world = GameWorld {
182+
players: vec![
183+
Player {
184+
id: 1,
185+
position: (0.0, 0.0),
186+
velocity: (2.0, 0.0),
187+
score: 0,
188+
},
189+
Player {
190+
id: 2,
191+
position: (100.0, 0.0),
192+
velocity: (8.0, 0.0),
193+
score: 0,
194+
},
195+
],
196+
};
197+
198+
let apply_gravity = |entity: &mut Player| {
199+
entity.position.0 += entity.velocity.0 * 0.9;
200+
entity.position.1 += entity.velocity.1 * 0.9;
201+
};
202+
203+
println!("Before Update: {:?}", world.players);
204+
update_players_system(&mut world, apply_gravity);
205+
}
206+
```
207+
208+
Bu kod parçasını göz önüne alırsak aşağıdakilerden hangisi update_players_system’in doğru bir tanımıdır?
209+
210+
**a)**
211+
```rust
212+
fn update_players_system<F>(world: &mut GameWorld, mut f: F)
213+
where
214+
F: Fn(&mut Player),
215+
{
216+
for p in &mut world.players {
217+
f(p);
218+
}
219+
}
220+
```
221+
222+
**b)**
223+
```rust
224+
fn update_players_system<F>(mut world: GameWorld, mut f: F)
225+
where
226+
F: FnMut(&Player),
227+
{
228+
for p in &world.players {
229+
f(p);
230+
}
231+
}
232+
```
233+
234+
**c)**
235+
```rust
236+
fn update_players_system<F>(world: &mut GameWorld, f: F)
237+
where
238+
F: FnMut(Player),
239+
{
240+
for mut p in world.players {
241+
f(p);
242+
}
243+
}
244+
```
245+
246+
**d)**
247+
```rust
248+
fn update_players_system<F>(world: &mut GameWorld, mut f: F)
249+
where
250+
F: FnOnce(&mut Player),
251+
{
252+
for p in &mut world.players {
253+
f(p);
254+
}
255+
}
256+
```
257+
258+
## Soru 6
259+
260+
Aşağıda verilen kod parçası bir closure ifadesi döndürüyor.
261+
262+
```rust
263+
use crate::models::{Level, Log};
264+
use std::io::{Write, stdout};
265+
266+
pub fn log() -> impl FnMut(&Log) {
267+
let mut error_count = 0;
268+
let mut warn_count = 0;
269+
let mut info_count = 0;
270+
move |l| {
271+
stdout()
272+
.write(format!("{}\n", l.to_string()).as_bytes())
273+
.unwrap();
274+
match l.level {
275+
Level::Error => error_count += 1,
276+
Level::Warn => warn_count += 1,
277+
Level::Info => info_count += 1,
278+
_ => {}
279+
}
280+
stdout()
281+
.write(
282+
format!(
283+
"Log Tracker: {} errors, {} warnings, {} infos\n",
284+
error_count, warn_count, info_count
285+
)
286+
.as_bytes(),
287+
)
288+
.unwrap();
289+
}
290+
}
291+
```
292+
293+
Buna göre aşağıdaki şıklarda belirtilen ifadelerden hangisi doğrudur?
294+
295+
**a)** Closure Copy trait’ine sahiptir, dolayısıyla her çağrıldığında iç sayaçlar sıfırdan başlar.
296+
297+
**b)** Dönüş tipi impl Fn(&Log) olarak da yazılabilir çünkü closure yalnızca okuma yapmaktadır.
298+
299+
**c)** Closure, mut olarak çağrılmak zorundadır çünkü error_count, warn_count, info_count değerleri her çağrımda değişir. Bu nedenle dönüş tipi impl FnMut(&Log) olarak belirtilmiştir.
300+
301+
**d)** Kodda move ifadesinin kullanılmasına gerek yoktur. error_count, warn_count, info_count değerleri heap üzerinde tutulmadığı için closure zaten bu değerlere doğrudan erişebilir.
302+
303+
## Soru 7
304+
305+
Aşağıdaki kod parçasını dikkatlice inceleyiniz.
306+
307+
```rust
308+
fn main() {
309+
create()
310+
}
311+
enum Tree {
312+
Node(i32, Tree, Tree),
313+
Empty,
314+
}
315+
316+
pub fn create() {
317+
let left_child = Tree::Node(1, Tree::Empty, Tree::Empty);
318+
let right_child = Tree::Node(3, Tree::Empty, Tree::Empty);
319+
let root = Tree::Node(2, left_child, right_child);
320+
}
321+
```
322+
323+
Yukarıdaki kod derleme zamanında **error[E0391]: cycle detected when computing when `Tree` needs drop** hatası verir. Bu hatanın sebebi şıklardan hangisidir?
324+
325+
**a)** Enum yapısında Empty varyantının bulunması Node varyantını geçersiz kılıp Rust’ın match yapısının kullanmasını gerektirdiği için hata alınır.
326+
327+
**b)** Enum Tree kendi içinde doğrudan kendisini barındırdığı için sonsuz büyüklükte bir veri yapısı oluşur ve bu kontrol edilebilir değildir. Çözüm için Box<Tree> gibi bir Smart Pointer kullanılarak recursive alanların heap’e taşınması sağlanmalıdır.
328+
329+
**c)** Tree yapısı içinde kullanılan i32 türünün Drop trait'ini implemente etmemesi sebebiyle hata oluşur.
330+
331+
**d)** Rust, enum türleri içinde başka enum’ları doğrudan kullanmayı desteklemez. Bu nedenle Tree enum’unun kendi türünde alanları olamaz.
332+
333+
## Soru 8
334+
335+

0 commit comments

Comments
 (0)