用 Elixir 的一周 已翻译 100%

dbtop 投递于 2014/03/14 17:26 (共 22 段, 翻译完成于 03-24)
阅读 3534
收藏 13
3
加载中

About a week ago I started looking at Elixir. Elixir had been one of those things that I was vaguely aware of but had not yet time to look at in any detail.

This all changed when I discovered the announcement that Dave Thomas was publishing Programming Elixir.  Dave Thomas edited my Erlang book and did great work in introducing Ruby, so when Dave gets excited about something then this is a sure sign that something interesting is in the wind.

Dave was excited about Elixir, in the introduction to his new book he says:

I came across Ruby in 1998 because I was an avid 
reader of comp.lang.misc (ask your parents). I 
downloaded it, compiled it, and fell in love. 
As with any time you fall in love,
it’s difficult to explain why. 
It just worked the way I work, 
and it had enough depth to keep me interested.

Fast forward 15 years. All that time I’d been 
looking for something new that gave me the same feeling.

I came across Elixir a while back, but for some 
reason never got stuck in. But a few months ago I 
was chatting with Corey Haines. I was
bemoaning the fact that I wanted to find a 
way to show people functional programming concepts 
without the kind of academic trappings those books 
seem to attract. He told me to look again at Elixir. I
did, and I felt the same way I felt when I first saw Ruby.
已有 1 人翻译此段
我来翻译

I know the feeling. Gut feeling  precedes logic. I know when things are right, I don’t know how or why I know, but the explanation of why things are right often comes weeks or years later. Malcolm Gladwell in his bookBlink: The Power of Thinking Without Thinkingtalks about this.  Experts in a particular field can often instantly know that something is right, but they can’t explain why.

When I saw that Dave had his eye “on the ball” I wanted to know why.

Surprise number two, Simon St. Laurent was also writing a book on Elixir. Simon did a good job with Introducing Erlang… and we’d exchanged several mails, so something was in the air. With both Pragmatic Press and O'Reilly racing to get into  Elixir I knew something was happening on the Erlang VM, and I didn’t know about this. Boy am I out of touch.

I mailed Dave and Simon and they kindly sent me copies of their books so I could start learning …  Thanks guys …

已有 1 人翻译此段
我来翻译

I downloaded elixir last week and started playing …

It didn’t take long, but pretty soon my gut feeling kicked in. This is good shit.  The funny thing is that Erlang and Elixir are the same thing under the surface.  They “feel” the same to me. In fact this is literally true, they both compile to instructions for the EVM (Erlang Virtual Machine) - actually nobody call this the EVM They just say the “Beam” VM but I thing we should start calling this the EVM to distinguish it for the JVM.

Why do Erlang and Elixir have the same “semantics”? The reason has to do with the underlying machine. The garbage collection behavior, the non-shared concurrency model, the underlying error handling and code loading mechanism are identical. They must be identical: they run on the same VM. This is also why things like Scala and Akka will never be like Erlang. Scala and Akka run on the JVM so under the covers, things like garbage collection and code loading are fundamentally different.

已有 1 人翻译此段
我来翻译

What Elixir brings to the table is a complete different surface syntax, inspired by Ruby. What you might call a “non-scary” syntax, and a load of extra goodies.

Erlang’s syntax derived from Prolog and was heavily influenced by smalltalk, CSP and the functional programming. Elixir is heavily influenced by Erlang and Ruby.  From Erlang it brings pattern matching, higher order functions and the entire process and error handling “let it crash” philosophy. From Ruby it brings sigils, and shortcut syntaxes. It also adds a few goodies of its own, the |> pipe operator, reminiscent of Prologs DCGs and Haskell monads (though less complicated, more like the good old unix pipe operator) and the macro quote and unquote operators, which come from the lisp quasiquote and comma operators.

Elixir also brings a new underlying AST to the table, instead of the Erlang AST where everything form has its own representation, the Elixir AST has a far more uniform representation, which makes meta-programming far easier.

已有 1 人翻译此段
我来翻译

The implementation is surprisingly solid, though some things don’t work as I expected. String interpolation (which is a great idea) works in a hit-and-miss manner.

I’d thought that:

IO.puts "...#{x}..."

evaluated x and injected a pretty-printed representation of x into the string.  But it only works for some simpler forms of x and not all x.

Since you can call any Erlang function from Elixir this was easy to fix.

IO.puts “…#{pp(x)}…” always works. I just defined pp(x) as

def pp(x) do 
    :io_lib.format("~p", [x])
    |> :lists.flatten
    |> :erlang.list_to_binary
end

In Erlang this would be:

