How to show Elixir to Scala Programmers?

Ok but if you have team:

  • you need to agree on standards what can you use or not
  • code review

But on the other hand
It could be quite hard if you have big team to have people on the same level …

I think this is bad idea to choose language only to match your team, you should choose language for it purpose what can do best …

1 Like

and there’s always the 3rd party libs that you have no control over but need to inspect from time-to-time. I soured on scala partially because of incomprehensible libs and overuse of implicits essentially making learning hard. I decided I just did not like using it and felt I would not recommend to it colleagues either.

3 Likes

Scala and Haskell are both similar in that they love their obtuse and hard-to-read code, especially with huge over-use of operators. I quite like that OCaml and Elixir are both anti-operator and love clarity.

3 Likes

Totally. While Scala/Haskell syntax might create excitement for the the ivory tower-inclined minds, but from the commercial production point of view: Its expensive for the reason that you can’t modified or fix a code base with confident with code you don’t understand well…or read.

1 Like

Agreed. Able to read third-party’s code is invaluable if the documentation is poor.

3 Likes

I can’t stop myself here. :smiley:

What you are used is what you usually find to be clear and easy to understand. Not being a Ruby programmer I tend to find Elixir to be obtuse and hard to read, especially compared to Erlang and LFE which are both anti-operator and big on clarity.

3 Likes

Lol, yeah Elixir’s Macros are a bit magic at times… ^.^

1 Like

Not just the macros, unfortunately. :anguished:

1 Like

There are other areas more minor that I’d agree with, but I’m curious which you are specifically referencing? :slight_smile:

(Hmm, maybe new thread time?)

1 Like

Don’t show this message to scala programmers! :slight_smile:
I needed some time to search and replace values in complex nested jsons (representing different UI’s f.e.) using elixir. I wonder if there is a clear and simple way in erlang?
I read http://blog.element84.com/elixir-update-in.html which explains the use of update_in (borrowed from clojure?) and https://gist.github.com/josevalim/535a3db5a5a03ebfde0f (use of a regular function returning an anonymous one, the link I got from https://groups.google.com/forum/#!msg/elixir-lang-talk/tu82k5NfinU/6FQEw7ORCAAJ where another developer asks about update_in) to reach my goal and produced the following piece of terribly obtuse code that however endured my tests. The values in the json_updater function are meant as test, they will be fetched from somewhere based on the keys). The exec function is the entrypoint.

defmodule BpmServer.Json do
  defp eval_field(field, next) do
    cond do
      (field |> Map.has_key?("key")) && (field |> Map.has_key?("defaultValue")) ->
        {_, updated_field} = next.(field)
        field
        |> Map.update!("defaultValue", fn _ -> updated_field["key"] end)
      (field |> Map.has_key?("columns")) ->
        field
        |> update_in(["columns", update_components()],
                     fn _ -> nil end)
      (field |> Map.has_key?("rows")) ->
        field
        |> update_in(["rows", update_components()],
                     fn _ -> nil end)
      (field |> Map.has_key?("components")) -> json_updater(field)
      true -> field
    end
  end

  defp update_components() do
    fn :get_and_update, data, next ->
      new_data =
        case data do
          [] -> data
          _  -> [head | _] = data
                cond do
                  is_list(head) -> Enum.map(data,
                                            fn list -> Enum.map(list,
                                                                fn field -> eval_field(field, next) end)
                                            end)
                  true          -> Enum.map(data, fn field -> eval_field(field, next) end)
                end
        end
      {nil, new_data}
    end
  end

  defp json_updater(json_part), do:
    json_part |> update_in(["components", update_components(), "key"],
                           fn key ->
                             case key do
                               "telenenbedrag" -> "YtelenenbedragY"
                               "looptijd"      -> "XlooptijdX"
                               "binnenpanel"   -> "XbinnenpanelX"
                               "binnencolumn"  -> "XbinnencolumnX"
                               "root"          -> "XrootX"
                               "stefan"        -> "ZstefanZ"
                               "boris"        -> "ZborisZ"
                               "flip"        -> "ZflipZ"
                             end
                           end)

  def exec() do
  # "leningwens"
    json = (Application.get_env(:bpm_server, :form_files_dir) <> "/" <> "fieldsettest" <> ".form")
           |> File.read!()
           |> Poison.Parser.parse!()
  IO.inspect json

    IO.inspect json_updater(json)
  end

end
1 Like

