2015-02-17 26 views
7

Neden bir yineleme işlevini değişken olarak tanımlayamıyorum? Nüks ettikleri zamanlar dışında keyfi işlevleri tanımlayabiliyorum.Golang işlevi ve işlev değişkeni semantiği

Bu yasaldır:

func f(i int) int { 
    if i == 0 { 
     return 1 
    } 
    return i * f(i-1) 
} 

func main() { 
    fmt.Println(f(2)) 
} 

Bu yasa dışıdır:

var f func(int) int = func(i int) int { 
    if i == 0 { 
     return 1 
    } 
    return i * f(i-1) 
} 

func main() { 
    fmt.Println(f(2)) 
} 

Bu yasal ve ben bunu başlatmasından sonra f anlamaya çünkü sadece tahmin ediyorum:

func main() { 
    var f *func(int) int; 
    t := func(i int) int { 
     if i == 0 { 
      return 1 
     } 
     return i * (*f)(i-1) 
    } 
    f = &t 
    fmt.Println((*f)(2)) 
} 

İşlevsel olarak işlev görüyor gibi görünüyor ve bir işlev türünün değişken bildirimleri farklı bir şekilde ele alınır. Okumaktan öte, belgenin okunmasını beklemiyordum. Bunu detaylandıran belgelerin bir kısmını özledim mi?

Yasadışı davanın sadece başka dillerde çalıştığı için çalışmasını beklerim. JavaScript'te olduğu gibi:

(function() { 
    var f = function (i) { 
    if (i == 0) { 
     return 1; 
    } 
    return i * f(i - 1); 
    }; 

    console.log(f(2)); 
})(); 
+3

Git JavaScript değildir. Javascript kodunuza bakar ve "bu iyi görünüyor, henüz ne olduğunu bilmiyorum, ama muhtemelen bu bloğun çağrıldığı andan itibaren" diyor ve sonra işlevi "f" değişkenine atar ve herşey iyi. Go, onu aramadan önce kodla karşılaşmadan önce ne olduğunu bilmek istiyor. –

+0

Neler oluyor ama gerçekten nedenini söylemiyor. Go, 'f' işlev olarak bildirilirse ancak' f' işlev türü değişkeni olarak bildirilip bildirilmediğini bilmek isterse, 'f' nedir bilmek istemez. Bu garip olan şey. –

cevap

21

Aşağıdaki kod, açıkladığınız şeyi yapmanın tercih edilen yolu olacaktır. Eğer ek bir değişken oluşturmak zorunda olmadığını unutmayın, ne de bir işleve bir işaretçi var:

package main 

import "fmt" 

func main() { 
    var f func(int) int 
    f = func(i int) int { 
     if i == 0 { 
      return 1 
     } 
     return i * f(i-1) 
    } 
    fmt.Println(f(2)) 
} 
+0

Teşekkürler, bu çok daha iyi bir çalışma çözümü. Bunu gösteren bazı belgeler umuyorum. İşlev türlerinin işlev ve değişkenlerinin çok farklı olduğu çok garip görünmektedir. –

+2

@DanielWilliams: [Özellik] 'den (https://golang.org/ref/spec#Declarations_and_scope): * Bir işlev içinde bildirilen bir sabit veya değişken tanımlayıcının kapsamı, ConstSpec veya VarSpec'in sonunda başlar (ShortVarDecl for kısa değişken bildirimleri) ve en içteki bloğun sonunda biter. * Bu, f tanımlayıcısının, değer tam olarak tanımlanana kadar geçerli olmadığı anlamına gelir. Bu yüzden Go’da JavaScript’te yaptıklarınızı yapamazsınız. –