tbk

tbk

Reusing function variables in a `when` conditional

I have a function with a condition:

  def iteraterefs(divisor, number, table, out, i) when number >= divisor do
    number = number - divisor
    out = out <> elem(table, i)
  end

However it seems that the compiler does not like the condition when number >= divisor do, is there something about reuse of function variables I am missing from the documentation?

Marked As Solved

dimitarvp

dimitarvp

IMO this thread is getting a bit too micro, you are kind of posting an error after error and I think you should step back and just post your entire module source code, and state the end goal.

It also sounds like you haven’t practiced Elixir enough if lack of mutability and the lexical scope are still surprising for you. Exercism requires some understanding of the language’s constructs. Without that you’ll just be crashing into one error after another, as it seems it is happening currently.

Also Liked

al2o3cr

al2o3cr

FunctionClauseError is what I’d expect from iteraterefs if it was called with number < divisor. You likely need to define it for those inputs as well to pass Exercism’s tests.

General note: this isn’t going to do what you want. i = i + 1 rebinds the name i inside the do / end block but that value doesn’t escape or even make it to the next iteration.

Same thing for out = out <> elem(table, i) inside iteraterefs; the name out is bound to a new name but then the scope ends immediately.

My recommendation would be to forget completely about Enum.each for a little while; it is almost never the right solution in Elixir.

tbk

tbk

I went away, far up into the mountains which are the Elixir documents, I learned many things and when I returned to take on the challenge again, it neatly folded before me like the recursion I used to solve it:

defmodule RomanNumerals do
  @doc """
  Convert the number to a roman number.
  """
  @table {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
  @refs {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
  @spec numeral(pos_integer) :: String.t()
  def numeral(number) do
    iterate(number, @refs, @table, 0, "")
  end

  defp iterate(num, refs, table, index, out) do
    if num == 0 do 
      out
    else
      ref = elem(refs, index)
      cond do
        num >= ref -> sym = elem(table, index)
                      iterate(num - ref, refs, table, index, out <> sym)
        true -> iterate(num, refs, table, index + 1, out)
      end
    end
  end 
end
benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Nicely done, a big improvement! Probably the only other change I’d advocate for is to do this:

  defp iterate(0, _refs, _table, _index, out) do
    out
  end

  defp iterate(num, refs, table, index, out) do
    ref = elem(refs, index)
    cond do
      num >= ref ->
        sym = elem(table, index)
        iterate(num - ref, refs, table, index, out <> sym)
      true ->
        iterate(num, refs, table, index + 1, out)
    end
  end

It’s conventional that when you’re doing recursion like this to define the “base case” or “termination case” as its own clause up front, and then you have other clauses after. This is entirely a stylistic thing though, so it’s up to you!

Last Post!

tbk

tbk

There is a lot of really good learning in this post. I had been using List splitting in function signatures but had not thought to further disambiguate those elements using a set. The information on Enum and hd/tl was new as was placing wildcards in a signature. The idea of building a list and joining at the end seems to have a lot of value.

Where Next?

Popular in Questions Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New

We're in Beta

About us Mission Statement