Writing the function "once" in Elixir - functional-programming

I'm coming to Elixir from primarily a Javascript background. in JS, it's possible to write a higher order function "once" which returns a function that will invoke the passed in function only once, and returns the previous result on subsequent calls- the trick is manipulating variables that were captured via closure:
var once = (func) => {
var wasCalled = false, prevResult;
return (...args) => {
if (wasCalled) return prevResult;
wasCalled = true;
return prevResult = func(...args);
}
}
It seems to me that it's not possible to create this function in Elixir, due to its different variable rebinding behavior. Is there some other clever way to do it via pattern matching or recursion, or is it just not possible? Without macros that is, I'd imagine those might enable it. Thanks

Using the current process dictionary:
defmodule A do
def once(f) do
key = make_ref()
fn ->
case Process.get(key) do
{^key, val} -> val
nil ->
val = f.()
Process.put(key, {key, val})
val
end
end
end
end
Or if the function will be passed across processes, an ets table can be used:
# ... during application initialization
:ets.new(:cache, [:set, :public, :named_table])
defmodule A do
def once(f) do
key = make_ref()
fn ->
case :ets.lookup(:cache, key) do
[{^key, val}] -> val
[] ->
val = f.()
:ets.insert(:cache, {key, val})
val
end
end
end
end
Application.put_env / Application.get_env can also be used to hold global state, though usually is used for configuration settings.

It's not considered idiomatic in most cases, but you can do this with Agent:
defmodule A do
def once(fun) do
{:ok, agent} = Agent.start_link(fn -> nil end)
fn args ->
case Agent.get(agent, & &1) do
nil ->
result = apply(fun, args)
:ok = Agent.update(agent, fn _ -> {:ok, result} end)
result
{:ok, result} ->
result
end
end
end
end
Now if you run this:
once = A.once(fn sleep ->
:timer.sleep(sleep)
1 + 1
end)
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
IO.inspect once.([1000])
You'll see that the first line is printed after 1 second, but the next 3 are printed instantly, because the result is fetched from the agent.

While both already given answers are perfectly valid, the most precise translation from your javascript is shown below:
defmodule M do
use GenServer
def start_link(_opts \\ []) do
GenServer.start_link(__MODULE__, nil, name: __MODULE__)
end
def init(_args) do
Process.sleep(1_000)
{:ok, 42}
end
def value() do
start_link()
GenServer.call(__MODULE__, :value)
end
def handle_call(:value, _from, state) do
{:reply, state, state}
end
end
(1..5) |> Enum.each(&IO.inspect(M.value(), label: to_string(&1)))
Use the same metric as in #Dogbert’s answer: the first value is printed with a delay, all subsequent are printed immediately.
This is an exact analog of your memoized function using GenServer stage. GenServer.start_link/3 returns one of the following:
{:ok, #PID<0.80.0>}
{:error, {:already_started, #PID<0.80.0>}}
That said, it is not restarted if it’s already started. I do not bother to check the returned value since we are all set in any case: if it’s the initial start, we call the heavy function, if we were already started, the vaklue is already at fingers in the state.

Related

sendMessage in functional style

Suppose I have 2 messenger objects that can send and receive messages. When message is received it is appended to some file:
class Messenger:
def sendMessage(anotherMessenger, message):
anotherMessenger.receiveMessage(message)
def receiveMessage(msg):
# appending msg to file
a = Messenger()
b = Messenger()
a.sendMessage(b, "Hello b!")
b.sendMessage(a, "Hi a!")
What would be a functional programming equivalent of the program above?
In FP your 'objects' tend to be functions. In this case, instead of multiple objects, each with two member functions you would have multiple functions to handle different scenarios.
In this case you have:
receiveMessage: string -> ()
That is, receiveMessage is a function that takes a string and returns nothing - unit. Likewise:
sendMessage: (f: string -> ()) -> (msg: string) -> ()
I.e. sendMessage takes a receiveMessage implementation and a string and returns unit.
So, using a language like F# we can have the following:
let sendMessage (f: string -> ()) (msg: string) = f(msg)
let aRecv (msg: string) = // Do something with msg
let bRecv (msg: string) = // Do something else with msg
...
sendMessage bRecv "Hello b!"
sendMessage aRecv "Hi a!"
...
Since your question is kind of generic I will leave this as a kind of generic answer. If you have something more specific in mind this answer can be expanded on.

Infinite loop with counter in elixir

I'm studying functional programming and I want to implement something like this.
while(true) do
if(somethingHappensHere) {
break
}
counter++
end
return counter
How can I do this in functional way using elixir?
Thanks for this.
While in most functional programming languages one would use a recursion for this task, Elixir particularly provides the way to do this without using an explicit recursion call: Enum.reduce_while/3:
Enum.reduce_while(1..100, 0, fn i, acc ->
if condition, do: {:halt, acc}, else: {:cont, acc + i}
end)
For lazy evaluation one would use Stream.reduce_while/3.
To make it infinite, one might use one of infinite generators, provided by Stream module, like Stream.iterate/2:
Stream.iterate(0, &(&1+1)) |> Enum.reduce_while(0, fn i, acc ->
if i > 6, do: {:halt, acc}, else: {:cont, acc + 1}
end)
#⇒ 7
For the sake of recursion, this is how the recursive solution might be implemented in Elixir:
defmodule M do
def checker, do: & &1 <= 0
def factorial(v, acc \\ 1) do
if checker().(v), do: acc, else: factorial(v - 1, v * acc)
end
end
M.factorial 6
#⇒ 720
Not sure about elixir specifically, but you can achieve this using recursion:
function myFunction(int counter)
{
if (condition) {
return counter
}
return myFunction(counter + 1)
}
This essentially sets up a function that can infinitely recurse (call itself), each time passing in the next counter value.
By having the recursive call as the last thing the function does, this is known as tail-call recursion which elixir supports (as per: Does Elixir infinite recursion ever overflow the stack?)
This can then be used as such:
int counterValue = myFunction(0)
With the function only returning once the condition is true.
You could also make this more generic by having the function take another function that returns true or false (i.e. performs the conditional check).
As I said, unfortunately I'm not aware of the syntax of elixir, but I'm sure you'll be able to bridge that gap.
An example of something in Elixir syntax:
defmodule SOQuestion do
def test(counter) do
if (something_happens_here?()), do: counter, else: test(counter+1)
end
def something_happens_here?() do
true
end
end
And it would be invoked like this:
SOQuestion.test(0)
A couple of notes on this:
1.) It's a code fragment. Obviously it's tough to be very complete given the broad nature of your question.
2.) something_happens_here? being a predicate it would normally be named ending with a question mark.
3.) If something_happens_here? were defined in a different module, then the call would be if (Module.something_happens_here?())
4.) I've obviously coded something_happens_here? to simply return true unconditionally. In real code, of course, you'd want to pass some argument to something_happens_here? and act on that to determine which boolean to return.
Given all that I totally agree with #mudasowba--this sort of thing is usually better handled with one of the higher order functions built into the language. It's less error prone and often much easier for others to read too.
As mentioned, you could use a number of built-in functions like Enum.reduce_while/3. However, sometimes it is just as easy (or fun) to use simple recursion.
Using recursion:
I will make some generic examples and use bar(foo) as an example of your somethingHappensHere condition.
1) If bar(foo) is something allowed in a guard clause:
defmodule Counter do
def count do
count(foo, 0)
end
defp count(foo, count) when bar(foo), do: count
defp count(foo, count), do: count(foo, count + 1)
end
2) If bar(foo) is a function that returns a boolean:
defmodule Counter do
def count(foo) do
count(foo, 0)
end
defp count(foo, count) do
if bar(foo) do
count
else
count(foo, count + 1)
end
end
end
3) If bar(foo) returns something other than a boolean, that you can pattern-match on, like:
defmodule Counter do
def count(foo) do
count(foo, 0)
end
defp count(foo, count) do
case bar(foo) do
{:ok, baz} -> count
{:error, _} -> count(foo, count + 1)
end
end
end
Call the module and function:
Counter.count(foo)

Recursively convert Map to Keyword List

