Lazy evaluation of expression in Elixir - clojure

I'm trying to figure out if there is a macro similar to delay in clojure to get a lazy expression/ variable that can be evaluated later.
The use case is a default value for Map.get/3, since the default value comes from a database call, I'd prefer it to be called only when it's needed.

Elixir's macro could be used for writing simple wrapper function for conditional evaluation. I've put one gist in the following, though it may be better/smarter way.
https://gist.github.com/parroty/98a68f2e8a735434bd60

"Generic" laziness is a bit of a tough nut to crack because it's a fairly broad question. Streams allow laziness for enumerables but I'm not sure what laziness for an expression would mean. For example what would a lazy form of x = 1 + 2 be? When would it be evaluated?
The thought that comes to mind for a lazy form of an expression is a procedure expression:
def x, do: 1 + 2
Because the value of x wouldn't be calculated until the expression is actually invoked (as far as I know). I'm sure others will correct me if I'm wrong on that point. But I don't think that's what you want.
Maybe you want to rephrase your question--leaving out streams and lazy evaluation of enumerated values.

One way to do this would be using processes. For example the map could be wrapped in a process like a GenServer or an Agent where the default value will be evaluated lazy.

The default value can be a function which makes the expensive call. If Map.get/3 isn't being used to return functions you can check if the value is a function and invoke it if it is returned. Like so:
def default_value()
expensive_db_call()
end
def get_something(dict, key) do
case Map.get(dict, key, default_value) do
value when is_fun(value) ->
value.() # invoke the default function and return the result of the call
value ->
value # key must have existed, return value
end
end
Of course if the map contains functions this type of solution probably won't work.
Also check Elixir's Stream module. While I don't know that it would help solve your particular problem it does allow for lazy evaluation. From the documentation:
Streams are composable, lazy enumerables. Any enumerable that generates items one by one during enumeration is called a stream. For example, Elixir’s Range is a stream:
More information is available in the Stream documentation.

Map.get_lazy and Keyword.get_lazy hold off on generating the default until needed, links the documentation below
https://hexdocs.pm/elixir/Map.html#get_lazy/3
https://hexdocs.pm/elixir/Keyword.html#get_lazy/3

You can wrap it in an anonymous function, then it will be evaluated when the function is called:
iex()> lazy = fn -> :os.list_env_vars() end
#Function<45.79398840/0 in :erl_eval.expr/5>
iex()> lazy.()

Related

Turn an IO[List[String]] in scala to a String that's comma separated

I have a IO[List[String]] (of urls string) that I'd like to convert into a comma separated String. Is there a join or something I can use? I'm getting caught up on the IO type.
You can use the map method to apply a function to the result of the IO action:
def toCommaSeparated(
io: IO[List[String]]
): IO[String] =
io.map(_.mkString(", "))
There is a way. You could use unsafeRunSync() or unsafePerformIO() once at the end to evaluate the encapsulated code.
But I advise against it, because IO's purpose is to encapsulate side-effecting code in the first place, that would otherwise make code impure, to be wrapped inside the IO and unable to evaluate unless and until we want it to do so.
In a monadic way you write code using the map and flatMap functions to compose other functions and ideally call one of these unsafe operations only once, at the end. Getting the value out of a monadic context is contrary to it's purpose in the first place, and usually hints a code smell in your design.
A more logical approach would be to use a Comonad, which has an extract method that instead takes an F[A] and extracts the A. You must be sure you can get an A from an F[A] when calling it though (e.g. you cannot get an A from a List[A] if the list is empty).

Assign variable in list

