How to do a name calculator? Mine throws errors! (newbie)

Hi there Elixir guys and gals,

I’m new to Elixir, trying to build a name calculator for exercise.

It should let you type in a name and give you back a number! So, “a” is represented by 1, “b” by 2, but it only counts up to 9 so that “j” is also represented by 1, ending with “z” as 8. Those numbers of the respective letters will be added and the result is the response the user should get.

So I tried it like that:

defmodule NameCalc do

  def add(x) do
    letterlist = String.graphemes("#{x}")
    for n <- letterlist, do: %{"a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5, "f" => 6, "g" => 7,
  "h" => 8, "i" => 9, "j" => 1, "k" => 2, "l" => 3, "m" => 4, "n" => 5,
  "o" => 6, "p" => 7, "q" => 8, "r" => 9, "s" => 1, "t" => 2, "u" => 3,
  "v" => 4, "w" => 5, "x" => 6, "y" => 7, "z" => 8}[n]
    |> Sum.sum
  end
end

defmodule Sum do
  def sum ([]) do
    0
  end
  def sum([h | t]) do
    h + sum(t)
  end
end

It seems like I’m doing something (several things) completely wrong!

It yells at me:

undefined function x/0

I’m sure this isn’t the only mistake in my file?

Where are my mistakes? Thx everybody.

V. Jim Deeno

You do not have a binding or call of name anywhere in your posted code at all? o.O

I have no clue how you’d be getting that error at all based on the code you supplied.

Also, instead of Summe.sum don’t you mean Sum.sum?

Also I’d probably just do (single-long-line because I’m testing in iex, reformat as you wish ^.^;):

(fn(name) -> name |> String.downcase() |> String.graphemes() |> Enum.map(fn(<<c::utf8>>) -> rem(c-?a, 9)+1 end) |> Enum.sum() end).("myname")
1 Like

I was a bit hasty there, made some edits without corresponding readjustments! Sorry for the confusions!

So it’s not name, it’s x correspondingly!
And: yes it’s Sum.sum

Even though your code is much better I’m still curious about why my script didn’t work. Do you have an idea? I’m afraid this problem will rearise in my next exercise :wink:

Ok, that’s interesting how smooth and clean your code looks and it gets the job done! I still have some follow-ups if you don’t mind

Enum.map(fn(<<c::utf8>>) -> rem(c-?a, 9)+1 end)

Could you just give a very general description about what this is doing and how you came up with that? Hope that’s not too fuzzy a question!

Hoping everyone has a good day.

V. Jim Deeno

Well if x is actually name then I’m not sure, nothing looks wrong, so I’d need to see your complete and reproducible example to see why. :slight_smile:

I’m just matching out the single character that is from the grapheme call. It is the entirely lazy way to do it and is not how I’d recommend doing it in this case, but it worked fine for your trivial example that only supported a-z and no other characters. ^.^;

I probably should have done String.to_charlist() instead of the grapheme call there, but eh… ^.^;

Add parenthesis around your for ala (for ..., do: ...) and only pass in lowercase strings, and your implementation should work.

(The parenthesis requirement might be a bug with Elixir. Without the parenthesis it places |> Sum.sum inside the do rather than after it.)

Ahh true true! |> binds tightly!

This is why I really think for should be an expression body and not arguments as it would prevent these errors. ^.^

thx
Just tried that. It’s still throwing the same error … too bad

and @OvermindDL1 there’s really nothing more to this story … so I’m in the shell, writing
iex then
iex> c("filename.exs")
[Sum, NameCalc]
iex> NameCalc.add(whatevername)
and … sadly the output is
** (CompileError) iex:2: undefined function whatevername/0

So for some unforeseen reason the machine interprets my input as a function with the arity of zero?!

V. Jim Deeno

You need to pass a string: NameCalc.add("whatevername"). Simply writing whatevername by itself refers to a variable or function.

1 Like

Oh… sure, what just happened to my reputation.

V. Jim Deeno

1 Like