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

vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
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
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

Other popular topics Top

Qqwy
Update: How to use the Blogs &amp; Podcasts section You can post links to your blog posts or podcasts either in one of the Official Blog...
3271 130579 1222
New
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
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
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

We're in Beta

About us Mission Statement