2015-12-01 3 views
7

In einem Paket für eine MongoDB driver, ich brauchte eine Funktion, um eine eindeutige Dokument-ID zu generieren.Erlang: now() in V18 veraltet, was ist der beste Übergang

Diese Funktion verwendet :erlang.now() die

in v18 ist veraltet

ich Hilfe suchen, wie man wandern, aber kein Erfolg.

Meine eigentliche Code (verkürzt):

defmodule MyModule_v17 do 
    use Bitwise, only_operators: true 
    def gen_trans_prefix do 
    {gs, s, ms} = :erlang.now 
    (gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655 
    end 
end 

Beste, was ich kam mit:

defmodule MyModule_v18 do 
    use Bitwise, only_operators: true 
    Kernel.if Keyword.get(:erlang.module_info, :exports) |> Enum.any?(fn({:system_time, 1}) -> true; (_) -> false end) do 
    def gen_trans_prefix do 
     :erlang.system_time(:micro_seconds) &&& 281474976710655 
    end 
    else 
    def gen_trans_prefix do 
     {gs, s, ms} = :erlang.now 
     (gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655 
    end 
    end 
end 

Es macht den Job, aber ich fühle mich nicht es der beste Weg ist.

Irgendwelche Vorschläge?

Antwort

6

Um OTP 17 und 18 (und darüber hinaus) gleichzeitig zu unterstützen, müssen Sie die OTP-Version zum Zeitpunkt der Kompilierung erkennen. Hier ist ein Beispiel aus den rebar.config for the lftpc project:

{erl_opts, [ 
    {platform_define, "(?=^[0-9]+)(?!^17$)", time_correction} 
]}. 

Diese regulären Ausdruck Prüfung funktioniert, weil die Freisetzung von OTP 17 die Verwendung von semantic versioning (oder nahe daran) markiert, so etwas weniger als OTP 17 hat eine Versionsnummer, die beginnt mit R (wie R16).

Dann in Ihrem Erlang Code können Sie so etwas wie this tun:

-ifdef(time_correction). 
gen_trans_prefix() -> 
    {GS, S, MS} = erlang:timestamp(), 
    (GS * 1000000000000 + S * 1000000 + MS) band 281474976710655. 
-else. 
gen_trans_prefix() -> 
    {GS, S, MS} = erlang:now(), 
    (GS * 1000000000000 + S * 1000000 + MS) band 281474976710655. 
-endif. 

Wenn Sie Mix verwenden, können Sie die erlc_options im mix.exs for the jose project als getan definieren:

def erlc_options do 
    extra_options = try do 
    case :erlang.list_to_integer(:erlang.system_info(:otp_release)) do 
     v when v >= 18 -> 
     [{:d, :time_correction}] 
     _ -> 
     [] 
    end 
    catch 
    _ -> 
     [] 
    end 
    extra_options 
end 

Die erlc_options kann durch Erlang oder Elixir-Code für das Projekt referenziert werden (ähnlich der Lösung, die Sie in Ihrer Frage erwähnt haben):

defmodule MyModule do 
    use Bitwise, only_operators: true 
    if Enum.member?(Mix.Project.get!.project[:erlc_options] || [], {:d, :time_correction}) do 
    def gen_trans_prefix do 
     {gs, s, ms} = :erlang.timestamp 
     (gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655 
    end 
    else 
    def gen_trans_prefix do 
     {gs, s, ms} = :erlang.now 
     (gs * 1000000000000 + s * 1000000 + ms) &&& 281474976710655 
    end 
    end 
end 
+0

Vielen Dank für Ihren Beitrag, ich mag die Art, wie Sie es behandelt haben. Ich erstelle einen Repo [jerp/now] (https://github.com/jerp/now), wo ich das, was ich getan habe, am Ende ablege. Es ist nah an Ihrer Antwort – jerome

+0

Auch in einer anderen Sache, ich freue mich, über Erlang-Jose zu erfahren. Ich unterschreibe Nachrichten unter Verwendung eines Ports auf OpenSSL, ich werde Ihr Projekt in naher Zukunft betrachten. – jerome

1

Try this:

erlang:timestamp() 

die eine Alternative zu erlang ist: now() in erlang 18

Check this: http://www.erlang.org/doc/man/erlang.html#timestamp-0

+0

danke aber die Frage ist nicht, wie erlang.now zu ersetzen(), aber was ist der beste Übergang für ein Paket, das sowohl in der Version v17 und v18 arbeiten sollte. 'erlang: timestamp()' existiert nicht in v17 – jerome

+0

Es ist auch kein passender Ersatz, da erlang: timestamp/0 nicht garantiert eindeutig ist wie erlang: jetzt/0 ist, ein wichtiges Merkmal der Frage. – Michael

2

Wenn erlang:now() ist veraltet, aber nicht entfernt in Erlang 18 dann würde ich den Code in Ruhe lassen.

Das ist mein Argument: Wenn Sie neuen Code erstellen, erstellen Sie ihn für Erlang 18 und später und verwenden Sie erlang:timestamp(). Das heißt, wenn Sie neuen Code erstellen, benötigen Sie ihn, um auf Erlang 17 und Erlang 18 laufen zu können? Wahrscheinlichkeiten sind, wenn es neuer Code ist, kannst du nur vorschreiben, dass es nur auf 18 ausgeführt wird. Und wenn du Code behaltest und erlang:now() in 18 noch funktioniert, dann, was ist das Problem?

Denken Sie daran, dass veraltet ist nicht das Gleiche wie entfernt. Es bedeutet nur, dass Sie es vermeiden sollten, es für neue Arbeit zu verwenden.

+1

Nun, obwohl dies eine sehr vernünftige Option ist, bekomme ich eine epidermale Reaktion, wenn ich 'warning erlang: now/0 deprecated BIF' sehe. Ich nehme an, jeder, der diese Bibliothek benutzt, würde sich genauso fühlen. Vor allem, wenn man den Erlang-Doc in Fettschrift anschaut ** Diese Funktion ist veraltet! Benutze es nicht! ** – jerome

7

Dies ist bereits in der "Time and Time Correction in Erlang" documentation und auch in der "Time Goes On" postscript zu der wunderbaren "Learn You Some Erlang" book abgedeckt.

+0

Danke für den Zeiger Steve. –

+0

In der Tat eine große Referenz. Es hilft. Aber die Frage war mehr, wie man den Übergang bewältigt. In "Learn You Some Erlang" verweist der Autor auf [okeuday/uuid] (https://github.com/okeuday/uuid), das eine Lösung ähnlich wie @potatosalad implementiert. Schauen Sie sich beide Optionen jetzt an. – jerome

Verwandte Themen