Kurzusok
/
Elixir
Elixir
/
Feladatok
/
Szigorúan titkos
Szigorúan titkos

Szigorúan titkos

Tanulófeladat

Bevezetés

AST

Az absztrakt szintaxisfa (AST), más néven quoted expression, a kód adatként való ábrázolásának egyik módja.

Az AST minden csomópontja egy háromelemű tuple.

# AST representation of:
# 2 + 3
{:+, [], [2, 3]}

Az első elem egy atom: maga a művelet. A második elem egy keyword list: a metaadatok. A harmadik elem az argumentumok listája, amely további csomópontokat tartalmaz. A literál értékeket, például az egész számokat, atomokat és stringeket az AST önmagukként ábrázolja, nem háromelemű tuple-ként.

Hogyan lesz a kódból AST

Az Elixir-kód AST-vé alakítása és az AST-k visszaalakítása kóddá a szabványos könyvtár része. Az AST-kkal való munkához szükséges függvényeket a Code modulban találod (például hogy egy kódot tartalmazó stringet AST-vé alakíts), és a Macro modulban (például hogy bejárd az AST-t, vagy stringgé alakítsd).

Figyeld meg, hogy a szabványos könyvtár minden függvénye a „quoted” nevet használja, amikor az AST-ra utal (a quoted expression rövidítéseként).

A kód AST-vé alakítására szolgáló speciális forma neve quote. Ez egy kódblokkot fogad, és visszaadja annak AST-ját.

quote do
  2 + 3 - 1
end

# => {:-, [], [
#      {:+, [], [2, 3]},
#      1
#    ]}

Használati esetek

Az Elixir metaprogramozásának a lényege, hogy a kódot AST-ként ábrázolhatjuk. A makrók, amelyek segítségével olyan Elixir-kódot írhatsz, ami Elixir-kódot állít elő, úgy működnek, hogy kimenetként AST-kat adnak vissza.

Az AST-k másik felhasználási területe a statikus kódelemzés, mint például az Exercism saját eszköze, az Elemző, amelyet talán már ismersz: az a kis bot, amely megjegyzéseket hagy a megoldásaidon.

Utasítások

Egy vállalati kémkedés ellen harcoló munkacsoport tagja vagy. Van egy titkos informátorod a Shady Company X-nél, amelyről azt gyanítod, hogy titkokat lop a versenytársaitól.

Az informátorod, Agent Ex, Elixir-fejlesztő. Titkos üzeneteket kódol a kódjában.

A titkos üzenetei dekódolásához:

  • Vedd az összes függvényt (nyilvánosat és privátat) abban a sorrendben, ahogy definiálva vannak.
  • Minden függvénynél vedd a nevének első n karakterét, ahol n a függvény aritása.

1. Alakítsd a kódot adattá

Valósítsd meg a TopSecret.to_ast/1 függvényt. Egy Elixir-kódot tartalmazó stringet kell fogadnia, és vissza kell adnia az AST-ját.

TopSecret.to_ast("div(4, 3)")
# => {:div, [line: 1], [4, 3]}

2. Dolgozz fel egyetlen AST-csomópontot

Valósítsd meg a TopSecret.decode_secret_message_part/2 függvényt. Egy AST-csomópontot és a titkos üzenethez tartozó akkumulátort (egy listát) kell fogadnia. Egy tuple-t kell visszaadnia, amelynek első eleme a változatlan AST-csomópont, második eleme pedig az akkumulátor.

Ha az AST-csomópont művelete függvényt definiál (def vagy defp), a függvény nevét (stringgé alakítva) fűzd az akkumulátor elé. Ha a művelet valami más, add vissza az akkumulátort változatlanul.

ast_node = TopSecret.to_ast("defp cat(a, b, c), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["cat", "day"]}

ast_node = TopSecret.to_ast("10 + 3")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["day"]}

Ennek a függvénynek nem kell rekurzív hívásokat végeznie a teljes AST ellenőrzéséhez, csak az adott csomópontot kell vizsgálnia. A teljes AST-t az utolsó lépésben beépített eszközökkel járjuk be.

3. Dekódold a titkos üzenet részét függvénydefinícióból

Terjeszd ki a TopSecret.decode_secret_message_part/2 függvényt. Ha az AST-csomópontban a művelet függvényt definiál, ne a teljes függvénynevet add vissza. Ehelyett ellenőrizd a függvény aritását. Ezután csak a név első n karakterét add vissza, ahol n az aritás.

ast_node = TopSecret.to_ast("defp cat(a, b), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["ca", "day"]}

ast_node = TopSecret.to_ast("defp cat(), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["", "day"]}

4. Javítsd a dekódolást őrfeltételeket használó függvényeknél

Terjeszd ki a TopSecret.decode_secret_message_part/2 függvényt. Ügyelj arra, hogy az őrfeltételeket használó függvénydefinícióknál a függvény neve és aritása helyesen legyen felismerve.

ast_node = TopSecret.to_ast("defp cat(a, b) when is_nil(a), do: nil")
TopSecret.decode_secret_message_part(ast_node, ["day"])
# => {ast_node, ["ca", "day"]}

5. Dekódold a teljes titkos üzenetet

Valósítsd meg a TopSecret.decode_secret_message/1 függvényt. Egy Elixir-kódot tartalmazó stringet kell fogadnia, és vissza kell adnia a kódban található összes függvénydefinícióból dekódolt titkos üzenetet stringként. Ügyelj arra, hogy újrahasználd a korábbi lépésekben definiált függvényeket.

code = """
defmodule MyCalendar do
  def busy?(date, time) do
    Date.day_of_week(date) != 7 and
      time.hour in 10..16
  end

  def yesterday?(date) do
    Date.diff(Date.utc_today, date)
  end
end
"""

TopSecret.decode_secret_message(code)
# => "buy"
Szerkesztés GitHubon A hivatkozás új ablakban vagy lapon nyílik meg
Elixir Exercism

Készen állsz elkezdeni a(z) Szigorúan titkos feladatot?

Iratkozz fel az Exercism-re, hogy megtanuld és elsajátítsd a(z) Elixir nyelvet 58 fogalom168 feladat segítségével, valódi emberi mentorálással, mindez ingyen.