2014-12-29 18 views
15

Na bardzo wczesnym etapie nauki języka i pracy w serii filmów ElixirSips. Ciągle uderzam w rzeczy, które zostały nieznacznie zmienione przez zmiany językowe. Próbuję to sobie zawikłać, a śledzenie problemów w wyszukiwarce Google/Github/SO jest dla mnie nigdzie nieprzydatne. Mam to bardzo podstawowy moduł, który należy po prostu uruchomić polecenie powłoki:Wykonywanie podstawowego polecenia powłoki w Elixir

defmodule QuickieSynth.Sound do 
    def command(note) do 
    "play -qn synth 2 pluck #{note}" 
    end 

    def play(note) do 
    note |> command |> System.cmd 
    end 
end 

Jednak, gdy plik ten jest skompilowany i uruchomić testy, pojawia się błąd argumentu; Wystarczająco fair - System.cmd/1 nie jest już częścią standardowej biblioteki lib.

System.cmd/3 to w standardowej bibliotece i czytanie dokumentów wskazało, że opcje są opcjonalne. Tak więc przekazuję puste argumenty: note |> command |> System.cmd([]), a to, co otrzymuję, to erlang: :enoent: ponownie po przeczytaniu dokumentów nieco ostrożniej, sprawiedliwie.

Więc próbuję użyć Erlanga w wersji :os.cmd/1, więc note |> command |> :os.cmd, a otrzymam (FunctionClauseError) no function clause matching in :os.validate/1. A teraz utknąłem.

+2

piszę inną funkcję, aby tę pracę Tutorial na ostatnich wersjach Elixir: 'def uruchomić (full_cmd) do [cmd | args] = String.split (full_cmd, "") System.cmd (cmd, args) end' – ghayes

Odpowiedz

29

System.cmd/3 wydaje się przyjmować argumenty do polecenia jako listę i nie jest szczęśliwy, gdy próbuje się wkraść w argumenty w nazwie polecenia. Na przykład działa System.cmd("ls", ["-al"]), natomiast System.cmd("ls -al", []) nie. Więc w twoim przypadku będzie potrzebne coś takiego:

System.cmd("play", ["-qn", "synth", "2", "pluck", note]) 

co w rzeczywistości dzieje się pod spodem jest System.cmd/3 rozmowy :os.find_executable/1 z pierwszym argumentem, który działa dobrze na coś takiego ls ale zwraca false dla ls -al na przykład.

Wezwanie Erlang spodziewa listę char zamiast binarnego, więc trzeba coś jak następuje:

"ls -al" |> String.to_char_list |> :os.cmd 
+1

Ah, to ma sens. Będę i tak chciał zbudować opcje, więc to był pierwszy podstawowy krok, który mnie potknął; Nie mogę tego zrobić w taki sposób, w jaki próbowałem. BTW, jakikolwiek pomysł, dlaczego wywołanie Erlangu nie zadziała (: os.cmd)? – DanCouper

+1

Dodano do odpowiedzi –

+1

Dziękuję, to świetnie. – DanCouper

Powiązane problemy