简体   繁体   中英

Updating named-function variable inside anonymous function Elixir

I'm new to Elixir and trying to solve guitar tab problem. My code:

def sumTabs([head|tail], result) do
        nextLine = hd(tail)
        tail = List.delete(tail, nextLine)
        head
        |> Enum.with_index
        |> Enum.each(fn({x, i}) ->
            s = [x <> Enum.at(nextLine, i) |> to_charlist]
            IO.inspect s
            result = [result | s] 
            IO.inspect result end)
        result
    end

I want to update result, which is an empty list at the start, but in each iteration of Enum.each function, the result is empty. I think it is because of the anonymous function.

For the start I want it to work at least with two lines.

Input:

tab = """
  e|-7-----7-----7-----7-----5-----3-----3-----2-----0-----0-----|
  B|---0-----0-----0-----0-----0-----0-----0-----0-----0-----0---|
  G|-----0-----0-----0-----0-----0-----0-----0-----0-----0-----0-|
  D|-------------------------------------------------------------|
  A|-------------------------------------------------------------|
  E|-------------------------------------------------------------|
  """

Output:

['eB']
[[], 'eB']
['||']
[[], '||']
['--']
[[], '--']
['7-']
[[], '7-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['7-']
[[], '7-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['7-']
[[], '7-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['7-']
[[], '7-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['5-']
[[], '5-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['3-']
[[], '3-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['3-']
[[], '3-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['2-']
[[], '2-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['0-']
[[], '0-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['0-']
[[], '0-']
['--']
[[], '--']
['-0']
[[], '-0']
['--']
[[], '--']
['--']
[[], '--']
['--']
[[], '--']
['||']
[[], '||']

Code before sumTabs function:

defmodule TabPlayer do
    def parse(tab) do
        String.split(tab, "\n") 
            |> Enum.map(fn n -> to_string n end)
            |> List.delete([])
            |> Enum.map(fn n -> String.graphemes n end)
            |> sumTabs([])
            |> IO.inspect
    end

Variables in Elixir are immutable. You cannot reassign the value inside Enum.each and expect it to change outside. What this code does is create a new result value that lasts until the end of the anonymous function.

You can use Enum.reduce/3 here, returning the new result value on every iteration. Assuming the rest of your logic is correct, here's how the code can be rewritten to use Enum.reduce/3 . Note that I'm making use of the fact that IO.inspect prints a value and then returns it. So IO.inspect(x); x IO.inspect(x); x is the same as IO.inspect(x) .

def sumTabs([head|tail], result) do
  nextLine = hd(tail)
  tail = List.delete(tail, nextLine)
  head
  |> Enum.with_index
  |> Enum.reduce([], fn({x, i}, acc) ->
    s = IO.inspect [x <> Enum.at(nextLine, i) |> to_charlist]
    IO.inspect [s | acc]
  end)
  # We need to reverse at the end since we're creating a reversed list in
  # `Enum.reduce` for efficiency.
  |> Enum.reverse
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM