'Returning values from elixir functions inside modules
This is the method that processes an input string
def process(input) do
list=String.split(input, "\n")
f3=fn(a) ->
String.split(a," ")
end
list=Enum.map(list, f3)
func3=fn(n) ->
length(n)==3
end
func2=fn(n) ->
length(n)<=2
end
system=for x <-list, func3.(x), do: x
input=for y <- list, func2.(y), do: y
input=Enum.slice(input,0..length(input)-2)
output=""
output(input,output, system)
end
This is the output function that uses recursion to edit a string and eventually return its value
def output(input, output, system) do
cond do
length(input)==0 ->
output
true ->
[thing|tail]=input
if length(thing)==2 do
output=output<>"From "<>Enum.at(thing, 0)<>" to "<>Enum.at(thing,1)<>" is "<>Integer.to_string(calculate(thing, system))<>"km\n"
output(tail, output, system)
end
if length(thing)==1 do
if Enum.at(thing,0)=="Sun" do
output=output<>"Sun orbits"
output(tail, output, system)
else
output=output<>orbits(thing, system)<>" Sun"
output(tail, output, system)
end
end
output(tail, output, system)
end
end
As you can see when the input is an empty list it should return the output string. Using inspect shows that the output string does indeed have the correct value. Yet when the function is called in process(), it only returns the empty string, or nil.
Any help is appreciated, I am new to elixir so apologies if my code is a bit messy.
Solution 1:[1]
This could be a case where using pattern matching in the function head will let you avoid essentially all of the conditionals. You could break this down as:
def output([], message, _) do
message
end
def output([[from, to] | tail], message, system) do
distance = Integer.to_string(calculate(thing, system))
new_message = "#{message}From #{from} to #{to} is #{distance} km\n"
output(tail, new_message, system)
end
def output([["Sun"] | tail], message, system) do
output(tail, "Sun orbits #{message}", system)
end
def output([[thing] | tail], message, system) do
new_message = "#{message}#{orbits([thing], system)} Sun"
output(tail, new_message, system)
end
This gets around some of the difficulties highlighted in the comments: reassigning output inside a block doesn't have an effect, and there aren't non-local returns so after an if ... end block completes and goes on to the next conditional, its result is lost. This will also trap some incorrect inputs, and your process will exit with a pattern-match error if an empty or 3-element list winds up in the input list.
I've renamed the output parameter to the output function to message. This isn't required – the code will work fine whether or not you change it – but I found it a little confusing reading through the function whether output is a function call or a variable.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | David Maze |
