1. 13
  1.  

  2. 3

    Kind of a weird use of “emergent” isn’t it? Scoping imports is a design choice that lets you do these exact things.

    For a historical perspective, at the very least, the MLs have had powerful module systems for decades. If the author thinks Elixir’s module system is powerful then they might really like Ocaml’s or SML’s.

    1. 3

      In trying to understand some of the code here, the semantics of |> strike me as really odd.

      String.graphemes "Hello" |> Enum.reverse
      

      Translates to:

      String.graphemes("Hello" |> Enum.reverse)
      

      I would totally expect that to be:

      (String.graphemes "Hello") |> Enum.reverse
      

      And to get what Elixir actually does, I would expect to have to do:

      "Hello" |> Enum.reverse |> String.graphemes
      

      Which would be equivalent to:

      Enum.reverse "Hello" |> String.graphemes
      

      The existing semantics kind of strike me as really confusing and not really making much sense in terms of what a pipe does.

      Anyone know what the reasoning is behind this? THe |> operator has existed in multiple languages prior to Elixir with the semantics that make sense to me (F# and Ocaml).

      1. 1

        I don’t know the reasoning behind the decisions but:

        String.graphemes "Hello" |> Enum.reverse
        

        This tries to run and fails, because it’s doing what you said it would - trying to reverse “Hello”, but a string/binary doesn’t support the Enumerable protocol (use String.reverse/1 instead).

        To get the desired functionality, you need to use the call parentheses which are advised and not really optional inside a pipeline due to reasons I’m also unaware of.

        String.graphemes("Hello") |> Enum.reverse
        
        1. 1

          Ah sorry, the Enum.reverse failing is just an accident of me not knowing Elixir (I thought I copied it correctly from an example).

          But, ugh, I hate optional parens in these cases. Oh well.

          1. 2

            Another, probably more canonical, way to do it would be:

            "hello"
            |> String.graphemes
            |> Enum.reverse
            
            1. 1

              Yeah, I would agree. They’re a double edged sword, I’m happy that at least I can enforce them in my own code.

              Elixir definitely sides more on explicit is better than implicit though, this is an odd case which goes against that imo.

              1. 1

                FYI, I’m just reading the pre-release notes for v1.2 and it brings with it a compiler warning over the failure to use parentheses during a pipeline. So it’s gone from not enforced, to semi-enforced.

          2. 3

            OCaml has a nice thing

            Gutenex.( 
              begin_text
              |> set_font("Helvetica", 48)
              |> text_position(40, 180)
              |> text_render_mode(:fill)
              |> write_text("ABC")
              |> end_text
            )