pp(X) ->
  list_to_binary(lists_flatten(li_lib:format("~p),[X])))

which is “obviously” equivalent to the Elixir version. Actually the Elixir version is easier to read. The |> operator in the above means pipe the output of io_lib:format into lists:flatten and then list_to_binary. Just like the good ol' Unix pipe operator.

已有 1 人翻译此段
我来翻译

Elixir breaks a few Erlang holy cows - variables can be re-bound in sequences.  This is actually ok, the resulting forms can still be normalized into a static-single-assignment (SSA) form. While this is OK in sequences it would totally verboten-nicht-do-not-do-it in loop constructs. But this is fine, Elixir has no loops, only recursion. Actually it could not have loops with mutable variables since this would be impossible to compile into anything remotely sensible in the EVM. SSA variables in sequences are fine, the EVM knows how to optimize these. Loops no, so Elixir doesn’t go there. It would even boil nicely down into LLVM assembler - but that’s another story too long to tell here.

已有 1 人翻译此段
我来翻译

The Three Laws of Programming Language Design

  • What you get right, nobody mentions it.

  • What you get wrong, people bitch about.

  • What is difficult to understand you have to explain to people over and over again.

Some languages get some things so right that nobody ever bothers to mention them, they are right, they are beautiful, they are easy to understand.

The wrong stuff is a bitch. You boobed, but you are forgiven if the good stuff outweighs the bad. This is the stuff you want to remove later, but you can’t because of backwards compatibility and some nitwit has written a zillion lines of code using all the bad stuff.

已有 2 人翻译此段
我来翻译

The difficult to understand stuff is a real bummer. You have to explain it over and over again until you’re sick, and some people never get it, you have to write hundred of mails and thousands of words explaining over and over again why this stuff means and why it is so. For a language designer, or author, this is a pain in the bottom.

I’m going to mention a few things that I think fall into these three categories.

Before I start I’ll just say that Elixir has got a heck of lot of things right, and the good things far outweigh the bad things.

The nice thing about Elixir is that it’s not too late to fix the bad things. This can only be done before zillions of line of code get written and before trillions of programmers start using it - so there’s only a few days to fix this.

已有 2 人翻译此段
我来翻译

No versions in the source files

XML files always start

  <?xml version="1.0"?>

This is great. Reading the first line of an XML file is like listening to the opening bars of Rachmaninoff’s third piano concerto. A sublime experience. All praise to the XML designers, hallowed be their names, give these guys some Turing prizes.

Putting the language version in all source files is essential. Why is this?

Early Erlang did not have list comprehensions. Suppose that we give a modern Erlang module to an old Erlang compiler and ask it to compile it. The modern code has list comprehensions, but the old compiler doesn’t know about list comprehensions so the old compiler thinks this is a syntax error.

If a version3  Erlang compiler is given a file that starts:

-version(5,0).

Then it should say

** auuuuugggghhhhhh **

   Oh bother and blast, I am mere version 3 compiler
   and cannot see into the future.

   You have given me a version 5 program. This means 
   my time on earth has come.

   You will have to kill me. You will uninstall me, 
   and install a version five compiler. I will be
   no more. I will cease to exist.

   Goodbye old friend.

   I have a headache. I'm going to have a rest...
**

It’s the first law of data design:

 All data that might change in the future should be 
 tagged with a version number.

and a module is data.

已有 2 人翻译此段
我来翻译

Funs and defs are not the same

When I started writing “Programming Erlang” Dave Thomas wondered why you couldn’t type function in the shell.

If a module contains this:

fac(0) when N > 0 -> 1;
fac(N)            -> N* fac(N-1).

You can’t just cut and paste this into the shell and get the same result. Dave asked why and said that this was stupid.

In Lisp and so on you can. Dave said something like “this is going to confuse people” - he was right and it does confuse people. There must be hundreds to thousands of messages on forums asking about this.

I have explained why so many times that my hair has gone grey, it’s true my hair is now grey because of this.

It’s because there is a bug in Erlang.

Modules in Erlang are sequences of FORMS.

The Erlang shell evaluates a sequence of EXPRESSIONS.

In Erlang FORMS are not EXPRESSIONS.

double(X) -> 2*X.            in an Erlang module is a FORM

Double = fun(X) -> 2*X end.  in the shell is an EXPRESSION

The two are not the same. This bit of silliness has been Erlang forever but we didn’t notice it and we learned to live with it.

In an Elixir Module you can write

def triple(x) do
   3 * x;
end

My bet is that thousands of programmers will cut and paste this from their text editor into the shell and it will say

ex> def triple(x) do 3*x; end
** (SyntaxError) iex:66: cannot invoke def outside module

If you don’t fix this you’ll spend the next 20 years explain why - just like we did in Erlang.

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(3)

oldratlee
oldratlee
重新审校和翻译这个文章 放在了

与Elixir相处的一周 https://github.com/oldratlee/translations/blob/master/a-week-with-elixir/README.md 。

大家可以看看 :)
oldratlee
oldratlee

引用来自“betterforever”的评论

Erlang在占世界二分之一的手机网络中提供了 抢到 的支持

像是WhatsApp这个应用和全世界一半手机网络的关键部分都是搭建在Erlang之上。当技术变得更加亲和,当新一批热衷者进入阵营,让我现在怀着非常欣喜的心情关注着后续要发生的变化。 这个意思
b
betterforever

Erlang在占世界二分之一的手机网络中提供了 抢到 的支持

返回顶部
顶部