I've got a problem with Prolog lists.
Let's say I've got this predicate:
array(p, [A,B,C]).
When I do:
array(p,X).
I got: X = [_,_,_]
Now, considering I've got this predicate:
p1(1) :- array(p1, [1,B1,C1]).
I expected to get:
X = [1,_,_]
but instead, the result is the same as before. Is such a thing even possible in Prolog? Another question is if somehow we can set these values, could we overwrite these values in the same way? I understand that in the prolog variables are assigned only once but I would like to somehow get a dynamic list.
I'm not sure what you mean by "paradigm," and I'm very unclear on what you're trying to do with this code. If you have this at the toplevel:
array(p, [A,B,C]).
you are defining a fact array/2, which associates p with a list of three uninstantiated variables. Your first query amounts to retrieving this fact.
Your second "paradigm" is really the definition of a rule or predicate p1/1, which takes a single argument, which must be 1 for the rule to fire. The body of this second predicate is a call to the predicate array/2 which is definitely going to fail. I don't see how you could possibly get the same result as before, because you defined array(p, ...) before and now you are looking for array(p1, ...). Furthermore, there is no X in your second query, so there is no reason for X to appear in the result, and it definitely would not, even if you had called array(p, ...) instead of array(p1, ...).
I think what you're trying to do here is probably set up some kind of set of three variables and then unify each of them in turn as you proceed along some calculation. To do something like that is possible and easy in Prolog, but the fact database is not going to participate in this process really. You're going to have to write predicates that pass your variables along to other predicates that will unify them and return them bound. None of this is very hard, but it looks like you're going to have to go back and understand the fundamentals here a little better. You're far enough off track here that I don't think anyone can really answer your question as stated, because there's too much confusion in it.

How to detect list changes without comparing the complete list

I have a function which will fail if there has being any change on the term/list it is using since the generation of this term/list. I would like to avoid to check that each parameter still the same. So I had thought about each time I generate the term/list to perform a CRC or something similar. Before making use of it I would generate again the CRC so I can be 99,9999% sure the term/list still the same.
Going to a specfic answer, I am programming in Erlang, I am thinking on using a function of the following type:
-spec(list_crc32(List :: [term()]) -> CRC32 :: integer()).
I use term, because it is a list of terms, (erlang has already a default fast CRC libraries but for binary values). I have consider to use "erlang:crc32(term_to_binary(Term))", but not sure if there could be a better approach.
What do you think?
Regards, Borja.
Without more context it is a little bit difficult to understand why you would have this problem, particularly since Erlang terms are immutable -- once assigned no other operation can change the value of a variable, not even in the same function.
So if your question is "How do I quickly assert that true = A == A?" then consider this code:
A = generate_list()
% other things in this function happen
A = A.
The above snippet will always assert that A is still A, because it is not possible to change A like you might do in, say, Python.
If your question is "How do I assert that the value of a new list generated exactly the same value as a different known list?" then using either matching or an actual assertion is the fastest way:
start() ->
A = generate_list(),
assert_loop(A).
assert_loop(A) ->
ok = do_stuff(),
A = generate_list(),
assert_loop(A).
The assert_loop/1 function above is forcing an assertion that the output of generate_list/0 is still exactly A. There is no telling what other things in the system might be happening which may have affected the result of that function, but the line A = generate_list() will crash if the list returned is not exactly the same value as A.
In fact, there is no way to change the A in this example, no matter how many times we execute assert_loop/1 above.
Now consider a different style:
compare_loop(A) ->
ok = do_stuff(),
case A =:= generate_list() of
true -> compare_loop(A);
false -> terminate_gracefully()
end.
Here we have given ourselves the option to do something other than crash, but the effect is ultimately the same, as the =:= is not merely a test of equality, it is a match test meaning that the two do not evaluate to the same values, but that they actually match.
Consider:
1> 1 == 1.0.
true
2> 1 =:= 1.0.
false
The fastest way to compare two terms will depend partly on the sizes of the lists involved but especially on whether or not you expect the assertion to pass or fail more often.
If the check is expected to fail more often then the fastest check is to use an assertion with =, an equivalence test with == or a match test with =:= instead of using erlang:phash2/1. Why? Because these tests can return false as soon as a non-matching element is encountered -- and if this non-match occurs near the beginning of the list then a full traverse of both lists is avoided entirely.
If the check is expected to pass more often then something like erlang:phash2/1 will be faster, but only if the lists are long, because only one list will be fully traversed each iteration (the hash of the original list is already stored). It is possible, though, on a short list that a simple comparison will still be faster than computing a hash, storing it, computing another hash, and then comparing the hashes (obviously). So, as always, benchmark.
A phash2 version could look like:
start() ->
A = generate_list(),
Hash = erlang:phash2(A),
assert_loop(Hash).
assert_loop(Hash) ->
ok = do_stuff(),
Hash = erlang:phash2(generate_list()),
loop(Hash).
Again, this is an assertive loop that will crash instead of exit cleanly, so it would need to be adapted to your needs.
The basic mystery still remains, though: in a language with immutable variables why is it that you don't know whether something will have changed? This is almost certainly a symptom of an underlying architectural problem elsewhere in the program -- either that or simply a misunderstanding of immutability in Erlang.

