News for hackers. Stuff that matters.
Re:Happy Birthday, Ruby by dnautics on Thursday January 10, 2019 @03:15PM (#18877635)
> I'm not sure what language would be more beautiful than ruby.

Elixir (with static type analysis) - gets a bit of an edge, IMO, thanks to pipes, which are way prettier than .then:

    defmodule FizzBuzz do
      @spec fizzbuzz(integer)::String.t
      def fizzbuzz(int) do
        cond do
          rem(int, 15) == 0 -> "FizzBuzz"
          rem(int, 5) == 0  -> "Fizz"
          rem(int, 3) == 0  -> "Buzz"
          true              -> inspect int
        end
      end
    end

    1..100
    |> Enum.map(&FizzBuzz.fizzbuzz/1)  #[0]
    |> Enum.join("\n")
    |> IO.puts

    #[0] function variables are a very slightly "ugly 
    #syntax" part of the language due to erlang legacy
Other stuff that's really pretty in elixir is the first class documentation. Elixir docs are out of the box prettier than ruby docs.

Compare from the official (but as a user you get these docs too):

https://ruby-doc.org/core-2.6/Array.html

https://hexdocs.pm/elixir/List.html#content

But again, it's only a bit prettier. Of course, if you try to browse both on mobile, Elixir wins handily. This is great for when you have to use the bathroom at the same time as you're in the middle of debugging and need to look up what a library module member function does, so there's some developer benefit edge too.

Re:Happy Birthday, Ruby by bonquesha99 on Thursday January 10, 2019 @04:27PM (#18878384)
Elixir/Unix style pipe operations in Ruby!

https://github.com/LendingHome/pipe_operator

Re:Happy Birthday, Ruby by dnautics on Thursday January 10, 2019 @04:32PM (#18878428)
it's not nearly the same. Piping in elixir is a macro; it lets you preserve the other arguments in your function call.

The IO.inspect(value, label: "label string") semantic is incredibly powerful. During debugging I often do this:

    value
    |> IO.inspect(label: "A")
    |> do_something
    |> IO.inspect(label: "B")
    |> do_something_else
    |> IO.inspect(label: "C")

    ...
This gives me full visibility over the data transformations that are happening. And removing the IO.inspect's are trivial with an IDE like atom, vscode, etc. Also the way that the BEAM handles concurrent IO means that none of those strings that I send will be interrupted by other content, which is critical to interpretable println debugging in a concurrent environment. I haven't used the debugger (or IEX.pry, whic I hear is powerful) once.
Re:Happy Birthday, Ruby by bonquesha99 on Thursday January 10, 2019 @04:37PM (#18878460)
That's what it's doing, arguments are preserved:

    # don't really know what IO.inspect is doing
    # but guessing something like this?
    def IO.inspect(value, label:)
      puts "#{label}: #{value.inspect}"
      value
    end

    value.pipe do
      IO.inspect(label: "A")
      do_something
      IO.inspect(label: "B")
      do_something_else
      IO.inspect(label: "C")
    end
Re:Happy Birthday, Ruby by dnautics on Thursday January 10, 2019 @05:13PM (#18878807)
oh I didn't get past "Matz on Ruby"! Sorry. I do think the native pipe operator is prettier.
Re:Happy Birthday, Ruby by dnautics on Thursday January 10, 2019 @04:41PM (#18878507)
as per Jpakotal's comment elsewhere this might be even prettier:

    1..100
    |> Enum.map_join("\n", fn 
      int when rem(int, 15) == 0 -> "FizzBuzz"
      int when rem(int, 5)  == 0 -> "Fizz"
      int when rem(int, 3)  == 0 -> "Buzz"
      int                        -> inspect int
    end)
    |> IO.puts