I found a function to turn maps into keyword lists on the internet, but it is not recursive:
def to_keyword_list(dict) do
Enum.map(dict, fn({key, value}) -> {String.to_atom(key), value} end)
end
I then made this one, but it gives me an error.
def tokey(dict) do
Enum.map(dict, fn({key, value}) ->
if is_map value do
{String.to_atom(key), tokey(value)}
else
{String.to_atom(key), value}
end
end)
end
Result of the first one:
["calig├╝eva": %{speeking: "speeeeeeee"}, test: "teet", tututu: "tururuuu"]
Result of the second one:
** (ArgumentError) argument error
:erlang.binary_to_atom(:speeking, :utf8)
code.exs:10: anonymous fn/1 in Util.tokey/1
(elixir) lib/enum.ex:1233: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1263: :lists.foldl/3
(elixir) lib/enum.ex:1772: Enum.map/2
code.exs:8: anonymous fn/1 in Util.tokey/1
(elixir) lib/enum.ex:1233: anonymous fn/3 in Enum.map/2
(stdlib) lists.erl:1263: :lists.foldl/3
Is there an easier or more effective way of doing this? And why does it show that error? Can I not call a function from within itself?
Result of first one changing ü for u:
[caligueva: %{speeking: "speeeeeeee"}, test: "teet", tututu: "tururuuu"]
Second one outputs the same error. This is the map I'm using:
map = %{
"test" => "teet",
"tututu" => "tururuuu",
"caligueva" => %{"speeking": "speeeeeeee"}
}
For recursively converting Maps to Keyword Lists in Elixir:
defmodule MyMap do
def to_keyword_list(map) do
Enum.map(map, fn {k,v} ->
v = cond do
is_map(v) -> to_keyword_list(v)
true -> v
end
{String.to_atom("#{k}"), v}
end)
end
end
But as #Dogbert already mentioned, "Pure" Atoms cannot contain codepoints above 255, so your map keys should be simple Strings / Atoms:
iex(1)> MyMap.to_keyword_list(%{"caligueva" => %{speeking: "speeeeeeee"}, "test" => "teet", "tututu" => "tururuuu"})
[caligueva: [speeking: "speeeeeeee"], test: "teet", tututu: "tururuuu"]
Here is the refactored code for conversion:
def map_to_keyword_list(map), do: convert(map)
defp convert(map) when is_map(map), do: Enum.map(map, fn {k,v} ->{String.to_atom(k),convert(v)} end)
defp convert(v), do: v

How to pack / unpack a hex string (high nibble first) with Elixir

