3 ms·
Totally of topic but could someone explain Elixirs syntax to me? In the following code (from the linked site): What is embeds_many? Are :string and :map type
by J0-nas 10y ago
Totally of topic but could someone explain Elixirs syntax to me?
In the following code (from the linked site):
What is embeds_many?
Are :string and :map type information or Atoms?
What happens to :changes, Change, primary_key?
Does the code between do and end just call the field function twice?
embeds_many :changes, Change, primary_key: false do
field :field, :string
field :value, :map
end
- Cieplak 10y agohttps://learnxinyminutes.com/docs/elixir https://learnxinyminutes.com/docs/elixir
- J0-nas 10y agoI read this and it doesn't answer my questions
- ShaneWilton 10y agoThis code snippet is a little bit confusing if you aren't already familiar with Elixir, because most of the syntax you're seeing is actually from Ecto's [0] DSL. Calling "use Ecto.Schema" at the top of the module brings some extra functionality into the current scope. For example, embedded_schema is a macro exported by Ecto.Schema [1]. embeds_many is another such macro [2], that allows you embed another schema, in-line, into the current schema. This is contrast to your more common has_many relationship, which references another table entirely. Here, :string, :map, etc are atoms that are being passed to the field macro [3], to define the schema for the table. [0] Basically a super lightweight ActiveRecord [1] https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216f6cb31e158ea59e76e046/lib/ecto/schema.ex#L339 https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216... [2] https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216f6cb31e158ea59e76e046/lib/ecto/schema.ex#L1315 https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216... [3] https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216f6cb31e158ea59e76e046/lib/ecto/schema.ex#L446 https://github.com/elixir-ecto/ecto/blob/b030353d4b94ddd4216...
- J0-nas 10y agoThank you
- lilactown 10y agoIt's confusing because it's using a library called Ecto, which provides it's own DSL for describing schemas and queries. NOTE: I haven never used Ecto, but I have used Elixir for a few hobby projects. 1. `embeds_many` is a function name, described here: https://hexdocs.pm/ecto/Ecto.Schema.html#embeds_many/3 https://hexdocs.pm/ecto/Ecto.Schema.html#embeds_many/3 2. Anything that begins with a colon is an Atom in Elixir, including :string, :map, :changes, :field, and :value. These atoms are used by Ecto at runtime to identify certain things. `:changes` is a unique name given to the embedded schema, `:field` and `:value` are field names on that schema, and :string and :map are informing Ecto of how to treat certain values. 3. `Change` is the name of a Module which describes the Schema we are embedding 4. `primary_key: false` is a configuration option 5. Everything after `do...` is describing what the embedded schema would look like. So it has a `:field` field that is of type string, and a `:value` field that is of type map. Hopefully that makes some sense... I'm not totally clear on it either (having not used Ecto before) but that's what I'm grokking.
- J0-nas 10y agoThanks
- klibertp 10y agoOthers provided an explanation of the Ecto DSL, I just wanted to add the explanation of basic syntax. It goes like this. In Elixir, the most basic function application looks fairly standard: func_name(arg1, arg2, ...) But the parens are optional, so you can write: func_name arg1, arg2, ... as well. Next, in Erlang and Elixir function arity (number of arguments it takes) is always fixed (i.e. no varargs or Python's *args). Because of this you generally have to pack your arguments in a list; functions like `printf` work that way: iex(2)> :io.format("fmt ~p foo: ~p bar: ~p", [1, 3, 4]) fmt 1 foo: 3 bar: 4 That takes care of (positional) varargs. There are some other functions, however, which would benefit from "keyword arguments", which also isn't directly supported. To get around this, you can take a list of pairs (keyword, value) as one of your arguments (usually last): some_func(arg1, [{:keyword1, value}, {:keyword2, value}]) Where `{}` creates a tuple and `:` creates an atom (called symbols in Lisp), which you can think of as a special[1] string value. This pattern is so common, that Elixir provides a syntactic sugar for it. The above is equivalent to: some_func(arg1, [keyword1: value, keyword2: value]) The brackets around keyword list are also optional, but only inside function call. The most sugar-y way to write this looks like this: some_func arg1, keyword1: value, keyword2: value The last thing of note is that the `do ... end` is just a syntactic sugar for `[do: ...]`, where `...` is treated as a block of code. Normally, the block of code would be evaluated and only last value would be passed to the function: some_fun arg1, kwarg1: 1, kwarg2: 3 do 1; 2; 3 end # notice no comma before `do` would be equivalent to (after all the sugar being resolved): some_fun(arg1, [{:kwarg1, 1}, {:kwargs2, 2}], [{:do, 3}]) However, when writing a macro, the macro gets the unevaluated block, which then can be modified or executed. See http://elixir-lang.org/getting-started/meta/macros.html http://elixir-lang.org/getting-started/meta/macros.html for more info on that. Edited to add: Capitalized names in Elixir are actually special atoms, mostly used for naming modules. It works like this: iex(5)> :'Elixir.Change' == Change true There is more going on because of the fact you can alias module names, but mostly you can think about this as (another) special syntax for atoms. [1] Allocated once and cached. When working with normal strings: a = "Asd" b = "Asd" you have no guarantee that `a` and `b` point to the same thing in memory, while with atoms you do have that guarantee. This makes comparing them efficient.
- raarts 10y ago