What's the real purpose of `ignore` function in OCaml?

There is an ignore function in OCaml.
val ignore : 'a -> unit
Discard the value of its argument and return (). For instance,
ignore(f x) discards the result of the side-effecting function f. It
is equivalent to f x; (), except that the latter may generate a
compiler warning; writing ignore(f x) instead avoids the warning.
I know what this function will do, but don't get the point of using it.
Anyone can explain or give an example for when we have to use it?
You basically answered your own question. You don't ever have to use it. The point is precisely to avoid the warning. If you write f x; (), the compiler assumes you probably did something wrong. Probably you thought f x returns unit because you rarely want to ignore non-unit values.
However, sometimes that's not true, and you really want to ignore even non-unit values. Writing ignore (f x) documents the fact that you know f x returns something, but you are deliberately ignoring it.
Note that in real code f x might be something more complex, so the chances of you being wrong about the return type of f x are reasonably high. One example is partial application. Consider f : int -> int -> unit. You might accidentally write f 1, forgetting the second argument, and the warning will help you. Another example is if you do open Async, then many functions from the Standard Library change from returning unit to returning unit Deferred.t. Especially when first starting to use Async, it is quite likely that you'll accidentally think the semicolon operator is appropriate in places that you really need to use monadic bind.
As a complement to Ashish Agarwal's answer (because judging from your comment you don't seem very convinced) :
Imagine that I have a function that has side effects, and returns a value indicating something about the computation. Then, if I'm interested in how the computation went, I will need its return value. However, if I don't care about this and simply want the side effects to take place, I would use ignore.
Dumb example : let's say you have a function which sorts an array and returns Was_already_sorted or Was_not_sorted depending on the initial state of the array. Then if for some reason I'm interested in knowing how often my array was sorted, I might need the return value of this function. If not, I will ignore it.
I agree that this is a dumb example. And probably that in many cases there would be better ways to deal with the problem than using ignore (I've just noticed that I never use ignore). If you're really passionate about this, you could try to find examples of use of this function in real-life code (maybe in the source-code of software such as Unison?).
Also, note that you can use let _ = f x to the same end.

OCaml - issues connected with using fold__

I have a several questions connected with fold_left/right.
How to accumulate two or more values? If using a tuple is good solution ?
How to abort work of fold ? For example we must find firstly occurrence of any number, and return position. I mean a break (C++).
zurgl's comment is a great answer (maybe move it down to the answer region).
You can use an exception to terminate a fold early. It's good to try to structure your code so you don't have to do this (in my opinion). Code without exceptions is easier to understand, more composable, parallelizable, etc.
we must find firstly occurrence of any number then you must traverse all your list [1;1;1;1;5], no need to abort here. To deal with partial recursion there are other function like dropwhile, takewhile ... Or you can define the one you need. See folding as projection between type, you have a source type and a target type with a seed value (the accumulator), then folding is a procedure which realize this transformation. Yes using tuple is good solution, IMO.