Zadeklaruj stałą tablicę

164

Próbowałem:

const ascii = "abcdefghijklmnopqrstuvwxyz"
const letter_goodness []float32  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness = []float32 { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }

Po pierwsze, deklaracja i inicjalizacja działają dobrze, ale druga, trzecia i czwarta nie działają. Jak mogę zadeklarować i zainicjować tablicę const wartości zmiennoprzecinkowych?

demas
źródło

Odpowiedzi:

232

Tablica nie jest z natury niezmienna; nie możesz tego uczynić stałym.

Najbliższy możliwy do uzyskania to:

var letter_goodness = [...]float32 {.0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }

Zwróć uwagę na [...]zamiast []: zapewnia to otrzymanie tablicy (o stałym rozmiarze) zamiast wycinka. Więc wartości nie są stałe, ale rozmiar jest.

Denys Séguret
źródło
126
Dla wyjaśnienia: [...]Tskładnia to cukier [123]T. Tworzy tablicę o stałym rozmiarze, ale pozwala kompilatorowi dowiedzieć się, ile elementów się w niej znajduje.
jimt
5
Wydaje mi się, że zezwolenie na stałe tablice wymagałoby aktualizacji systemu typów. W przeciwnym razie, gdybyś zdefiniował funkcję f(xs [5]int), nie wiedziałbyś, czy przekazana tablica była stała czy zmienna.
Thomas Ahle,
TKS, mam problemy przy próbie strings.Join cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
Eddy Hernandez
Dzięki za rozwiązanie plasterka. Wątpliwość: sama tablica jest niezmienna, prawda? Nie można dodawać ani usuwać elementów po utworzeniu tablicy, prawda? Mogę jednak edytować elementy tablicy.
legends2k
@ legends2k Nie możesz zmienić rozmiaru tablicy, tak, ale możesz umieścić inne wartości w jej slotach.
Denys Séguret
63

Od Effective Go :

Stałe w Go są po prostu takie - stałe. Są tworzone w czasie kompilacji, nawet jeśli są zdefiniowane jako lokalne w funkcjach i mogą być tylko liczbami, łańcuchami znaków lub wartościami logicznymi. Ze względu na ograniczenie czasu kompilacji wyrażenia, które je definiują, muszą być wyrażeniami stałymi, możliwymi do oszacowania przez kompilator. Na przykład 1 << 3 jest wyrażeniem stałym, podczas gdy math.Sin (math.Pi / 4) nie jest wynikiem wywołania funkcji math.Sin w czasie wykonywania.

Plasterki i tablice są zawsze oceniane w czasie wykonywania:

var TestSlice = []float32 {.03, .02}
var TestArray = [2]float32 {.03, .02}
var TestArray2 = [...]float32 {.03, .02}

[...]mówi kompilatorowi, aby obliczył długość samej tablicy. Plasterki zawijają tablice i w większości przypadków są łatwiejsze w użyciu. Zamiast używać stałych, po prostu spraw, aby zmienne były niedostępne dla innych pakietów, używając małej pierwszej litery:

var ThisIsPublic = [2]float32 {.03, .02}
var thisIsPrivate = [2]float32 {.03, .02}

thisIsPrivatejest dostępny tylko w zdefiniowanym pakiecie. Jeśli potrzebujesz dostępu do odczytu z zewnątrz, możesz napisać prostą funkcję getter (zobacz Getters w golang ).

fasmat
źródło
12

W Go nie ma czegoś takiego jak stała tablicowa.

Cytowanie ze specyfikacji języka Go: Stałe :

Stałe logiczne , runiczne stałe , stałe całkowite , stałe zmiennoprzecinkowe , złożone stałe i stałe łańcuchowe . Stałe runiczne, całkowite, zmiennoprzecinkowe i złożone nazywane są łącznie stałymi numerycznymi .

Wyrażenie stałe (które jest wykorzystywane do inicjowania stałej) może obejmować jedynie ciągłe operandy i oceniane są w czasie kompilacji.

Specyfikacja zawiera listę różnych typów stałych. Zauważ, że możesz tworzyć i inicjować stałe za pomocą stałych wyrażeń typów mających jeden z dozwolonych typów jako typ bazowy . Na przykład jest to ważne:

func main() {
    type Myint int
    const i1 Myint = 1
    const i2 = Myint(2)
    fmt.Printf("%T %v\n", i1, i1)
    fmt.Printf("%T %v\n", i2, i2)
}

Wyjście (wypróbuj na Go Playground ):

main.Myint 1
main.Myint 2

Jeśli potrzebujesz tablicy, może to być tylko zmienna, ale nie stała.

Polecam ten świetny artykuł na blogu o stałych: Stałe

icza
źródło
co zrobić, jeśli potrzebujesz pojemnika o stałym rozmiarze?
@Atomic_alarm Czy możesz coś rozwinąć?
icza
Czy istnieje w analogowej tablicy C golang?
@Atomic_alarm Tak, tablice też istnieją w Go, po prostu nie są one stałymi wyrażeniami, są obliczane w czasie wykonywania. Zatem stała nie może być tablicą, ale zmienna może. Na przykład:var arr = [2]int{2, 3}
icza
3

Jak wspominali inni, nie ma do tego oficjalnej konstrukcji Go. Najbliższa, jaką mogę sobie wyobrazić, byłaby funkcja zwracająca wycinek. W ten sposób możesz zagwarantować, że nikt nie będzie manipulował elementami oryginalnego wycinka (ponieważ jest on „na stałe zakodowany” w tablicy).

Skróciłem twój kawałek, żeby był ... krótszy ...:

func GetLetterGoodness() []float32 {
    return [...]float32 { .0817,.0149,.0278,.0425,.1270,.0223 }
}
Paweł
źródło
4
wydaje się, że jest to najlepsza droga, jednak typ zwrotu func nie pasuje. cannot use [6]string literal (type [6]string) as type []string in return argumentwięcreturn []float32 { ... }
theRemix
@theRemix Trzy możliwe poprawki: (1) usuń ..., aby zadeklarować literał wycinka zamiast literału tablicowego. (2) zmień typ powrotu na [6]float32. (3) ekspresja przypisać do zmiennej tablicowej a := [...]float32 { (etc.) }i powrót plaster wszystkich elementów: return a[:]. (Literały tablicowe nie są adresowalne, nie jestem pewien dlaczego.)
David Moles
Nie jestem pewien, jakie gwarancje masz na myśli. Wygląda na to, że próbujesz rozwiązać coś w swoim kodzie, co prawdopodobnie jest lepiej rozwiązane za pomocą testów (jednostkowych).
Dynom