--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J5t8b7RGX3JxBJT-zG%3DKAwO4f6A0UfgZXLu2Q%3DVkNJVg%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/292de486-df0b-4522-ac72-ebd626de73b6%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/948e1dc1-578d-4703-8de4-8bba53993de2%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/76EBD5F3-EAC4-49F8-AC2C-E7CBFAC0B3B2%40gmail.com.
with {:ok, a} <- get_record(some_id),
{:ok, b} <- process_record(a),
{:ok, c} <- update_some_fields(b)
{:ok, d} <- process_some_more(c),
do: {:ok, d}
d = get_record(some_id)
|=> process_record
|=> update_some_fields
|=> process_some_more
Great idea! But I think for some simple cases it's over verbose. There will be many cases where we will just need simple `{:ok, value}` / `{:error, msg}` pattern and we would need to write something like this:
transact with user <- Repo.insert(user_changeset), log_changeset = Log.changeset(%Log{user_id: user.id}, params), log <- Repo.insert(log_changeset), do: {user, log}
with(transact) do
{:ok, user} <- Repo.insert(user_changeset),
log_changeset = Log.changeset(%Log{user_id: user.id}, params),
{:ok, log} <- Repo.insert(log_changeset)
finally
{user, log}
end--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/52b5b960-7b6a-440f-8438-026cdffeae6c%40googlegroups.com.
res1 = f1()
res2 = f2(res1)
res3 = f3(res2)
res4 = f4(res3)
res4
f1
|> f2
|> f3
|> f4
f1
|=> f2
|=> f3
|=> f4
with {:ok, res1} <- f1
{:ok, res2} <- f2(res1)
{:ok, res3} <- f3(res2)
{:ok, res4} <- f4(res3)
:do { res4 }
with {:ok, res1} <- f1 | res1 = f1()
{:ok, res2} <- f2(res1) | res2 = f2(res1)
{:ok, res3} <- f3(res2) | res3 = f3(res2)
{:ok, res4} <- f4(res3) | res4 = f4(res3)
:do { res4 } | res4
f1 | f1
|=> f2 | |> f2
|=> f3 | |> f3
|=> f4 | |> f4
You're right but the same can be said about thisexplicit form:res1 = f1()
res2 = f2(res1)
res3 = f3(res2)
res4 = f4(res3)
res4
and yet we have this shortcut:
with transact do{:ok, user} <- Repo.insert(user_changeset)if this and that do......end{:ok, log} <- Repo.insert(log_changeset)end
transact with user <- Repo.insert(user_changeset),log_changeset = Log.changeset(%Log{user_id: user.id}, params),log <- Repo.insert(log_changeset),do: {user, log}
transact with(user <- Repo.insert(user_changeset),
log_changeset = Log.changeset(%Log{user_id: user.id}, params),log <- Repo.insert(log_changeset),do: {user, log}
Better? Thoughts?)
with {:ok, x} <- ok(1),{:ok, y} <- ok(2),do: {:ok, x + y}#=> {:ok, 3}
def biggerError(3, 4) do
{:error, 3, 4}
end
with {:ok, x} <- ok(1)
{:error, a, b} <- biggerError(2,3)
do: {:ok, x, a, b},
otherwise: <fn inserted here>--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/7682c5e9-49b3-4e63-8381-97350b736c41%40googlegroups.com.
What's the difference between:with {:ok, binary} <- File.read(path),header = parse_header(binary),{:ok, data} <- :beam_lib.chunks(header, :abstract_code),do: {:ok, wrap(data)}andwith {:ok, binary} <- File.read(path),header <- parse_header(binary),{:ok, data} <- :beam_lib.chunks(header, :abstract_code),do: {:ok, wrap(data)}
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JwaVgsnkCOotw9dwxLcswMFjwuMR0GVv0yk3bnP2wfrg%40mail.gmail.com.
One behavioral difference I can think of might be that `{:ok, header} = parse_header(binary)` would raise MatchError if it fails whereas `{:ok, header} <- parse_header(binary)` returns the result of `parse_header(binary)`.
That was something I noted about this syntax. Both the "=" and the "<-" seem to be match operators. The difference might be that "<-" upon failing a match causes the with statement to return the mismatched value as the value of the with expression overall while using "=" and leading to a mismatch would cause a runtime mismatch exception.Seems like a subtle difference.
with {:ok, x} <- ok(1),
{:ok, y} <- ok(2),
do: {:ok, x + y}
#=> {:ok, 3}
What is the scope of variables bound by the statement?with {:ok, x} <- ok(1),{:ok, y} <- ok(2),do: {:ok, x + y}#=> {:ok, 3}Are x and y only bound within the scope of the 'with' expression and it's "do:" clause (making this something like a "let-do" statement from other languages, or are x and y bound in the enclosing scope?
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/ef2a9d20-c702-481a-90a0-1d056aedf9a5%40googlegroups.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4JwaVgsnkCOotw9dwxLcswMFjwuMR0GVv0yk3bnP2wfrg%40mail.gmail.com.
with%{halted: false} = conn <- plug1(conn, opts1),%{halted: false} = conn <- plug2(conn, opts2),%{halted: false} = conn <- plug3(conn, opts3),do: conn
Is every time a <- is seen, is the right hand side performed inside a task, or is that just for async?withx = {:ok, 1} <- ok(1),do: x#=> 1
# common use case but using withwithdata <- filter_a(data),data <- filter_b(data),do: data#=> filtered data
# Assuming data is a map that has a done: keywith%{done: false} = data <- filter_a(data),%{done: false} = data <- filter_b(data),do: data#=> Returns either data or the value of the first filter that does not set :done to false
It doesn't make much sense to use "with" if you are not performing any match. If you only assign to a variable, it will always match, which means it will always move to the next expression.
# Assuming data is a map that has a done: keywith%{done: false} = data <- filter_a(data),%{done: false} = data <- filter_b(data),do: data#=> Returns either data or the value of the first filter that does not set :done to falseThis will likely return %{done: true} or %{done: false} assuming filter_a and friends always returns maps.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4KLVmtDq8KdSGFUGmQ7ibPKNSJnLoaE_Q%3DM%2BeRd5fRXYg%40mail.gmail.com.
If all filters return %{done: false}, then the do: data will dictate that data should be returned, correct?
If all filters return %{done: false}, then the do: data will dictate that data should be returned, correct?The do part is only invoked if they all match. And, in your case, data is always a map if they match.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4K31zWUxKQ%2B_ZAq0rBVGei4PpAruSKPhOTmK0OWqHDERg%40mail.gmail.com.
Just to be clear, if they all match, then the do: data clause will be executed and data will be returned (the full map).If one of the filters returns %{done: true}, then %{done: false} = data will yield a runtime error?
Note: Proposal can also be read on gist. Please do not drop comments on Gist, the discussion should happen on this thread.`with` is `for`'s younger brother. Imagine we have two functions:def ok(x), do: {:ok, x}def error(x), do: {:error, x}While `for` is used to match on values out of a collection:for {:ok, x} <- [ok(1), error(2), ok(3)], do: x#=> [1, 3]`with` is used to match on values directly:
with {:ok, x} <- ok(1),{:ok, y} <- ok(2),do: {:ok, x + y}#=> {:ok, 3}
Because all values matched, the `do` block was executed, returning its result. If a value does not match, it will abort the chain:
with {:ok, x} <- ok(1),
{:ok, y} <- error(2),
do: {:ok, x + y}
#=> {:error, 2}Since `error(2)` did not match `{:ok, y}`, the `with` chain aborted, returning `{:error, 2}`.There are many different scenarios on every day Elixir code that we can use `with`. For example, it is useful to avoid nesting "case"s:case File.read(path) do{:ok, binary} ->case :beam_lib.chunks(binary, :abstract_code) do{:ok, data} ->{:ok, wrap(data)}error ->errorenderror ->errorendCan now be rewritten as:
with {:ok, binary} <- File.read(path),{:ok, data} <- :beam_lib.chunks(binary, :abstract_code),do: {:ok, wrap(data)}
Another example is Plug itself. Plug will only call the next plug if the `:halted` field in the connection is false. Therefore a whole plug pipeline can be written as:
with %{halted: false} = conn <- plug1(conn, opts1),%{halted: false} = conn <- plug2(conn, opts2),%{halted: false} = conn <- plug3(conn, opts3),do: conn
If any of them does not match, because `:halted` is true, the pipeline is aborted.
Similarly to `for`, variables bound inside `with` won't leak. Also similar to `for`, `with` allows "bare expressions". For example, imagine you need to calculate a value before calling the next match, you may write:with {:ok, binary} <- File.read(path),header = parse_header(binary),{:ok, data} <- :beam_lib.chunks(header, :abstract_code),do: {:ok, wrap(data)}
That's pretty much the gist of it. Thoughts?## FAQQ: Why `with` instead of one of the operators proposed on other discussions?The operators in the other discussions were always bound to some particular shape. For example, it would always match on `{:ok, _}`, which is limitting. `with` explicitly lays out the pattern, which means you can match on any value you want.Q: Will `with` work with the pipe operator?The answer is no. with, for, the pipe operator are implementations of different monads and we know from other comunities monads do not compose well. Even without a type system, the only way to introduce `with` that works with pipe is by defining something like `withpipe`, and maybe `withfor`, which obviously wouldn't scale because there are too many combinations. Furthermore, we really appreciate that `with` makes all the patterns explicit, instead of hiding it behind a pipe operator. `with` also gives us full control on how the arguments are forwarded.## José goes crazyTo mimic my ElixirConf keynotes, where the talk starts with reasonable proposals and ends-up with me babbling stuff that may not ever see the day of light, let's do it a bit in written form too. :)In 2014, I had proposed `stream for` and `parallel for` support alongside `for` comprehensions. Could we have similar modifiers for `with` too? I am glad you asked!We could at least introduce `async with`:async with part1 <- fetch_part("foo"), # asyncpart2 <- fetch_part("bar"), # async{:ok, page1} <- fetch_page(part2), # await part2, async{:ok, page2} <- fetch_page(part1), # await part1, asyncdo: {page1, page2}The right side of `<-` is always executed inside a new task. As soon as any of the parts finish, the task that depends on the previous one will be resolved. In other words, Elixir will solve the dependency graph for us and write this in the most performant way as possible. It will also ensure that, if a clause does not match, any running task is cancelled.That's not the only example. Ecto could introduce `transactional with`, where we wrap the whole `with` chunk in a transaction and rollback if it does not match. Imagine you want to introduce a `User` model followed by a `Log`, here is how it would be written today:user_changeset = User.changeset(%User{}, params)Repo.transaction fn ->case Repo.insert(user_changeset) do{:ok, user} ->
log_changeset = Log.changeset(%Log{user_id: user.id}, params)
case Repo.insert(log_changeset) do{:ok, log} -> {user, log}{:error, log_changeset} -> Repo.rollback log_changesetend{:error, user_changeset} ->Repo.rollback user_changesetendNow with `transactional with`:user_changeset = User.changeset(%User{}, params)transactional with user <- Repo.insert(user_changeset),
log_changeset = Log.changeset(%Log{user_id: user.id}, params),log <- Repo.insert(log_changeset),do: {user, log}
Note: we can't use `transaction` as a name because it is already part of the Ecto.Repo API. If someone knows a shorter word than `transactional`, I would appreciate it. Please send me a personal e-mail. :)You can see a discussion about this Ecto example in particular here: https://github.com/elixir-lang/ecto/issues/1009. Of course, there is a lot of prior art on all of this, but those last two examples, async and transactional, are heavily inspired by computation expressions from F#.While this "José goes crazy" section is meant to highlight how we could extend this feature, let's focus on the first part of this issue: the barebone `with`. It is definitely useful enough to stand on its own.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2By4Y3%3DX7%3DrVBmyh4dfk6OWu3Y%3DyxMa%2B6bUXh6ajF0puQ%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/6b329ccb-4bf2-4988-aaa7-501657decf5e%40googlegroups.com.
At the risk of showing people they've been right about my lack of intelligence all along . . .with {:ok, x} <- ok(1),{:ok, y} <- ok(2),do{:ok, x + y}#other statementsendis implied in the proposal right? I mean do: vs. do . . . end are no different in this proposal right?
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J2z4mAmf2XdqX7ps30CdtDPQVYB%2BYtQh4O6Xd3sYyV9Q%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/baef1203-fd13-4950-b78b-66f788a3b8a7%40googlegroups.com.
Such great fun just to follow the evolution of Elixir. Like before Jose, you just interrupt the discussion of monads and pipe operator variations with a completely different, and quite obivously good suggestion. We could all have come up with that particular solution, but you were the one to do it :)
Before I start any criticism, let me just make it clear that I really like the suggested change. It seems quite similar to Haskell's let .. in construct.
Now I haven't had the time to digest this properly, but my critisism would be that the formatting is less readable compared to the pipe that we like so much. The `do` block seems a bit redundant for many uses. I think if we were to keep the piping, we only needed to have pattern filters along the pipes:
# using with
with {:ok, binary} <- File.read(path),{:ok, data} <- :beam_lib.chunks(binary, :abstract_code),
do: {:ok, wrap(data)}|> [{:ok, &}] wrap
# using pipe patterns
File.read(path)
|> [{:ok, &}] :beam_lib.chunks(:abstract_code))
I realize that this particular syntax is full of issues, just food for thought...
--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/lzNhT87-XUU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BMMnF1oHXHOk2K%2B2X8tqnc2tXtVj41MTdLwWafdzW5jQ%40mail.gmail.com.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAPCQOz2mHhg%3DtuxnBHmAopkfgfzqAj9wBXsCoGH6_FmViihjeQ%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LX2UmEWt2o-LAU%2B%2BqoBTqcxitz%3DJb5id1P9z38ddTGBg%40mail.gmail.com.
On the other hand, I have a hard time imagining how `transact with` could be implemented. Would transact be a macro?
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LX2UmEWt2o-LAU%2B%2BqoBTqcxitz%3DJb5id1P9z38ddTGBg%40mail.gmail.com.
Note: Proposal can also be read on gist. Please do not drop comments on Gist, the discussion should happen on this thread.`with` is `for`'s younger brother. Imagine we have two functions:def ok(x), do: {:ok, x}def error(x), do: {:error, x}While `for` is used to match on values out of a collection:for {:ok, x} <- [ok(1), error(2), ok(3)], do: x#=> [1, 3]`with` is used to match on values directly:
with {:ok, x} <- ok(1),{:ok, y} <- ok(2),do: {:ok, x + y}
#=> {:ok, 3}Because all values matched, the `do` block was executed, returning its result. If a value does not match, it will abort the chain:
with {:ok, x} <- ok(1),
{:ok, y} <- error(2),
do: {:ok, x + y}
#=> {:error, 2}Since `error(2)` did not match `{:ok, y}`, the `with` chain aborted, returning `{:error, 2}`.There are many different scenarios on every day Elixir code that we can use `with`. For example, it is useful to avoid nesting "case"s:case File.read(path) do{:ok, binary} ->case :beam_lib.chunks(binary, :abstract_code) do{:ok, data} ->{:ok, wrap(data)}error ->errorenderror ->errorendCan now be rewritten as:
with {:ok, binary} <- File.read(path),{:ok, data} <- :beam_lib.chunks(binary, :abstract_code),do: {:ok, wrap(data)}
Another example is Plug itself. Plug will only call the next plug if the `:halted` field in the connection is false. Therefore a whole plug pipeline can be written as:
with %{halted: false} = conn <- plug1(conn, opts1),
%{halted: false} = conn <- plug2(conn, opts2),%{halted: false} = conn <- plug3(conn, opts3),do: conn
If any of them does not match, because `:halted` is true, the pipeline is aborted.Similarly to `for`, variables bound inside `with` won't leak. Also similar to `for`, `with` allows "bare expressions". For example, imagine you need to calculate a value before calling the next match, you may write:
with {:ok, binary} <- File.read(path),
What about exeptions?
What would happen if plug2 throw an exception?with %{halted: false} = conn <- plug1(conn, opts1),%{halted: false} = conn <- plug2(conn, opts2),%{halted: false} = conn <- plug3(conn, opts3),do: conn
Or what would happen if in `async` one of tasks was killed?
However I do want to note that we should watch how we express ourselves here - and this critique is clearly directed at Booker. While I understand (and share) your strong opinion, hate is a pretty strong word.
--
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/lzNhT87-XUU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/8631dbb4-5b89-4781-a71c-65565d870fd5%40googlegroups.com.
My sincerest apologies, I was trying to be amusing and it fell flatter than a pancake.
- Booker C. Bense
On Friday, October 23, 2015, Michael Schaefermeyer <michael.sc...@gmail.com> wrote:
Very happy about this.--Like I stated earlier, the "syntactic" concerns seem manageable and are far outweighed by the possibilities this gives us. Thank you!One thing to:The while I was using above absolutely was accidental. That's what you get for writing replies at 1:15am. I apologise.However I do want to note that we should watch how we express ourselves here - and this critique is clearly directed at Booker. While I understand (and share) your strong opinion, hate is a pretty strong word. The way you hammered your point home reminded me of OSS communities we would strive to not become like (example: Linux Kernel). So while my mistake was stupid, please let's always keep a friendly tone. This is one of the many things that make this community so awesome: The respect and fun we have for and with one another while doing this.Thanks
Am Freitag, 23. Oktober 2015 11:45:43 UTC+2 schrieb José Valim:On the other hand, I have a hard time imagining how `transact with` could be implemented. Would transact be a macro?We will have a couple functions in Macro that will receive the AST and parse it out for us. This function can be shared for those implementing either custom "with"s or custom "for"s. Similar to Macro.pipe and Macro.unpipe. Although I think the bulk of it can't really be shared.
You received this message because you are subscribed to a topic in the Google Groups "elixir-lang-core" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/elixir-lang-core/lzNhT87-XUU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to elixir-lang-core+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/1EC16775-1315-482B-BD05-659341A7E26C%40chrismccord.com.
Note: Proposal can also be read on gist. Please do not drop comments on Gist, the discussion should happen on this thread.
with %{halted: false} = conn <- plug1(conn, opts1),
%{halted: false} = conn <- plug2(conn, opts2),%{halted: false} = conn <- plug3(conn, opts3),do: conn
If any of them does not match, because `:halted` is true, the pipeline is aborted.Similarly to `for`, variables bound inside `with` won't leak. Also similar to `for`, `with` allows "bare expressions". For example, imagine you need to calculate a value before calling the next match, you may write:with {:ok, binary} <- File.read(path),header = parse_header(binary),{:ok, data} <- :beam_lib.chunks(header, :abstract_code),do: {:ok, wrap(data)}That's pretty much the gist of it. Thoughts?
## FAQ
Q: Why `with` instead of one of the operators proposed on other discussions?
The operators in the other discussions were always bound to some particular shape. For example, it would always match on `{:ok, _}`, which is limitting. `with` explicitly lays out the pattern, which means you can match on any value you want.
Q: Will `with` work with the pipe operator?
The answer is no. with, for, the pipe operator are implementations of different monads and we know from other comunities monads do not compose well. Even without a type system, the only way to introduce `with` that works with pipe is by defining something like `withpipe`, and maybe `withfor`, which obviously wouldn't scale because there are too many combinations. Furthermore, we really appreciate that `with` makes all the patterns explicit, instead of hiding it behind a pipe operator. `with` also gives us full control on how the arguments are forwarded.
## José goes crazy
To mimic my ElixirConf keynotes, where the talk starts with reasonable proposals and ends-up with me babbling stuff that may not ever see the day of light, let's do it a bit in written form too. :)In 2014, I had proposed `stream for` and `parallel for` support alongside `for` comprehensions. Could we have similar modifiers for `with` too? I am glad you asked!We could at least introduce `async with`:
async with part1 <- fetch_part("foo"), # async
José Valim
That's correct, Nami. This is going to be implemented in an upcoming version of Elixir. 1.2, I think.
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/d8e055da-2513-4739-8497-b9b18500de0b%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAHi9bZoFQQ-SyqxUhhdwW3Ksd9oXGgQUVasGXMK8Yz9BYuPiDA%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CA%2BibZ9-2wDWdqgaE1EW_hfwarc2K2T5arHj4Jr8Cp%2Bu5GuyFBA%40mail.gmail.com.
with do
%{halted: false} = conn <- plug1(conn, opts1)
%{halted: false} = conn <- plug2(conn, opts2)
%{halted: false} = conn <- plug3(conn, opts3)
conn
endTo view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LfKx9GAZmSEcvHYpb59WwadxdD%3DuBVJxZGc3SO6UpVyw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAOtk34e9ZHbcjY5-sPwPZkfwT7Xp6GVsH7wDZuGb4x6DvDy7Rw%40mail.gmail.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4%2BqrB9iVkwxTOiw61TKA7%3Dtm48vLOvLnjF8VteihYutzw%40mail.gmail.com.
with {:ok, x} <- ok(1),
{:ok, y} <- error(2),
do: {:ok, x + y}
#=> {:error, 2}
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/19d3ba76-da05-4560-bdb9-9e2a2ef374e0%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4LfKx9GAZmSEcvHYpb59WwadxdD%3DuBVJxZGc3SO6UpVyw%40mail.gmail.com.
The implementation is already in master thanks to lexmag. :)
--
You received this message because you are subscribed to the Google Groups "elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-co...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/9a5fb079-07a7-44d4-ab3d-d6ab1ab8a9bd%40googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/db5ad17a-3ed4-4bba-b117-264889233bb5%40googlegroups.com.