Enum.reduce retruning :ok after first iterationelixir not updating values in mapset using enum.eachHow do you create and load modules dynamically at runtime in Elixir, or Erlang?Enum.reduce/2 doesn't output IOReturn Map or Convert to Map? word-count elixirElixir Phoenix shutdown: failed to start childCreate Map on iterationIncreasing date with few miliseonds using Enum.reduce ElixirErlang Binary Leak?Why is this tail recursion not faster than its non-tail recursive implementation?Select Merge not working as expected inside Enum.reduceWhile macro bind_quoted breaks on first iteration
What is this old "lemon-squeezer" shaped pan
Doing research in academia and not liking competition
Why does the autopilot disengage even when it does not receive pilot input?
What is the closed form of the following recursive function?
Supporting developers who insist on using their pet language
Access files in Home directory from live mode
How might the United Kingdom become a republic?
Won 50K! Now what should I do with it
Is it rude to tell recruiters I would only change jobs for a better salary?
Does ability to impeach an expert witness on science or scholarship go too far?
Crab Nebula short story from 1960s or '70s
I quit, and boss offered me 3 month "grace period" where I could still come back
Is this more than a packing puzzle?
Too many spies!
mhchem - bold part of equation typeset with ce
How can I legally visit the United States Minor Outlying Islands in the Pacific?
Would letting a multiclass character rebuild their character to be single-classed be game-breaking?
What exactly is the Tension force?
Do native speakers use ZVE or CPU?
Alternatives to using writing paper for writing practice
Add region constraint to Graphics
Mistakenly modified `/bin/sh'
Confused about 誘われて (Sasowarete)
Why are Japanese translated subtitles non-conversational?
Enum.reduce retruning :ok after first iteration
elixir not updating values in mapset using enum.eachHow do you create and load modules dynamically at runtime in Elixir, or Erlang?Enum.reduce/2 doesn't output IOReturn Map or Convert to Map? word-count elixirElixir Phoenix shutdown: failed to start childCreate Map on iterationIncreasing date with few miliseonds using Enum.reduce ElixirErlang Binary Leak?Why is this tail recursion not faster than its non-tail recursive implementation?Select Merge not working as expected inside Enum.reduceWhile macro bind_quoted breaks on first iteration
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I am passing a list consist of integers as strings in Enum.reduce, and running a function on each value of the list. But the problem is in second iteration it is returning :ok, due to which function is giving error, I am using multiple IO.puts in my code just to trace the error.
Below is my function to_decimal and when we pass "11" as parameter, then it should return decimal representation of this binary value. But it stops in second iteration, I will write the output below -
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list,0, fn x,acc ->
temp=String.to_integer(x)
power = round(:math.pow(2,len-1))
IO.puts(power)
acc = acc + temp*power
IO.puts(acc)
len=len-1
IO.puts(len)
end)
end
iex(1)> Binary.to_decimal("11")
2
2
1
2
** (ArithmeticError) bad argument in arithmetic expression: :ok + 2
:erlang.+(:ok, 2)
binary.exs:16: anonymous fn/3 in Binary.to_decimal/1
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
elixir
add a comment |
I am passing a list consist of integers as strings in Enum.reduce, and running a function on each value of the list. But the problem is in second iteration it is returning :ok, due to which function is giving error, I am using multiple IO.puts in my code just to trace the error.
Below is my function to_decimal and when we pass "11" as parameter, then it should return decimal representation of this binary value. But it stops in second iteration, I will write the output below -
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list,0, fn x,acc ->
temp=String.to_integer(x)
power = round(:math.pow(2,len-1))
IO.puts(power)
acc = acc + temp*power
IO.puts(acc)
len=len-1
IO.puts(len)
end)
end
iex(1)> Binary.to_decimal("11")
2
2
1
2
** (ArithmeticError) bad argument in arithmetic expression: :ok + 2
:erlang.+(:ok, 2)
binary.exs:16: anonymous fn/3 in Binary.to_decimal/1
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
elixir
add a comment |
I am passing a list consist of integers as strings in Enum.reduce, and running a function on each value of the list. But the problem is in second iteration it is returning :ok, due to which function is giving error, I am using multiple IO.puts in my code just to trace the error.
Below is my function to_decimal and when we pass "11" as parameter, then it should return decimal representation of this binary value. But it stops in second iteration, I will write the output below -
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list,0, fn x,acc ->
temp=String.to_integer(x)
power = round(:math.pow(2,len-1))
IO.puts(power)
acc = acc + temp*power
IO.puts(acc)
len=len-1
IO.puts(len)
end)
end
iex(1)> Binary.to_decimal("11")
2
2
1
2
** (ArithmeticError) bad argument in arithmetic expression: :ok + 2
:erlang.+(:ok, 2)
binary.exs:16: anonymous fn/3 in Binary.to_decimal/1
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
elixir
I am passing a list consist of integers as strings in Enum.reduce, and running a function on each value of the list. But the problem is in second iteration it is returning :ok, due to which function is giving error, I am using multiple IO.puts in my code just to trace the error.
Below is my function to_decimal and when we pass "11" as parameter, then it should return decimal representation of this binary value. But it stops in second iteration, I will write the output below -
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list,0, fn x,acc ->
temp=String.to_integer(x)
power = round(:math.pow(2,len-1))
IO.puts(power)
acc = acc + temp*power
IO.puts(acc)
len=len-1
IO.puts(len)
end)
end
iex(1)> Binary.to_decimal("11")
2
2
1
2
** (ArithmeticError) bad argument in arithmetic expression: :ok + 2
:erlang.+(:ok, 2)
binary.exs:16: anonymous fn/3 in Binary.to_decimal/1
(elixir) lib/enum.ex:1925: Enum."-reduce/3-lists^foldl/2-0-"/3
elixir
elixir
asked Mar 26 at 6:30
user9106677user9106677
162 bronze badges
162 bronze badges
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
For real-world code, you should go with the pre-rolled solution:
String.to_integer(string, 2)
That being said, let's treat this as an exercise for learning more about Elixir. A common pitfall with Elixir is a misconception about variable scope. Variables in Elixir are immutable and always local in scope, but they can be rebound to new values. This makes it hard to wrap your head around if you're just starting out because it looks like you can change the value, but in fact you're just binding the variable name to a new value. This means the original scope will still be bound to the same value:
counter = 0
for i <- 1..10 do
counter = counter + 1
end
IO.inspect counter # prints 0
Another way to think about this is that the inner counter is simply a new variable that happens to have the same name as the outer one. The above example is equivalent to:
counter = 0
for i <- 1..10 do
new_counter = counter + 1
end
To get around this, as you already correctly observed, we use functions like Enum.reduce/2-3 which allow us to store intermediate results in an accumulator. So each of the variables that need remembering must go in the accumulator. The value for the next iteration is then returned from the anonymous function, which allows Enum.reduce to pass it back into the next iteration.
In your case, this means that you'll want to remember the len and sum, which we can put in a tuple to pass it around as sum, len. The basic structure of your reduction should be:
result = Enum.reduce list, 0, len, fn sum, len ->
new_sum = sum + ...
new_len = ...
new_sum, new_len
end
sum, _ = result
sum
If you want to go one step further and get a better feeling of how all those pieces fit together, I highly recommend reading the first few chapters of Programming Elixir by Dave Thomas. It includes some exercises to build utilities like Enum.reduce from the ground up which helps tremendously.
As a final remark, there are still some things that could be improved in your code. For example it will happily accept invalid digits like "2". Just as an inspiration, here's how I would tackle this problem:
string
|> String.graphemes
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn
"0", _, acc -> acc
"1", i, acc -> acc + :math.pow(2, i)
end)
|> trunc()
I already hear some voices screaming: "but now you're iterating multiple times over the list" to which I would reply that clarity goes over performance optimization, as long as this is not a bottleneck. If you really find that you need to squeeze the last bit of performance out of this, it's usually best to write a tail-recursive function that does not rely on the Enum module at all, but I'll leave that up to you to explore.
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
add a comment |
You should return the new acc in each iteration. Currently the last expression in the "callback" function (that is the fun in thereduce(enumerable, acc, fun)) is IO.puts which returns :ok. You should build the new acc in each iteration and return it which will be used in the next iteration.
Note that in Elixir data structures are immutable. Also beware that you're not changing the len that exists in the upper scope. Basically what you doing is throw_away = len - 1.
Check out this answer if you want to know more about variable scope.
add a comment |
Using Enum.reduce the way you're doing it isn't the best approach for your problem.
This is because each iteration of Enum.reduce should "return" the accumulator for the next iteration.
When you put acc = acc + temp * power and len = len-1, you aren't assigning acc and len to have the values you're giving them in the next iteration, just on the current one, and in fact, you should be getting warnings about those variables being unused.
At the end of your block, since the last thing you're doing is len = len - 1, and since len will always be the same, what you're passing on to the next iteration is always 1, in the case of the input of "11".
And when you add the IO.puts/1, at the end, you're passing :ok (the "return" of IO.puts) to the next iteration, which produces the error you're seeing.
an alternative approach using Enum.reduce could be to keep a tuple len, sum and at the end of the block, put always the new values for len and sum.
So, you could change it like:
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list, 0, len, fn x, sum, len ->
temp = String.to_integer(x)
power = :math.pow(2, len - 1) |> round()
sum = sum + temp * power
len = len - 1
sum, len
end)
end
This will at the end return a tuple containing n, l where n will be the decimal representation, and, l, the final length.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55351029%2fenum-reduce-retruning-ok-after-first-iteration%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
For real-world code, you should go with the pre-rolled solution:
String.to_integer(string, 2)
That being said, let's treat this as an exercise for learning more about Elixir. A common pitfall with Elixir is a misconception about variable scope. Variables in Elixir are immutable and always local in scope, but they can be rebound to new values. This makes it hard to wrap your head around if you're just starting out because it looks like you can change the value, but in fact you're just binding the variable name to a new value. This means the original scope will still be bound to the same value:
counter = 0
for i <- 1..10 do
counter = counter + 1
end
IO.inspect counter # prints 0
Another way to think about this is that the inner counter is simply a new variable that happens to have the same name as the outer one. The above example is equivalent to:
counter = 0
for i <- 1..10 do
new_counter = counter + 1
end
To get around this, as you already correctly observed, we use functions like Enum.reduce/2-3 which allow us to store intermediate results in an accumulator. So each of the variables that need remembering must go in the accumulator. The value for the next iteration is then returned from the anonymous function, which allows Enum.reduce to pass it back into the next iteration.
In your case, this means that you'll want to remember the len and sum, which we can put in a tuple to pass it around as sum, len. The basic structure of your reduction should be:
result = Enum.reduce list, 0, len, fn sum, len ->
new_sum = sum + ...
new_len = ...
new_sum, new_len
end
sum, _ = result
sum
If you want to go one step further and get a better feeling of how all those pieces fit together, I highly recommend reading the first few chapters of Programming Elixir by Dave Thomas. It includes some exercises to build utilities like Enum.reduce from the ground up which helps tremendously.
As a final remark, there are still some things that could be improved in your code. For example it will happily accept invalid digits like "2". Just as an inspiration, here's how I would tackle this problem:
string
|> String.graphemes
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn
"0", _, acc -> acc
"1", i, acc -> acc + :math.pow(2, i)
end)
|> trunc()
I already hear some voices screaming: "but now you're iterating multiple times over the list" to which I would reply that clarity goes over performance optimization, as long as this is not a bottleneck. If you really find that you need to squeeze the last bit of performance out of this, it's usually best to write a tail-recursive function that does not rely on the Enum module at all, but I'll leave that up to you to explore.
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
add a comment |
For real-world code, you should go with the pre-rolled solution:
String.to_integer(string, 2)
That being said, let's treat this as an exercise for learning more about Elixir. A common pitfall with Elixir is a misconception about variable scope. Variables in Elixir are immutable and always local in scope, but they can be rebound to new values. This makes it hard to wrap your head around if you're just starting out because it looks like you can change the value, but in fact you're just binding the variable name to a new value. This means the original scope will still be bound to the same value:
counter = 0
for i <- 1..10 do
counter = counter + 1
end
IO.inspect counter # prints 0
Another way to think about this is that the inner counter is simply a new variable that happens to have the same name as the outer one. The above example is equivalent to:
counter = 0
for i <- 1..10 do
new_counter = counter + 1
end
To get around this, as you already correctly observed, we use functions like Enum.reduce/2-3 which allow us to store intermediate results in an accumulator. So each of the variables that need remembering must go in the accumulator. The value for the next iteration is then returned from the anonymous function, which allows Enum.reduce to pass it back into the next iteration.
In your case, this means that you'll want to remember the len and sum, which we can put in a tuple to pass it around as sum, len. The basic structure of your reduction should be:
result = Enum.reduce list, 0, len, fn sum, len ->
new_sum = sum + ...
new_len = ...
new_sum, new_len
end
sum, _ = result
sum
If you want to go one step further and get a better feeling of how all those pieces fit together, I highly recommend reading the first few chapters of Programming Elixir by Dave Thomas. It includes some exercises to build utilities like Enum.reduce from the ground up which helps tremendously.
As a final remark, there are still some things that could be improved in your code. For example it will happily accept invalid digits like "2". Just as an inspiration, here's how I would tackle this problem:
string
|> String.graphemes
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn
"0", _, acc -> acc
"1", i, acc -> acc + :math.pow(2, i)
end)
|> trunc()
I already hear some voices screaming: "but now you're iterating multiple times over the list" to which I would reply that clarity goes over performance optimization, as long as this is not a bottleneck. If you really find that you need to squeeze the last bit of performance out of this, it's usually best to write a tail-recursive function that does not rely on the Enum module at all, but I'll leave that up to you to explore.
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
add a comment |
For real-world code, you should go with the pre-rolled solution:
String.to_integer(string, 2)
That being said, let's treat this as an exercise for learning more about Elixir. A common pitfall with Elixir is a misconception about variable scope. Variables in Elixir are immutable and always local in scope, but they can be rebound to new values. This makes it hard to wrap your head around if you're just starting out because it looks like you can change the value, but in fact you're just binding the variable name to a new value. This means the original scope will still be bound to the same value:
counter = 0
for i <- 1..10 do
counter = counter + 1
end
IO.inspect counter # prints 0
Another way to think about this is that the inner counter is simply a new variable that happens to have the same name as the outer one. The above example is equivalent to:
counter = 0
for i <- 1..10 do
new_counter = counter + 1
end
To get around this, as you already correctly observed, we use functions like Enum.reduce/2-3 which allow us to store intermediate results in an accumulator. So each of the variables that need remembering must go in the accumulator. The value for the next iteration is then returned from the anonymous function, which allows Enum.reduce to pass it back into the next iteration.
In your case, this means that you'll want to remember the len and sum, which we can put in a tuple to pass it around as sum, len. The basic structure of your reduction should be:
result = Enum.reduce list, 0, len, fn sum, len ->
new_sum = sum + ...
new_len = ...
new_sum, new_len
end
sum, _ = result
sum
If you want to go one step further and get a better feeling of how all those pieces fit together, I highly recommend reading the first few chapters of Programming Elixir by Dave Thomas. It includes some exercises to build utilities like Enum.reduce from the ground up which helps tremendously.
As a final remark, there are still some things that could be improved in your code. For example it will happily accept invalid digits like "2". Just as an inspiration, here's how I would tackle this problem:
string
|> String.graphemes
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn
"0", _, acc -> acc
"1", i, acc -> acc + :math.pow(2, i)
end)
|> trunc()
I already hear some voices screaming: "but now you're iterating multiple times over the list" to which I would reply that clarity goes over performance optimization, as long as this is not a bottleneck. If you really find that you need to squeeze the last bit of performance out of this, it's usually best to write a tail-recursive function that does not rely on the Enum module at all, but I'll leave that up to you to explore.
For real-world code, you should go with the pre-rolled solution:
String.to_integer(string, 2)
That being said, let's treat this as an exercise for learning more about Elixir. A common pitfall with Elixir is a misconception about variable scope. Variables in Elixir are immutable and always local in scope, but they can be rebound to new values. This makes it hard to wrap your head around if you're just starting out because it looks like you can change the value, but in fact you're just binding the variable name to a new value. This means the original scope will still be bound to the same value:
counter = 0
for i <- 1..10 do
counter = counter + 1
end
IO.inspect counter # prints 0
Another way to think about this is that the inner counter is simply a new variable that happens to have the same name as the outer one. The above example is equivalent to:
counter = 0
for i <- 1..10 do
new_counter = counter + 1
end
To get around this, as you already correctly observed, we use functions like Enum.reduce/2-3 which allow us to store intermediate results in an accumulator. So each of the variables that need remembering must go in the accumulator. The value for the next iteration is then returned from the anonymous function, which allows Enum.reduce to pass it back into the next iteration.
In your case, this means that you'll want to remember the len and sum, which we can put in a tuple to pass it around as sum, len. The basic structure of your reduction should be:
result = Enum.reduce list, 0, len, fn sum, len ->
new_sum = sum + ...
new_len = ...
new_sum, new_len
end
sum, _ = result
sum
If you want to go one step further and get a better feeling of how all those pieces fit together, I highly recommend reading the first few chapters of Programming Elixir by Dave Thomas. It includes some exercises to build utilities like Enum.reduce from the ground up which helps tremendously.
As a final remark, there are still some things that could be improved in your code. For example it will happily accept invalid digits like "2". Just as an inspiration, here's how I would tackle this problem:
string
|> String.graphemes
|> Enum.reverse
|> Enum.with_index
|> Enum.reduce(0, fn
"0", _, acc -> acc
"1", i, acc -> acc + :math.pow(2, i)
end)
|> trunc()
I already hear some voices screaming: "but now you're iterating multiple times over the list" to which I would reply that clarity goes over performance optimization, as long as this is not a bottleneck. If you really find that you need to squeeze the last bit of performance out of this, it's usually best to write a tail-recursive function that does not rely on the Enum module at all, but I'll leave that up to you to explore.
edited Mar 26 at 13:46
answered Mar 26 at 8:46
Patrick OscityPatrick Oscity
44k13 gold badges112 silver badges137 bronze badges
44k13 gold badges112 silver badges137 bronze badges
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
add a comment |
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
1
1
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
I think that last point should really be the first point.
– Adam Millerchip
Mar 26 at 13:29
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
@AdamMillerchip fair point, thanks.
– Patrick Oscity
Mar 26 at 13:45
add a comment |
You should return the new acc in each iteration. Currently the last expression in the "callback" function (that is the fun in thereduce(enumerable, acc, fun)) is IO.puts which returns :ok. You should build the new acc in each iteration and return it which will be used in the next iteration.
Note that in Elixir data structures are immutable. Also beware that you're not changing the len that exists in the upper scope. Basically what you doing is throw_away = len - 1.
Check out this answer if you want to know more about variable scope.
add a comment |
You should return the new acc in each iteration. Currently the last expression in the "callback" function (that is the fun in thereduce(enumerable, acc, fun)) is IO.puts which returns :ok. You should build the new acc in each iteration and return it which will be used in the next iteration.
Note that in Elixir data structures are immutable. Also beware that you're not changing the len that exists in the upper scope. Basically what you doing is throw_away = len - 1.
Check out this answer if you want to know more about variable scope.
add a comment |
You should return the new acc in each iteration. Currently the last expression in the "callback" function (that is the fun in thereduce(enumerable, acc, fun)) is IO.puts which returns :ok. You should build the new acc in each iteration and return it which will be used in the next iteration.
Note that in Elixir data structures are immutable. Also beware that you're not changing the len that exists in the upper scope. Basically what you doing is throw_away = len - 1.
Check out this answer if you want to know more about variable scope.
You should return the new acc in each iteration. Currently the last expression in the "callback" function (that is the fun in thereduce(enumerable, acc, fun)) is IO.puts which returns :ok. You should build the new acc in each iteration and return it which will be used in the next iteration.
Note that in Elixir data structures are immutable. Also beware that you're not changing the len that exists in the upper scope. Basically what you doing is throw_away = len - 1.
Check out this answer if you want to know more about variable scope.
edited Mar 26 at 14:20
answered Mar 26 at 7:51
fhdhsnifhdhsni
8201 gold badge8 silver badges16 bronze badges
8201 gold badge8 silver badges16 bronze badges
add a comment |
add a comment |
Using Enum.reduce the way you're doing it isn't the best approach for your problem.
This is because each iteration of Enum.reduce should "return" the accumulator for the next iteration.
When you put acc = acc + temp * power and len = len-1, you aren't assigning acc and len to have the values you're giving them in the next iteration, just on the current one, and in fact, you should be getting warnings about those variables being unused.
At the end of your block, since the last thing you're doing is len = len - 1, and since len will always be the same, what you're passing on to the next iteration is always 1, in the case of the input of "11".
And when you add the IO.puts/1, at the end, you're passing :ok (the "return" of IO.puts) to the next iteration, which produces the error you're seeing.
an alternative approach using Enum.reduce could be to keep a tuple len, sum and at the end of the block, put always the new values for len and sum.
So, you could change it like:
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list, 0, len, fn x, sum, len ->
temp = String.to_integer(x)
power = :math.pow(2, len - 1) |> round()
sum = sum + temp * power
len = len - 1
sum, len
end)
end
This will at the end return a tuple containing n, l where n will be the decimal representation, and, l, the final length.
add a comment |
Using Enum.reduce the way you're doing it isn't the best approach for your problem.
This is because each iteration of Enum.reduce should "return" the accumulator for the next iteration.
When you put acc = acc + temp * power and len = len-1, you aren't assigning acc and len to have the values you're giving them in the next iteration, just on the current one, and in fact, you should be getting warnings about those variables being unused.
At the end of your block, since the last thing you're doing is len = len - 1, and since len will always be the same, what you're passing on to the next iteration is always 1, in the case of the input of "11".
And when you add the IO.puts/1, at the end, you're passing :ok (the "return" of IO.puts) to the next iteration, which produces the error you're seeing.
an alternative approach using Enum.reduce could be to keep a tuple len, sum and at the end of the block, put always the new values for len and sum.
So, you could change it like:
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list, 0, len, fn x, sum, len ->
temp = String.to_integer(x)
power = :math.pow(2, len - 1) |> round()
sum = sum + temp * power
len = len - 1
sum, len
end)
end
This will at the end return a tuple containing n, l where n will be the decimal representation, and, l, the final length.
add a comment |
Using Enum.reduce the way you're doing it isn't the best approach for your problem.
This is because each iteration of Enum.reduce should "return" the accumulator for the next iteration.
When you put acc = acc + temp * power and len = len-1, you aren't assigning acc and len to have the values you're giving them in the next iteration, just on the current one, and in fact, you should be getting warnings about those variables being unused.
At the end of your block, since the last thing you're doing is len = len - 1, and since len will always be the same, what you're passing on to the next iteration is always 1, in the case of the input of "11".
And when you add the IO.puts/1, at the end, you're passing :ok (the "return" of IO.puts) to the next iteration, which produces the error you're seeing.
an alternative approach using Enum.reduce could be to keep a tuple len, sum and at the end of the block, put always the new values for len and sum.
So, you could change it like:
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list, 0, len, fn x, sum, len ->
temp = String.to_integer(x)
power = :math.pow(2, len - 1) |> round()
sum = sum + temp * power
len = len - 1
sum, len
end)
end
This will at the end return a tuple containing n, l where n will be the decimal representation, and, l, the final length.
Using Enum.reduce the way you're doing it isn't the best approach for your problem.
This is because each iteration of Enum.reduce should "return" the accumulator for the next iteration.
When you put acc = acc + temp * power and len = len-1, you aren't assigning acc and len to have the values you're giving them in the next iteration, just on the current one, and in fact, you should be getting warnings about those variables being unused.
At the end of your block, since the last thing you're doing is len = len - 1, and since len will always be the same, what you're passing on to the next iteration is always 1, in the case of the input of "11".
And when you add the IO.puts/1, at the end, you're passing :ok (the "return" of IO.puts) to the next iteration, which produces the error you're seeing.
an alternative approach using Enum.reduce could be to keep a tuple len, sum and at the end of the block, put always the new values for len and sum.
So, you could change it like:
def to_decimal(string) do
list = String.graphemes(string)
len = length(list)
Enum.reduce(list, 0, len, fn x, sum, len ->
temp = String.to_integer(x)
power = :math.pow(2, len - 1) |> round()
sum = sum + temp * power
len = len - 1
sum, len
end)
end
This will at the end return a tuple containing n, l where n will be the decimal representation, and, l, the final length.
edited Mar 26 at 8:18
answered Mar 26 at 7:54
sbacarosbacaro
4051 gold badge5 silver badges11 bronze badges
4051 gold badge5 silver badges11 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55351029%2fenum-reduce-retruning-ok-after-first-iteration%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown