2012-01-13 29 views
5

"Aralık adımı" operatörünü (.. ..) kullanmak/aşırı yüklemekle ilgileniyorum, ama nasıl kullanacağımı öğrenemiyorum. o. o "açıkça" mümkündür çağıran AncakF # (.. ..) kullanıcı ismi/aşırı yükleme

> let x = 1 .. 2 .. 7;; 

    let x = 1 .. 2 .. 7;; 
    ----------^^ 

stdin(54,11): error FS0010: Unexpected symbol '..' in binding. Expected incomplete structured construct at or before this point or other token. 

: belgelerinde

o

// Usage: 
start .. step .. finish 

ancak F # kabuğunda olduğu çalışırken hatalar verir diyor

> let x = (.. ..) 1 2 7;; 

val x : seq<int> 

Bu operatörün sadece [1..2..7] vegibi liste/seri yapı için kullanılması mümkün mü??

cevap

1

spec § 6.3.12, bununla ilgili açık değildir, ancak verilen tek örnek, dizi ifadeleri içerisindedir. Bu, başka hiçbir şeyin işe yaramadığı gerçeğiyle birlikte, sonucunuzu teyit ediyor gibi görünüyor.

FYI - Aralıklı işleçler için ilgili dokümanlar.

Operators.(..)<^T>
Operators.(.. ..)<^T,^Step>

Section 3.8.2

da (.. ..) ait özel işlem bahseder, bu yüzden ayrı tipik işlevleri/operatörlerin olanlardan sınırlamalar/davranışa konu varsaymak güvenlidir.

+0

kabul edilen yanıt olarak bu işaretleme En hızlı olduğu ve diğerlerinin daha fazla bilgi içermediği için. “(.. ..)' sadece “seq {...}' içinde yaşayabilir gibi görünüyor. - Benim için spec okumak için teşekkürler ;-) – uhrm

2

Bu işlevin kullanımları section 6.3.12 of the spec (Aralık İfadeleri) kapsamındadır. (.. ..) operatör uygun (+) ve Zero üyeleri ile her türlü çalışır, ancak o başka bir şey yapmak yeniden tanımlayabilirsiniz yerleşik (bu örnek saçma olduğuna dikkat edin):

let (.. ..) x y z = 
    Seq.map (fun (s:string) -> s.[z] + y) x 

let result = seq { ["test"; "func"] .. (char 1) .. 2 } // contains 't' 'o' 
2

ağır basan (... .) işleci

@ kvb'nin yanıtında olduğu gibi (.. ..) operatörünü yeniden tanımladıysanız, bu işleç her türden geçersiz kılacaktır. Muhtemelen (.. ..) operatörünün özel bir veri türü için çalışmasını istiyorsanız, statik (+) ve One üyelerini geçersiz kılmak yeterlidir. Örneğin, aşağıda @Tomas's blog alınan modüler aritmetik için özel sayısal türüdür:

type IntegerZ5 = 
    | Z5 of int 
    member z.ToInt32() = 
    let (Z5 n) = z in n 
    override z.ToString() = 
    sprintf "%d (mod 5)" (z.ToInt32()) 

    static member Create(n) = 
    let z5 = n % 5 
    Z5(max ((z5 + 5) % 5) z5) 
    static member (+) (Z5 a, Z5 b) = IntegerZ5.Create(a + b) 
    static member (-) (Z5 a, Z5 b) = IntegerZ5.Create(a - b) 
    static member (*) (Z5 a, Z5 b) = IntegerZ5.Create(a * b) 
    static member Zero = Z5 0 
    static member One = Z5 1 

    let inline z5 a = IntegerZ5.Create(a) 

(+) ve One sonraki maddeyi bulmak için kullanılır, alt sınır bir dizi başlangıç ​​inşa ederken. Bir sonraki elemanın menzilin üst sınırına eşit veya bu sınırı aştığı zaman, inşaat tamamlanır. Artık herhangi aralık ifadesinde IntegerZ5 istihdam edebilirsiniz:

let s1 = seq{z5 37..z5 3};; // seq [Z5 2; Z5 3] 
    let s2 = seq{z5 10..z5 22..z5 4};; // seq [Z5 0; Z5 2; Z5 4] 

Kullanma (.. ..) operatörü

aralığı ifade Başka bir kullanım for döngüler bulunmaktadır.Ben yararlı birçok durumda bulabilirsiniz:

let sum = 
    let mutable s = 0L 
    for i in 1L..1000L do (* or 1L..1L..1000L with an explicit step *) 
     s <- s + i 
    s 

sadece int sınırlıdır for...to..do daha esnektir ve 1 bir adımla bir dizi ima çünkü:

let sum = 
    let mutable s = 0L 
    for i = 1L to 1000L do (* doesn't work *) 
     s <- s + i 
    s 
+0

Bu özellikle, spec göre, birçok durumda basit bir for döngüsüne tercüme edildiğinden, güzel bir kullanım. – Daniel

+0

... ve 1 'e eşit olmayan açık bir adım ile aralık ifadeleri için çalışır, örneğin 1I..2I..100I için printf "% A" i' –

+0

yapar. Bu yüzden daha esnek olduğunu söyledim. – pad