But I think it was also partly due to the language's API being a little confusing. I find myself frequently wondering if some method was in List or Enum (and only after the fact did I learn about Stream). I think also that the syntax, while looking like Ruby, wasn't really much like Ruby at all. It would be like writing Ruby if all you ever used were module methods. Something I always hated about Ruby was having to write File.read(...) and File.join(...) all the time. That's the pattern Elixir uses for everything. Since the Ruby-esque syntax, in the end, didn't prove so nice, I am now wondering what writing in Erlang would be like. I also started to wonder why Elixir doesn't support a more Ruby like syntax of, e.g. `[1,2,3].each` as a syntax sugar for `Enum.each [1,2,3]`. Given how protocols work, it seems like that should be possible. I think it would have made the experience of writing Elixir code much better and the code would be easier to read too.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Finally, regarding the error messages, any poor error message is considered a bug. If there is anything you recall and if you stumble against any poor error message, please open up an issue. We do not take bad error messages lightly.
Hi Jose,You point on the reason why it's hard to find the functions is interesting. I've never realized this before.This make me understand why, when I was playing around with Clojure, I prefer to find functions from clojure cheatsheet rather than going directly to clojure doc. Because it groups by data type!
A little bit off-topic, but I fell in love with the ClojureDocs.org website for quickly finding my way around the standard library :) http://clojuredocs.org/quickref/Clojure%20CoreWould love to see something similar for Elixir.
Could you share your code in Elixir and Go? I'd love to compare the styles.
Extremely doable in a statically typed language, in Elixir not so much. The problem is that when you have `[1, 2, 3].each` you have to find the correct implementation of `each`, in the correct protocol, in the correct namespace before you can actually run the `each` function. It also happens to be a little difficult if the same `each` name can be used in different protocols that both provide implementations for a given kind of value, so say `Associative.at` would give a different value than `Sequential.at`, and once all you have is `[1, 2].at 1`, which may be both `Sequential` and `Associative`, you can't really infer what kind of implementation to use.
There's also some dynamic resolution overhead because you can't infer the protocol at compile time, that you wouldn't have in a statically typed language.
On Tuesday, August 13, 2013 9:48:06 AM UTC-4, Chris-tina Whyte wrote:Extremely doable in a statically typed language, in Elixir not so much. The problem is that when you have `[1, 2, 3].each` you have to find the correct implementation of `each`, in the correct protocol, in the correct namespace before you can actually run the `each` function. It also happens to be a little difficult if the same `each` name can be used in different protocols that both provide implementations for a given kind of value, so say `Associative.at` would give a different value than `Sequential.at`, and once all you have is `[1, 2].at 1`, which may be both `Sequential` and `Associative`, you can't really infer what kind of implementation to use.
Protocols have order, so I was thinking it would just use the first matching implementation it comes upon. So not everything you can do with a particular data type would be accessible this way. But at least the most common functions would be.
There's also some dynamic resolution overhead because you can't infer the protocol at compile time, that you wouldn't have in a statically typed language.
So it would have to be done at runtime, not compile time? Why is that? And if so how much overhead?
// Good lord, I have to write my own routine to convert a []string to []interface |
// so I can pass the contents of the []string to fmt.Printf. |
This is true if you try to pass it is fmt.Println([]string...), but you can pass the slice directly just fine. http://play.golang.org/p/yS7MVG1wB5 |
The performance results make me very suspicious. Generally I would expect Go's performance to be similar or better than Erlang/Elixir (note: I am only remotely familiar with Go)
prog.go:9: cannot use s (type []string) as type []interface {} in argument to fmt.Println
[process exited with non-zero status]
Elixir on the other hand has many constructs that allow you to use threads without realizing it, and it will use as much of the machine as it can right out of the box. With just a few lines of code, you can create a process with thousands of threads that chews up gigabytes of memory.
This is a great example of what's great about Elixir vs. C/Go/Next.
A similar story. There's a highway with a 65 MPH speed limit. My wife always takes it. There's another road with a 45 MPH speed limit. The back way. I always beat my wife home. It's the lights, of course.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-ta...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Hi José,
I had the error message noted, but not the culprit - a simple syntax error.
I thought it was List.count, but that gives a precise error message:
cannot invoke remote function List.count/1 inside guard
At the time, I wasn't aware of, or had forgotten about `length/1`, so I thought I might not be able to achieve the desired guard, but it was quickly found.
defmodule MatchError do
@my_const = 42 # Oops.
def main() do
my_func(10, @my_const)
end
def my_func(a, b) when a > b, do: a
def my_func(a, b) when a < b, do: b
#def my_func(a, b) when List.count(a) == length(b), do: a
end
Gives:
cannot invoke remote function Module.get_attribute/3 inside match
Quicker for noobs would be eg: Syntax error in attribute definition.
`match` refers to the fact that with an `=` the parser thinks that's an expression rather than an attribute definition, I think.
This looks a little to me like the same issue as the `ErrorBad` example in my previous post, in that if the order of the parsing was changed then a different error would be identified first and returned.
That is, in the `ErrorBad` example, if the parser found unexpected keywords before extra `end`s that would be more helpful, even though it does seem intuitive to first check the basic structure, and is probably necessarily first.
In this match error example, if the parser found attribute definition errors before match errors, this would be more helpful.
I think I'm understanding your parser rewrite comment. But I'm not much beyond the brainfuck language level of language writing, so get out your bucket of salt.
I'm wondering if the `ErrorBad` example, highlighting as faulty the line of an effect rather the cause, that possibility starts to creep into one's mind with other errors. So if I don't spot the error immediately in the mentioned line, I start looking at associated locations, starting a wild goose chase.
It's Rumsfeld territory [0] - as a noob, I know I don't know what I'm doing, so I don't know what I know and what I don't know, known unknowns, and knowing there are unknown unknowns, so I doubt, wonder and fumble.
The Go error messages having a really quick turn-around time greases the wheels nicely.
This has turned into a useful reflective meditation, if nothing else!
defmodule MatchError do
@my_const = 42 # Oops.
def main() do
my_func(10, @my_const)
end
def my_func(a, b) when a > b, do: a
def my_func(a, b) when a < b, do: b
#def my_func(a, b) when List.count(a) == length(b), do: a
end
It's Rumsfeld territory [0] - as a noob, I know I don't know what I'm doing, so I don't know what I know and what I don't know, known unknowns, and knowing there are unknown unknowns, so I doubt, wonder and fumble.
Elixir on the other hand has many constructs that allow you to use threads without realizing it, and it will use as much of the machine as it can right out of the box. With just a few lines of code, you can create a process with thousands of threads that chews up gigabytes of memory.I'd like to see these few lines you claim eat up gigabytes of memory.
You cannot create thousands of threads in the Erlang VM because it uses processes. The Erlang VM will create 1 thread for each scheduler (which by default I believe is one per core, so an 8 core machine would have 8 schedulers). Each scheduler will run code in thousands or millions of processes (I personally have created 10 million on my machine without using up hardly any memory or CPU at all). Erlang was created in the '80s where memory was extremely scarce, it doesn't make any sense if this were true.