I have problems with Elixir’s handling of newlines. It is not part of the syntax like in Python but you cannot ignore it and often have to be careful when adding newlines. For example I cannot write:

def a(x, y) do
  [
    x
    ,
    y
    ]
  end

Putting [ and ] first on a line works but not ,. Ok, this is something most people wouldn’t worry about but it does illustrate the problem. There are lots of things with parentheses as well. Now I know WHY most of it is like it is but it is not obvious unless you get down into the nittygritties of the syntax.

And there is way too much syntax for my likings, I like syntax to be simple and consistent and simple. :grinning:

1 Like

That exact same thing has bugged me quite well, newlines are just so randomly required and randomly required not to exist as well. I know why it is as well, but it so bugs me… (Ahh OCaml, no newline sensitivity except for top-module, which just saves you a semicolon anyway, but is still a wart. ^.^)

So… Lisp? ^.^

1 Like

You are talking to the guy who created LFE ( LISP for Erlang) :slight_smile:

1 Like

Heh, I know, hence why I mentioned it, just being sarcastic. ^.^

1 Like

Yeah, sorry… I’m bad with sarcasm. :confused:

1 Like

No worries, I really love lisp. How can you hate a language where you can describe most of the syntax on one slide. :wink:

1 Like

I got a question for you @rvirding: do you believe it would be possible to combine a type system (like F#'s or OCaml) into a LISP?

For polymorphism, using the idea of Protocols (the same as Elixir/Clojure) so we could potentially let users “overload” operators for other types. To be honest I think that Protocols behave quite like Traits.

1 Like

Unfortunately obtuse solutions don’t make clear problem statements either. From what I could gather you are trying to update the “defaultValue” value (provided it exists) on “key” maps found inside “components”, “rows” or “columns” maps. For my made up sample data this seems to do the same thing.

defmodule Test do

  def updateDefaultValues( data_map, default_values ) do
    
    update = fn data, upd ->
      case data do
        [_|_] ->
          Enum.map data, &(upd.(&1,upd))

        %{ "key" => name, "defaultValue" => _ } ->
          put_in data["defaultValue"], default_values[name]

        %{ "components" => components } ->
          put_in data["components"], upd.(components,upd)
          
        %{ "columns" => columns } ->
          put_in data["columns"], upd.(columns,upd)
          
        %{ "rows" => rows } ->
          put_in data["rows"], upd.(rows,upd)
          
        _ ->
          data
      end
    end

    update.(data_map,update)
  end

end

json =
  %{"components" => [
    %{"rows" => [
       [%{ "columns" => [
           
        [%{ "components" => [
          %{"key" => "telenenbedrag", "defaultValue" => "value"},
          %{"key" => "looptijd", "defaultValue" => "value"}
        ]},
        %{ "components" => [
            %{"key" => "telenenbedrag", "defaultValue" => "value"},
            %{"key" => "looptijd", "defaultValue" => "value"}
        ]}],
        
        [%{ "components" => [
          %{"key" => "telenenbedrag", "defaultValue" => "value"},
          %{"key" => "looptijd", "defaultValue" => "value"}
        ]},
        %{ "components" => [
            %{"key" => "telenenbedrag", "defaultValue" => "value"},
            %{"key" => "looptijd", "defaultValue" => "value"}
        ]}]
        
      ]}],
      [%{ "columns" => [
           
        [%{ "components" => [
          %{"key" => "telenenbedrag", "defaultValue" => "value"},
          %{"key" => "looptijd", "defaultValue" => "value"}
        ]},
        %{ "components" => [
          %{"key" => "telenenbedrag", "defaultValue" => "value"},
          %{"key" => "looptijd", "defaultValue" => "value"}
        ]}]
        
      ]}]
    ]},
    %{"key" => "root", "defaultValue" => "value"},
    %{"key" => "flip"},
  ]}

default_values = %{
  "telenenbedrag" => "YtelenenbedragY",
  "looptijd" =>  "XlooptijdX",
  "binnenpanel" =>  "XbinnenpanelX",
  "binnencolumn"=>  "XbinnencolumnX",
  "root" =>  "XrootX",
  "stefan" =>  "ZstefanZ",
  "boris" =>  "ZborisZ",
  "flip" => "ZflipZ"
}

IO.inspect json
IO.inspect Test.updateDefaultValues( json, default_values )
2 Likes

Ok, I take that back. Looks great, thanks a lot!

1 Like

/me is not rvirding, but yes, absolutely, you can even do it via LISP’s macro system.

1 Like