C#では、次のようなことができます。
var a = new {name = "cow", sound = "moooo", omg = "wtfbbq"};
Pythonでは、次のようなことができます。
a = t(name = "cow", sound = "moooo", omg = "wtfbbq")
もちろんデフォルトではありませんが、クラスを実装するのは簡単ですt
それができます。私がPythonで作業していたとき、私はまさにそれをしました、そしてそれはあなたがインデックスではなく名前でコンポーネントにアクセスすることができるようにしたい小さな使い捨てコンテナのために信じられないほど便利であると思いました。
それ以外の細部を除けば、それらは基本的に彼らが仕えるニッチのタプルと同じです。
特に、私は今、このC#コードを見ています。
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
それはF#相当です
type Route = {
controller : string
action : string
id : UrlParameter }
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
{ controller = "Home"; action = "Index"; id = UrlParameter.Optional } // Parameter defaults
)
どちらかといえば冗長で反復的で、どちらかといえば面倒です。 F#のこの種の構文にどれだけ近づくことができますか。それがそれが私にこのようなコードを乾燥させるのに役に立つ何かを与えるだろうという意味なら今私はいくつかのフープ(燃えるようなフープさえ!)を飛び越えても構わない。
やりやすい
let route = routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}" // URL with parameters
)
route.Defaults.Add("controller", "Home")
route.Defaults.Add("action", "Index")
または
[ "controller", "Home"
"action", "Index" ]
|> List.iter route.Defaults.Add
F#では、匿名型を受け入れるオーバーロードを呼び出すことは避けますFSharpList
C#から。これらは言語固有の機能です。通常、言語に依存しない過負荷/回避策があります。
ドキュメントを見ただけです - これを実行するもう1つの方法があります
let inline (=>) a b = a, box b
let defaults = dict [
"controller" => "Home"
"action" => "Index"
]
route.Defaults <- RouteValueDictionary(defaults)
Add
- 私は私のASP.NET MVCサンプルでもそれを使うべきです! - Tomas Petricek
F#で "匿名レコード"を作成することはできません。型を使用するときは、匿名でタプルを使用せずにラベルを付けることも、事前に宣言してラベルを付けるレコードを使用することもできます。
// Creating an anonymous tuple
let route = ("Home", "Index", UrlParameter.Optional)
// Declaration and creating of a record with named fields
type Route = { controller : string; action : string; id : UrlParameter }
let route = { controller = "Home"; action = "Index"; id = UrlParameter.Optional }
技術的には、匿名レコードの問題はそれらが実際のクラスとして定義されなければならないということです。どこかに(.NETランタイムには型が必要です)しかし、コンパイラがそれらをすべてのアセンブリに入れると、同じメンバを持つ2つの無名レコードが異なるアセンブリで定義されている場合、それらは異なる型になる可能性があります。
正直に言って、あなたが投稿した例はASP.NETの設計上の不適切な決定にすぎないと思います - それは設計されていない何かをするために特定のC#機能を誤用しているためです。それほど悪くないかもしれませんこのしかし、それはまだ変です。このライブラリはC#の匿名型を取りますが、辞書として使用します(つまり、指定する必要があるプロパティが動的であるため、キーと値のペアを作成するための良い方法として使用します)。
そのため、F#からASP.NETを使用している場合は、レコードを作成する必要がない場合に代替アプローチを使用する方がおそらく簡単です。それを書く方法)。
IDictionary
より良い選択のようです。 F#ではそれはdict ["controller", "Home"; "action", "Index"]
- とても自然 - Danielnew Dictionary<string, object> { { "controller", "Home" }, { "action", "Index" } }
対new { controller = "Home", action = "Index" }
(そして、C#ではもっと悪くならない解決策を具体的に求めていました) - Kirk WollIDictionary
C#ではより明確または短いですが、いくつかの言語がCLRをターゲットにしていることを考えると、これはより良いアプローチ(幸せな媒体)です。匿名型はC#固有のものです。 - Danieldefaults
パラメータの型はobject
「デフォルトルート値を含むオブジェクト」の説明付き。呼び出し側としては、ライブラリで使用されている非常に慣用的なスタイルの例を見たことがない限り、これはまったく不可解です。私には、これは、F#にはないC#機能の積極的な使用ではなく、C#が簡潔なコレクションリテラルをサポートできないことに対する回避策の兆候です。 - kvb
OPは匿名型の最良の使用法を説明していません。 LINQを使って任意のクラスにマッピングするときに最もよく使われます。例えば:
var results = context.Students
.Where(x => x.CourseID = 12)
.Select(x => new {
StudentID = x.ID,
Name = x.Forename + " " + x.Surname
});
これは新しいレコードタイプを定義することで実現できることを私は知っていますが、コードを管理する場所は2つあります。(1)レコードタイプの定義(2)使用した場所。
代わりにタプルで実行することもできますが、個々のフィールドにアクセスするには分解構文を使用する必要があります。(studentId, name)
ずっと。タプルに5つのアイテムがあると、これは扱いにくくなります。入力したいx
そしてドットを打って、どのフィールドが利用可能であるかをインテリセンスに教えてもらってください。
これがデフォルトのWebプロジェクトのルート設定です。
module RouteConfig =
open System.Web.Mvc
open System.Web.Routing
let registerRoutes (routes: RouteCollection) =
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
/// create a pair, boxing the second item
let inline (=>) a b = a, box b
/// set the Defaults property from a given dictionary
let setDefaults defaultDict (route : Route) =
route.Defaults <- RouteValueDictionary(defaultDict)
routes.MapRoute(name="Default", url="{controller}/{action}/{id}")
|> setDefaults (dict ["controller" => "Home"
"action" => "Index"
"id" => UrlParameter.Optional])