11# Ders 13: Macros  
22
3- Makrolar meta programlamanın temel unsurlarındadır. Meta programlama  kod yazan kodlar oluşturulmasını benimseyen bir
4- yaklaşımdır. Makroları kullanarak kod tekrarını azaltabilir ve daha okunabilir kodların oluşturulmasını sağlayabiliriz. 
5- Makrolar ile delerme zamanında kaynak kod üzerinde manipülasyon da  yapılabilir. Ayrıca struct,  enum, fn  gibi yapıların
6- derleme zamanında analiz edilip yeni kodların üretilmesini de sağlayabiliriz. Bugüne kadarki örneklerimizde bir çok 
7- makro kullandık. println!, write!, vec! gibi sonu ! ile  biten enstrümanlar aslında birer makrodur. Makroları  Declarative
8- _ (Bildirime  dayalı)_  ve Procedural  _ (Yönergelere dayalı) _   olmak üzere iki ana kategoriye ayırabiliriz .
3+ Makrolar kod yazan kodlar oluşturulmasını benimseyen bir meta programlama yaklaşımdır. Makroları kullanarak kod 
4+ tekrarlarını azaltabilir, daha okunabilir kodlar oluşturulabilir, delerme zamanında kaynak kod üzerinde değişikliler 
5+ yapılabilir. Ayrıca ** struct** ,  ** enum** ,  ** fn **  gibi yapıların derleme zamanında analiz edilip yeni kodların üretilmesi 
6+ de sağlanabilir. Önceki örneklerde bir çok makro kullanılmıştır.  ** println! ** ,  ** write! ** ,  ** vec! **  gibi sonu  ** ! **  ile 
7+ biten enstrümanlar aslında birer makrodur. Makrolar  Declarative  _ (Bildirime dayalı) _  ve Procedural  _ (Yönergelere 
8+ dayalı)_  olmak üzere iki ana kategoriye ayrılır .
99
1010## Hello Macro _ (Declarative)_   
1111
12- Makrolar belli bir fonksiyonelliğin farklı türevlerinin yazmaktan kaçınmamızı da sağlar . Aşağıdaki basit fonksiyonu göz
12+ Makrolar ile  belli bir fonksiyonelliğin farklı türevlerinin yazmak zorunda kalmayız . Aşağıdaki basit fonksiyonu göz
1313önüne alalım.
1414
1515``` rust 
@@ -32,10 +32,9 @@ mod tests {
3232}
3333``` 
3434
35- max_of_two fonksiyonu iki integer değerden hangisi büyükse onu geriye döndürmek amacıyla tasarlanmıştır. Ancak n adet
36- sayının birbiriyle karşılaştırılmasını istediğimiz bir durumda ne yaparız? Bu genellikle yeni bir fonksiyon yazılmasını
37- gerektirecektir. Bunun yerine bir makro hazırlayıp, sum_of fonksiyon bloğunun gelen koşullara göre üretilmesini de
38- sağlayabiliriz.
35+ ** max_of_two**  fonksiyonu iki tam sayı değerden hangisi büyükse onu geriye döndürmek amacıyla tasarlanmıştır. Ancak n
36+ adet sayının birbiriyle karşılaştırılması istendiğinde fonksiyonun farkı bir versiyonunun yazılması gerekir. Bunun
37+ yerine bir makro hazırlayıp, ** max_of**  fonksiyon bloğunun gelen koşullara göre üretilmesini sağlanabilir.
3938
4039``` rust 
4140macro_rules!  max_of  {
@@ -66,21 +65,22 @@ mod tests {
6665}
6766``` 
6867
69- Declarative yani bildirime dayalı makrolar yazmak için macro_rules isimli başka bir makro kullanılır. Kendi yazdığımız
70- makrolar dahil isimlendirmelerde fonksiyon adı ! işareti ile sonlandırılır. Örnekte bazı özel kalıpları kullanılmıştır.
68+ Declarative yani bildirime dayalı makrolar yazmak için ** macro_rules**  isimli başka bir makro kullanılır. Kendi
69+ yazdığımız makrolar dahil isimlendirmelerde fonksiyon adı ** !**  işareti ile sonlandırılır. Örnekte bazı özel kalıplar
70+ kullanılmıştır.
7171
72- -  ($x: expr ) => { $x } : Tek bir argüman ile çalışılacağını belirtir. expr ile bir expression türü ifade edilir.
72+ -  ($x: expr ) => { $x } : Tek bir argüman ile çalışılacağını belirtir. ** expr**  ile bir ** expression**  türü ifade edilir.
7373  Dolayısıyla makronun uygulandığı yapıda tek bir sayısal ifade varsa doğrudan döndüren bir kod bloğu üretilecektir.
74- -  ($x: expr , $y: expr ) => { ... } : Bu kısımda ise iki argümanla eşleşilen durumu  ele alır. Burada if  kullanılan bir kod
74+ -  ($x: expr , $y: expr ) => { ... } : Bu kısımda ise iki argümanla eşleşilen durum  ele alınır.  ** if **  kullanılan bir kod
7575  bloğunun üretimi sağlanır.
7676-  ($x: expr , $($y: expr ),+) => { ... } : Bu kalıpsa iki veya daha fazla argüman için geçerlidir. İkinci söz diziminde yer
77-   alan +  operaötörü en az bir veya daha fazla anlamındadır . Bu durumla karşılaşılması halinde recursive olarak kendisini 
78-   çağıran bir fonksiyon kodu üretilecektir .
77+   alan ** + **  operaötörü en az bir veya daha fazla anlamına gelir . Bu durumla karşılaşılması halinde ** recursive**  olarak
78+   kendisini  çağıran bir fonksiyon kodu üretilir .
7979
8080## MetaSyntactic Variables  
8181
82- Makrolarda ifadeleri analiz etmek ve eşleşmeleri yakalamak için token'lar kullanılır. Bunlardan en çok kullanılanlar 
83- aşağıdaki tabloda belirtilmektedir .
82+ Makrolarda ifadeleri analiz etmek ve eşleşmeleri yakalamak için ** token** 'lar kullanılır. En sık kullanılan token 
83+ değerleri  aşağıdaki tabloda özetlenmiştir .
8484
8585|  Token     |  Açıklama                                                              |  Örnek                                             | 
8686| -----------| -----------------------------------------------------------------------| ---------------------------------------------------| 
@@ -97,8 +97,8 @@ aşağıdaki tabloda belirtilmektedir.
9797
9898## Örnekler  
9999
100- Aşağıdaki kod parçalarında farklı senaryoların ele alındığı procedural makrolar  yer almaktadır. İlk örnek bir model 
101- nesnesi için gerekli struct'ı  kolayca oluşturmak  için kullanılır.
100+ Aşağıdaki kod parçalarında farklı senaryoların ele alındığı ** procedural**  makro örnekleri  yer almaktadır. İlk örnek bir
101+ model  nesnesi için gerekli struct'ın  kolayca oluşturulması  için kullanılır.
102102
103103``` rust 
104104macro_rules!  crud  {
@@ -139,12 +139,13 @@ mod tests {
139139}
140140``` 
141141
142- Örneğin Product, Customer, Order, Category ve benzeri entity nesnelerinin yer aldığı bir senaryoda her birisi için ayrı
143- ayrı struct geliştirmek yerine bir makro ile kod tekrarlarının önüne geçebilir, veri yapılarını basitçe
144- tanımlayabiliriz. crud isimli makro argüman olarak gelen identifier ve type bilgilerini kullanarak struct'ın temel
145- halini inşa eder ve aynı zamanda new metodunu otomatik olarak implemente eder.
142+ Örneğin ** Product** , ** Customer** , ** Order** , ** Category**  ve benzeri entity nesnelerinin yer aldığı bir senaryoda her
143+ biri için ayrı ayrı ** struct**  yazmak yerine bir makro ile kod tekrarlarının önüne geçebilir. ** crud**  isimli makro
144+ argüman olarak gelen ** identifier**  ve ** type**  bilgilerini kullanarak ** struct** 'ın temel halini inşa eder ve aynı
145+ zamanda ** new**  metodunu da otomatik olarak implemente eder. Bu senaryo veri model nesnelerinin farklı kaynaklardan
146+ geldiği _ (örneğin metin tabanlı dosyalar)_  durumlarda kullanışlı olabilir. Bunu araştırıp deneyiniz.
146147
147- Sıradaki örnek  makro bir kod bloğunun çalışma süresini ölçümlemekte  kullanılır.
148+ Sıradaki makro bir kod bloğunun çalışma süresini ölçümlemek için  kullanılır.
148149
149150``` rust 
150151macro_rules!  wt  {
@@ -175,11 +176,11 @@ mod tests {
175176}
176177``` 
177178
178- Örnekteki makro $block ifadesi ile aslında bir kod bloğunu ele alır. Bu bloğun öncesine bir sayaç yerleştirir ve son
179- olarak da çıktıyı terminal ekranına basar. println! kullanımı demo ve öğrenim senaryoları için yeterlidir ancak makronun 
180- bir kütüphane üzerinden kullanıma açışması söz konusu olacaksa  terminal bağımsız çalışan kısacası stdout üzerinden çıktı 
181- veren bir hale getirilmesi daha doğru olur . Bu, makronun biraz daha farklı yazılmasını gerektirebilir. Aşağıdaki kod 
182- parçasında bu durum ele alınmaktadır.
179+ Örnekteki makro ** $block**  ifadesi ile aslında bir kod bloğunu ele alır. Bu bloğun öncesine bir sayaç yerleştirir ve son
180+ olarak da çıktıyı terminal ekranına basar. ** println!**  kullanımı demo ve öğrenim senaryoları için yeterlidir ancak
181+ makronun  bir kütüphane üzerinden kullanıma açışması söz konusu ise  terminal bağımsız çalışan kısacası ** stdout** 
182+ üzerinden çıktı  veren bir hale getirilmesi daha doğrudur . Bu, makronun biraz daha farklı yazılmasını gerektirebilir.
183+ Aşağıdaki kod  parçasında bu durum ele alınmaktadır.
183184
184185``` rust 
185186macro_rules!  wt_with  {
@@ -211,17 +212,19 @@ mod tests {
211212}
212213``` 
213214
214- Makroya parametre atandığına dikkat edilmelidir. Bu bir nevi writeln! çağrısının hangi ortama yapılacağının
215- soyutlanmasıdır. Test metodundaki gibi stdout verilmesi, bilginin terminaldeki test çıktısına yansıtılmasını sağlar.
215+ Makroya parametre atandığına dikkat edilmelidir. Bu, bir nevi ** writeln!**  çağrısının hangi ortama yapılacağının
216+ soyutlanmasıdır. ** Test**  metodundaki gibi ** stdout**  verilmesi, bilginin terminaldeki test çıktısına yansıtılmasını
217+ sağlar.
216218
217219![ Macro Test Result] ( MacroTestResult.png ) 
218220
219- Dolayısıyla çıktının writeln! makrosunu kullanabilen bir logger'a, network stream'a veya bir veritabanına aktarılması da
220- mümkündür. _ (Bu durum C#, Java gibi dillerdeki bileşen bağımlılıklarının metotlar üzerinden enjekte edilerek
221- kullanılmasına da benzetilebilir. Daha detaylı bilgi için Dependency Injection konusuna bakılabilir)_ 
221+ Dolayısıyla çıktının ** writeln!**  makrosunu kullanabilen bir ** logger**  nesnesine, ** network**  stream'a veya bir
222+ veritabanına aktarılması da mümkündür. _ (Bu durum C#, Java gibi dillerdeki bileşen bağımlılıklarının metotlar üzerinden
223+ enjekte edilerek kullanılmasına da benzetilebilir. Daha detaylı bilgi için ** Dependency Injection**  konusuna
224+ bakılabilir)_ 
222225
223- Devam eden örnekte ise kod bloğu içerisinde gönderilen bir veri yapısının XML çıktısını hazırlayan kodların yazıldığı 
224- bir makro söz konusudur.
226+ Devam eden örnekte ise kod bloğu içerisinde gönderilen bir veri yapısının ** XML**  çıktısını hazırlayan kodların
227+ yazıldığı  bir makro söz konusudur.
225228
226229``` rust 
227230macro_rules!  wt_with  {
@@ -258,13 +261,15 @@ mod tests {
258261
259262## Procedural Macros  
260263
261- Procedural makrolar bir Rust kodundan yararlanarak başka bir rust kodu üretilmesinde sıklıkla kullanılır. TokenStream
262- girdileri ile çalışır. Temelde üç türü vardır. Derive direktifi ile kullanılanlar, attribute olarak kullanılanlar ve
263- fonksiyon stilinde kullanılanlar.
264+ ** Procedural**  makrolar bir Rust kodundan yararlanarak başka bir rust kodu üretilmesinde sıklıkla kullanılır.
265+ ** TokenStream**  girdileri ile çalışır. Bu nedenle dilin genel semantik yapısına ve abstract syntax tree gibi kavramlara
266+ aşina olmakta yarar vardır. Temelde üç tür ** procedural**  makro vardır. ** Derive**  direktifi ile kullanılanlar,
267+ ** attribute**  şeklinde tasarlananlar ve fonksiyon stilinde yazılanlar.
264268
265269![ Procedural Macro Types] ( ProceduralMacros.png ) 
266270
267- Declarative makrolar ile aralarında bazı farklılıklar da vardır. Bunlar aşağıdaki tabloda özetlenmiştir.
271+ ** Procedural**  ve ** Declarative**  makrolar arasında bazı temel farklılıklar vardır. Bunlar aşağıdaki tabloda
272+ özetlenmiştir.
268273
269274|  Özellik                  |  Declarative Macros (` macro_rules! ` )                    |  Procedural Macros                                             | 
270275| --------------------------| --------------------------------------------------------| ---------------------------------------------------------------| 
@@ -275,9 +280,9 @@ Declarative makrolar ile aralarında bazı farklılıklar da vardır. Bunlar aş
275280|  ** Karmaşıklık Yönetimi**  |  Büyük ve karmaşık işleri yönetmek zordur               |  Büyük projelerde karmaşıklığın daha iyi yönetilmesini sağlar  | 
276281|  ** Kapsam**                |  Kod tekrarını azaltma veya basit DSL'ler için idealdir |  Gelişmiş DSL'ler, derive ve attribute işlevleri için idealdir | 
277282
278- Procedural Macro'lar,  proc-macro crate olarak adlandırılan ayrı bir kütüphanede  yazılırlar. Rust söz dizimi üzerinde 
279- TokenStream kullanılarak işlem yapılması bazı durumlarda zorlayıcı olabilir. syn ve quote gibi küfeler genellikle işi 
280- kolaylaştıran enstrümanlar içerirler.
283+ Procedural makrolar,  ** proc-macro**  crate olarak adlandırılan ayrı bir kütüphane formatında  yazılırlar. Rust söz dizimi
284+ üzerinde  ** TokenStream**  kullanılarak işlem yapılması bazı durumlarda zorlayıcı olabilir. ** syn**  ve ** quote**  gibi
285+ küfeler genellikle işi  kolaylaştıran enstrümanlar içerirler.
281286
282287## Örnek Procedural Macro  
283288
@@ -291,14 +296,15 @@ cargo add quote
291296cargo add syn -F full
292297``` 
293298
294- Ardından toml dosyasında bu küfenin bir  procedural macro olarak ele alınması gerektiği bildirilir .
299+ Ardından ** toml**  dosyasında bu küfenin procedural bir  macro kütüphanesi  olarak ele alınması gerektiği belirtilir .
295300
296301``` toml 
297302[lib ]
298303proc-macro  = true 
299304``` 
300305
301- Aşağıda kodun çalışma zamanının ölçen bir işlevselliğin procedural macro olarak nasıl yazılabileceği örneklenmektedir.
306+ Aşağıda kodun çalışma zamanını ölçen bir işlevselliğin ** procedural macro**  olarak nasıl yazılabileceği
307+ örneklenmektedir.
302308
303309``` rust 
304310extern  crate  proc_macro;
@@ -325,15 +331,16 @@ pub fn work_time_effort(_attr: TokenStream, item: TokenStream) -> TokenStream {
325331}
326332``` 
327333
328- İlgili makro parametre olarak TokenStream'ler alır. Özellikle item değişkeni kod içerisinde kullanılır. item değişkeni
329- ile gelen TokenStream parse_macro_input! makrosu kullanılarak içeriği ele alınabilir bir türe dönüştürülür. Buradan
330- hareketle makronun uygulandığı metodun adı ve gövdesi yakalanbilir.
334+ İlgili makro parametre olarak ** TokenStream** 'ler alır. Özellikle ** item**  değişkeni kod içerisinde kullanılır. item
335+ değişkeni ile gelen ** TokenStream** , ** parse_macro_input!**  makrosu kullanılarak içeriği ele alınabilir bir türe
336+ dönüştürülür. Bir başka deyişle stream üzerinden gelen kod içerisindeki unsurlar özellik şeklinde ele alınabilir hale
337+ gelir. Buradan hareketle makronun uygulandığı metodun adı ve gövdesi yakalanmaktadır.
331338
332- İlerleyen adımda quote! makrosu ile yeni bir fonksiyon hazırlanır. Dikkat edileceği üzere gelen fonksiyon bloğunun
339+ İlerleyen adımda ** quote!**  makrosu ile yeni bir fonksiyon hazırlanır. Dikkat edileceği üzere gelen fonksiyon bloğunun
333340öncesine ve sonrasına yeni kod parçaları eklenmektedir. Makro çıktı olarak üretilen yeni kod parçasını yine bir
334- TokenStream olarak dışarı verir.
341+ ** TokenStream**  olarak dışarı verir.
335342
336- Bu makro herhangibir  metot için aşağıdaki gibi kullanılabilir.
343+ Bu makro herhangi bir  metot için aşağıdaki gibi kullanılabilir.
337344
338345``` rust 
339346mod  samples ;
@@ -354,8 +361,8 @@ fn main() {
354361}
355362``` 
356363
357- Bir procedural macro küfesini kullanmak için ilgili projeye dependency olarak bildirilmesi gerekir. Bunun için toml 
358- dosyasındaki ilgili kısım değiştirilmelidir. Örneğin, 
364+ Bir procedural macro küfesini kullanmak için ilgili projeye ** dependency**  olarak bildirilmesi gerekir. Bunun için makro 
365+ kütüphanesini kullanacak projenin  ** toml **  dosyasında aşağıdaki gibi bir değişiklik yapılmalıdır. 
359366
360367``` toml 
361368[dependencies ]
0 commit comments