2014-05-13 10 views
7

In statisch typisierten Sprachen mit Generika, wie C#, kann ich in der Methodensignatur angeben, dass jeder der Schlüssel der Map ein Atom ist und jeder Wert eine Liste von {string, int} ist Tupel. Wie definiere ich die Typspezifikation für Funktionsargumente wie in Elixir?Elixier: Typspezifikation für Maps/Hashdicts definieren

PS: Wenn Sie dies lesen und eine Bewertung von> 1500 haben, könnten Sie bitte ein Typenspezifikations-Tag erstellen.

+0

ich mit Elixier nicht vertraut bin, aber es behauptet, eine "dynamische Sprache" zu sein, was normalerweise bedeutet, dass es kein formales System gibt. Also ... benutze einen Kommentar? – luqui

+4

es hat Typ Spezifikationen, die von der statischen Analyse-Tool verwendet werden können Dialyzer - http://elixir-lang.org/docs/stable/Kernel.Typespechtml – tldr

Antwort

12

Sie würden es wie so definieren:

@type bar :: %{atom => [{binary, integer}]} 

@spec foo(bar) :: bar 
def foo(bar), do: bar 

Die oben definiert eine neue Art, die auf Listen von binären/integer Tupeln Ihre Karte Atom Schlüssel ist, und verwendet dann diese Art in der Art Spezifikation für foo.

+0

nur um sicher zu sein, muss ich es als ein Typ angeben vorher kann ich es nicht einfach inline? Wenn ja, sollte ich alle meine benutzerdefinierten Typen in einem separaten Modul behalten und sie nur importieren, um zu vermeiden, dass die Typdefinition in mehrere Module kopiert wird? – tldr

+2

Sie können es definitiv inline, aber ich finde es schwierig zu lesen, wenn Sie mehrere komplexe Typen alle inline haben. Es ist auch ein wenig expliziter über * was * der Typ ist, anstatt nur die Struktur davon. Sie können Typen in anderen Modulen definieren und über 'Module.type_name' verwenden. – bitwalker

+0

toll, danke! In diesem Sinne ist die statische Analyse von Elixir granularer als die von Go, da Go keine Funktionen definiert, die Ihre benutzerdefinierten Typen als Argumente verwenden. (Nicht zu beachten, wenn Sie Go nicht benutzt haben) – tldr

1

Für Inline-Spezifikation geht es wie folgt aus:

defmodule LousyCalculator do 
    @spec add(number, number) :: {number, String.t} 
    def add(x, y), do: {x + y, "You need a calculator to do that?!"} 

    @spec multiply(number, number) :: {number, String.t} 
    def multiply(x, y), do: {x * y, "Jeez, come on!"} 
end 

Wenn Sie eine Struktur erwarten dann ist der Typ:

@spec struct_returner_and_getter(%Struct_name1{}) :: %Struct_name2{} 

Quelle: http://elixir-lang.org/getting-started/typespecs-and-behaviours.html