mixin in Nemerle
Nemerle 0.9.2からProxyPublicMembersマクロがサポートされました。この属性を付けると、オブジェクトの持つpublicなメンバへの委譲が自動生成されます。
using System; using Nemerle.Utility; using Nemerle.DesignPatterns; class Programmer { [Accessor] lang : string; this (lang : string) { this.lang = lang; } public static Create (lang : string) : Programmer { Programmer (lang); } public WriteCode () : void { Console.WriteLine ($"Programming in $lang"); } } class Singer { this () {} public static Create () : Singer { Singer (); } public Sing () : void { Console.WriteLine ("Sing a song."); } } class Dancer { this () {} public static Create () : Dancer { Dancer (); } public Dance () : void { Console.WriteLine ("Dance to the music."); } } class SuperProgrammer { [ProxyPublicMembers] programmer : Programmer; [ProxyPublicMembers] singer : Singer; [ProxyPublicMembers] dancer : Dancer; public this (lang : string) { programmer = Programmer.Create (lang); singer = Singer.Create (); dancer = Dancer.Create (); } } // 歌って踊れるプログラマ def hacker = SuperProgrammer ("C#"); Console.WriteLine (hacker.Lang); hacker.WriteCode (); hacker.Sing (); hacker.Dance (); /* C# Programming in C# Sing a song. Dance to the music. */
ただ、現在のマクロはpublicなコンストラクタまで委譲してしまい、コンストラクタが重複してしまいます。取りあえず、Creation Methodを作って逃げました。
Adapterパターン
Nemerleの特徴を利用して変則的に実装してみました。
using Nemerle.Utility; // 移譲先 public class Banner { text : string; public this (text : string) { this.text = text; } public ShowWithParen () : void { System.Console.WriteLine ($"($text)"); } public ShowWithAster () : void { System.Console.WriteLine ($"*$text*"); } } // アダプタのインタフェース public interface IPrint { // 関数型(≒C#のdelegate)のプロパティを持つ // void -> void は 引数void、戻り値voidの関数を意味する PrintWeak : void -> void { get; } PrintStrong : void -> void { get; } } public class Print : IPrint { banner : Banner; [Accessor] printWeak : void -> void; [Accessor] printStrong : void -> void; public this (text : string) { // Bannerクラスへ委譲 banner = Banner (text); printWeak = banner.ShowWithParen; printStrong = banner.ShowWithAster; } } def print = Print ("Hello"); print.PrintWeak (); print.PrintStrong (); /* 結果 (Hello) *Hello* */
Ranges
List comprehensions内で...を使って範囲指定が出来るようになったみたい。
[ 開始 ... 終了]
または、
[開始, 次の値 ... 終了]
こちらだと、次の値-開始がステップ値になります。ってコード見た方が早いですね。
using System; Console.WriteLine ($[ x | x in [1 ... 10] ]); Console.WriteLine ($[ x | x in [1, 3 ... 10] ]); Console.WriteLine ($[ x | x in [10, 9 ... 1] ]); Console.WriteLine ($[ x | x in [10, 8 ... 1] ]); Console.WriteLine ($[ (x, y) | x in [1 ... 3], y in [2 ... 4], x < y]); /* [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] [1, 3, 5, 7, 9] [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] [10, 8, 6, 4, 2] [(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)] */
リスト内包表記
・List comprehensions
Pythonなどでお馴染みのやつ。ほんと、何でもサポートするなぁ。(^^;
yieldその後
結構、使えるようになってきた?
using System; using System.Collections.Generic; class Fib : IEnumerable [int] { mutable max = 0; public this (n : int) { max = n; } public GetEnumerator () : IEnumerator [int] { mutable (a, b) = (0, 1); while (b < max) { yield b; (a, b) = (b, a + b); } } } foreach (n in Fib (20)) Console.WriteLine (n); /* 1 1 2 3 5 8 13 */