I was wondering how I would work with hex strings in Elixir. Specifically, I'm interested in converting from Hex to ASCII.
In Ruby, an implementation of this may be:
["001C7F616A8B002128C1A33E8100"].pack('H*').gsub(/[^[:print:]]/, '.')
How would I accomplish this task with Elixir? I have tried:
<<00, 01, C7, F6...>>
but this isn't a correct representation of the hex for a string. Thanks for your time and assistance!
So I've made some progress but am currently struggling with the recursion aspect of this.
This is my solution thus far:
defmodule ElixirNetworkTools do
def decode(payload) do
upper_payload = String.upcase payload
case Base.decode16(upper_payload) do
:error -> decode_with_nonprintable_characters(payload)
{:ok, decoded_payload} -> decoded_payload
end
|> IO.write
end
def decode_with_nonprintable_characters(payload) do
String.chunk(payload, ~r/\w{2}/)
|> Enum.each(fn(byte) ->
case Base.decode16(byte) do
:error -> '.'
{:ok, decoded_payload} -> decoded_payload
end
end)
end
end
Here is another solution to the problem. A couple things before we start:
You can pass case: :mixed to Base.decode16/2: Base.decode16(string, case: :mixed), for this reason, you don't need do upcase before.
If you are going to raise on an invalid string, don't bother checking, just call decode16 directly as it also checks the size.
This means we can start with:
decoded = Base.decode16!(string, case: :mixed)
Now you need to replace non-printable characters. Don't use String.printable?/1 because it is about UTF-8 and not ASCII. We need to implement our own function but what makes more sense: to raise or replace them? It seems it must be considered an error if someone send invalidate data? If that is the case:
def validate_ascii!(<<h, t::binary>>) when h <= 127 do
validate_ascii!(t)
end
def validate_ascii!(<<>>) do
true
end
def validate_ascii!(rest) do
raise "invalid ascii on string starting at: #{rest}"
end
Alternatively you can just remove the last clause and it fail too.
Now we can put it together:
decoded = Base.decode16!(string, case: :mixed)
validate_ascii!(decoded)
decoded
EDIT: If you need to replace non-ascii by dots:
def keep_ascii(<<h, t::binary>>, acc) when h <= 127 do
keep_ascii(t, acc <> <<h>>)
end
def keep_ascii(<<_, t::binary>>, acc) do
keep_ascii(t, acc <> ".")
end
def keep_ascii(<<>>, acc) do
acc
end
The solution ended up being as follows, though if there is a cleaner or better solution I would be very interested in knowing it.
defmodule ElixirNetworkTools do
#doc """
The decode function takes a hexadecimal payload, such as one generated
by Snort, and returns the ASCII representation of the string.
## Example
iex> ElixirNetworkTools.decode("436F6E74656E742D4C656E6774683A203132")
{:ok, "Content-Length: 12"}
"""
def decode(payload) do
case _validate_length_of_snort(payload) do
:error -> raise "Invalid length hex string. Must be even length. Exiting"
_ -> nil
end
decoded = String.upcase(payload)
|> _do_decode
|> to_string
{:ok, decoded}
end
#doc """
Internal function used to manually process the hexadecimal payload,
and builds a char list of the printable characters. If a character is
not printable, we instead use periods.
## Example
iex> ElixirNetworkTools._do_decode("436F6E74656E742D4C656E6774683A203132")
["Content-Length: 12"]
"""
def _do_decode(payload) do
Base.decode16!(payload)
|> String.chunk(:printable)
|> Enum.map(fn(chunk) ->
case String.printable? chunk do
true -> chunk
_ -> "."
end
end)
end
#doc """
Internal function used to validate the length of the hexadecimal payload.
Hexadecimal strings should have an even number of characters.
## Example
iex> ElixirNetworkTools._validate_length_of_snort("436F6E74656E742D4C656E6774683A203132")
:ok
"""
def _validate_length_of_snort(payload) do
String.length(payload)
|> rem(2)
|> case do
0 -> :ok
_ -> :error
end
end
end

Monadic Retry logic w/ F# and async?

I've found this snippet:
http://fssnip.net/8o
But I'm working not only with retriable functions, but also with asynchronous such, and I was wondering how I make this type properly. I have a tiny piece of retryAsync monad that I'd like to use as a replacement for async computations, but that contains retry logic, and I'm wondering how I combine them?
type AsyncRetryBuilder(retries) =
member x.Return a = a // Enable 'return'
member x.ReturnFrom a = x.Run a
member x.Delay f = f // Gets wrapped body and returns it (as it is)
// so that the body is passed to 'Run'
member x.Bind expr f = async {
let! tmp = expr
return tmp
}
member x.Zero = failwith "Zero"
member x.Run (f : unit -> Async<_>) : _ =
let rec loop = function
| 0, Some(ex) -> raise ex
| n, _ ->
try
async { let! v = f()
return v }
with ex -> loop (n-1, Some(ex))
loop(retries, None)
let asyncRetry = AsyncRetryBuilder(4)
Consuming code is like this:
module Queue =
let desc (nm : NamespaceManager) name = asyncRetry {
let! exists = Async.FromBeginEnd(name, nm.BeginQueueExists, nm.EndQueueExists)
let beginCreate = nm.BeginCreateQueue : string * AsyncCallback * obj -> IAsyncResult
return! if exists then Async.FromBeginEnd(name, nm.BeginGetQueue, nm.EndGetQueue)
else Async.FromBeginEnd(name, beginCreate, nm.EndCreateQueue)
}
let recv (client : MessageReceiver) timeout =
let bRecv = client.BeginReceive : TimeSpan * AsyncCallback * obj -> IAsyncResult
asyncRetry {
let! res = Async.FromBeginEnd(timeout, bRecv, client.EndReceive)
return res }
Error is:
This expression was expected to have type Async<'a> but here has type 'b -> Async<'c>
Your Bind operation behaves like a normal Bind operation of async, so your code is mostly a re-implementation (or wrapper) over async. However, your Return does not have the right type (it should be 'T -> Async<'T>) and your Delay is also different than normal Delay of async. In general, you should start with Bind and Return - using Run is a bit tricky, because Run is used to wrap the entire foo { .. } block and so it does not give you the usual nice composability.
The F# specification and a free chapter 12 from Real-World Functional Programming both show the usual types that you should follow when implementing these operations, so I won't repeat that here.
The main issue with your approach is that you're trying to retry the computation only in Run, but the retry builder that you're referring to attempts to retry each individual operation called using let!. Your approach may be sufficient, but if that's the case, you can just implement a function that tries to run normal Async<'T> and retries:
let RetryRun count (work:Async<'T>) = async {
try
// Try to run the work
return! work
with e ->
// Retry if the count is larger than 0, otherwise fail
if count > 0 then return! RetryRun (count - 1) work
else return raise e }
If you actually want to implement a computation builder that will implicitly try to retry every single asynchronous operation, then you can write something like the following (it is just a sketch, but it should point you in the right direction):
// We're working with normal Async<'T> and
// attempt to retry it until it succeeds, so
// the computation has type Async<'T>
type RetryAsyncBuilder() =
member x.ReturnFrom(comp) = comp // Just return the computation
member x.Return(v) = async { return v } // Return value inside async
member x.Delay(f) = async { return! f() } // Wrap function inside async
member x.Bind(work, f) =
async {
try
// Try to call the input workflow
let! v = work
// If it succeeds, try to do the rest of the work
return! f v
with e ->
// In case of exception, call Bind to try again
return! x.Bind(work, f) }

Resources