Elixir: generating catch-all function calls - macros

I have a macro that puts catch-all functions in the end of the module, so resulting module looks something like:
defmodule Module1 do
<module body>
## Generated catch-all functions
def fun1(_, _), do: :ok
## ..more catch-all functions...##
end ## of module
The problem I'm trying to solve is to suppress warnings
"this clause cannot match because a previous clause at line XX always matches" in case the user of macro will have, for instance
def fun1(arg1, arg2), do: ...
in the body of the module.
I guess I can go through module's body AST and do some analysis of function signatures before generating catch-all functions, but it seems to be a lot of work. Is there any other way?

(I think you know this solution but maybe it could be useful to other SO users to answer this question :) )
As José have said, it's not a very good practice to hide too much in the code as it can lead to surprises (hidden code can do something you do not expect t to do) and can even limit you (in this particular case, if you have un-explicit catchall, you can't get rid of it...).
I thing the best approach is to explicitly use a macro to generate all the boilerplate code. One line to call the macro is not as much boilerplate ;)
Example implementation:
https://gist.github.com/mprymek/73f878e103f60d6d89e2

Related

How can I allow the caller to call method of field of case class?

I am not sure the keywords for this pattern, sorry if the question is not clear.
If you have:
case class MyFancyWrapper(
somethingElse: Any,
heavyComplexObject: CrazyThing
)
val w = MyFancyWrapper(???, complexThing)
I want to be able to call w.method with the method coming from complexThing. I tried to extends CrazyThing but it is a trait and I don't want to implement all the method that would be very tedious. I also don't want to have to do:
def method1 = heavyComplexObject.method1
...
for all of them.
Any solution ?
Thanks.
You can do this with macros but I agree with Luis that this is an overkill. Macros are intended to repetitive boring things, not one time boring things. Also this is not as trivial as it sounds, because you probably don't want to pass through all the methods (you probably still want your own hashCode and equals). Finally macros have bad IDE support so most probably no auto-completion for all those methods. On the other hand if you do use a good IDE (like IDEA) there is most probably an action like "Delegate methods" that will generate most of the code for you. You still will have to change the return type from Unit to MyFancyWrapper and add returning this at the end of each method but this can easily be done with mass replace operations (hint: replace "}" with "this }" and the automatically re-formatting code should do the trick)
Here are some screenshots of the process from JetBrains IDEA:
You can use an implicit conversion to make all the methods of heavyComplexThing directly available on MyFancyWrapper:
implicit def toHeavy(fancy: MyFancyWrapper): CrazyThing = fancy.heavyComplexObject
This needs to be in scope when the method is called.
In the comments you indicate that you want to return this so that you can chain multiple calls on the same object:
w.method1.method2.method3
Don't do this
While this is a common pattern in non-functional languages, it is bad practice is Scala for two reasons:
This pattern inherently relies on side-effects, which is the antithesis of functional programming.
It is confusing, because in Scala chaining calls in this way is used to implement a data pipeline, where the output of one function is passed as the input to the next.
It is much clearer to write separate statements so that it is obvious that the methods are being called on the same object:
w.method1()
w.method2()
w.method3()
(It is also conventional to use () when calling methods with side effects)

Using module annotations as method attributes

So here's an interesting question, what I look at the documentation for module attributes in elixir i.e. http://elixir-lang.org/getting-started/module-attributes.html at the bottom it mentions that they can be used as method annotations as in ExUnit.
Unfortunately there is basically no information on how to achieve this and looking through ExUnit code has just got me lost. It seems like I would need to determine the closest method to the attribute to say that they are associated in some way (could be wrong though).
Any idea where I might look to learn about this?
It works like this. Look at source code of ExUnit.Case.
At first, look into __using__ macro, since it will be invoked first when you use it in a test case. Particularly, note here
Enum.each [:ex_unit_tests, :tag, :describetag, :moduletag, :ex_unit_registered],
&Module.register_attribute(__MODULE__, &1, accumulate: true)
This registers #tag and a bunch of more attributes as accumulated. Read the docs of Module.register_attribute/3, and you will see it means anytime attribute is invoked, the value gets appended to a list of previous attributes.
Then note test/3 macro, particularly here
quote bind_quoted: [var: var, contents: contents, message: message] do
name = ExUnit.Case.register_test(__ENV__, :test, message, [])
def unquote(name)(unquote(var)), do: unquote(contents)
end
Note the call to ExUnit.Case.register_test/4. Looking at it, specially here
tag = Module.delete_attribute(mod, :tag)
It fetches the tags until here, and deletes them. And by having the tags, and the name of test, it invokes (here)
test = %ExUnit.Test{name: name, case: mod, tags: tags}
Module.put_attribute(mod, :ex_unit_tests, test)
which saves the test along with tags inside another attributes.
And at last, note here
#doc false
defmacro __before_compile__(_) do
quote do
def __ex_unit__(:case) do
%ExUnit.TestCase{name: __MODULE__, tests: #ex_unit_tests}
end
end
end
The function __ex_unit__/1 is called in ExUnit.Runner.run_case/3 to get information of tests inside each case.
You see the point? Use an accumulated attribute, inside your macro call a function that always gets current value of the attribute and clears it, then do anything you want with the value, because you know it is always for when the macro is called.
I hope it was clear enough, drop a comment if you need more explanation.
PS. I just read the source code to find this out. It was exciting to know how it works.

When to use macros functions in Erlang?

I'm currently following the book Learn You Some Erlang for Great Good by Fred Herbert and one of the sections is regarding Macros.
I understand using macros for variables (constant values, mainly), however, I don't understand the use case for macros as functions. For example, Herbert writes:
Defining a "function" macro is similar. Here's a simple macro used to subtract one number from another:
-define(sub(X, Y), X-Y).
Why not just define this as a function elsewhere? Why use a macro? Is there some sort of performance advantage from the compiler or is this merely just a "this function is so simple, let's just define it in one line" type of thing?
I'm not trying to start a debate or preference argument, but after seeing some production Erlang code, I've started noticing lots of macros function usage.
In this case, the one obvious advantage of the macro not being a function (-define(sub(X, Y), X-Y), which would be safer as -define(sub(X, Y), (X-Y))) is that it can be used as a guard since custom function calls are forbidden.
In many cases it would otherwise be safer to define the function as an inlined one.
On the other hand, there are other interesting cases, such as assertions in tests or shortcuts where what you want is to keep some local context in the final place.
For example, let's say I want to make a generic call for a test where the objective is 'match a given pattern and return a given value, or fail after M milliseconds'.
I cannot make this generic with code since patterns are not data structures you are allowed to carry around. However, with macros:
-define(wait_for(PAT, Timeout),
receive
PAT -> VAL
after Timeout ->
error(timeout)
end).
This macro can then be used as:
my_test() ->
Pid = start_whatever(),
%% ...
?wait_for({'EXIT', Pid, Reason}, 5000),
?assertMatch(shutdown, Reason).
By doing this, I'm able to simplify the form of text in some tests without needing a bunch of nesting, and in a way that is not possible with functions.
Do note that the assertion itself as defined by eunit is using a function macro, and does something akin to
-define(assertMatch(PAT, TERM),
%% funs to avoid leaking bindings into parent scope
(fun() ->
try
PAT = TERM,
true
catch _:_ ->
error({assertion_failed, ?LINE, ...})
end
end)()).
This similarly lets you carry patterns and bindings and do fancy forms that couldn't be possible otherwise.
In this last case, you'll notice I used the ?LINE macro. That's another advantage of macros: you preserve information and locality about the call site, such as its module name, line number, and so on. This is useful when such metadata is required, such as when you're reporting test failures.
If you're looking at old code, there might be macros used as a way of inlining small functions under the assumption that function calls are very expensive. I'm not sure if that was ever true, but it's not something you need to worry about today.
Macros can be used to define constants, like
-define(MAX_TIMEOUT, 30 * 1000).
%% ...
gen_server:call(my_server, {do_stuff, Data}, ?MAX_TIMEOUT),
%% ...
I mostly prefer to pass in environment variables for this job, but it's more work to read them on startup and stash them somewhere and write accessors.
Finally, you can do some simple metaprogramming:
-define(MAKE_REQUEST_FUN(Method),
Method(Request, HTTPOptions, Options) ->
httpc:request(Method, Request, HTTPOptions, Options)).
?MAKE_REQUEST_FUN(get).
?MAKE_REQUEST_FUN(put).
%% Now we've defined a get/3 that can be called as
%% get(Request, [], []).

Term expansion for a list of terms

Say I want to have a number of rules that all follow the same pattern. I have ran into this situation when I want to avoid non-deterministic behavior by explicitly listing all possible first arguments. I know, however, that I need to do exactly the same for some of the possibilities. One way to deal with it would be to have a catch-all clause at the end:
foo(a) :- /* do something */.
foo(b) :- /* do something else*/.
foo(_). /* ignore the rest */
but this is not very nice because I can't actually know if got unexpected input, or if I made a mistake in my program. To avoid this, I could also say
foo(X) :- memberchk(X, [ /* list of possible values of X */ ]).
but again, I am now fighting against Prolog's deterministic behavior and indexing when the argument is ground.
So, instead, I do something like this:
term_expansion(foos(Foos), Foo_rules) :-
maplist(expand_foo, Foos, Foo_rules).
expand_foo(Foo, foo(Foo)).
other_foos([x,y,z]).
The thing is, I sort of tried to find existing code like this and I couldn't. Is it because I am doing something wrong? Is there a better way to approach this problem? Or circumvent it altogether?
I don't mind answers that say "you are solving the wrong problem".
EDIT: Some googling actually got me to this very similar example from the SWI-Prolog documentation:
http://www.swi-prolog.org/pldoc/man?section=ext-dquotes-motivation
(at the very bottom)
First a few comments on the variants you already suggest:
foo(a) :- /* do something */.
foo(b) :- /* do something else */.
foo(_). /* ignore the rest */
The main problem with this is that the final clause (foo(_)) applies when the other - presumably more specialized - clauses also apply. So the query ?- foo(a). is now unintentionally non-deterministic.
You say this version "is not very nice because I can't actually know if got unexpected input, or if I made a mistake in my program". We could guard against unexpected input by making sure, in the check-all clause, that the given term is not unexpected:
foo(a) :- /* do something */.
foo(b) :- /* do something else */.
foo(X) :- must_be(oneof([a,b,x,y], X).
This raises an error when the term is of an unexpected form. I used x and y as examples for terms that are not handled specially. Note that a and b must of course be included, because the clause (again) applies to both of them as well. The predicate is still not deterministic even when its argument is instantiated, because first argument indexing cannot distinguish the cases. You write "I am now fighting against Prolog's deterministic behavior and indexing when the argument is ground" and probably (and correctly) mean that you cannot benefit from these features when you use this representation.
And now the nice declarative solution: Every time you are tempted to introduce a "catch-all" or "default" clause, reconsider your data representation, and introduce distinguishing functors for the different cases that can apply. In your example, the two cases are:
the term needs to be handled in a special way
nothing special needs to be done with the term.
I will use special(_) and ordinary(_) to distinguish the cases. Thus:
foo(special(S)) :- foo_special(S).
foo(ordinary(_)). % do nothing
foo_special(a) :- /* do something */
foo_special(b) :- /* do something else */
These predicates can be used in all directions, and are deterministic when the argument is known. Type-checks can be added easily.

Is it possible to achieve functionality provided by implicit classes via macros?

We are pretty familiar with implicits in Scala for now, but macros are pretty undiscovered area (at least for me) and, despite the presence of some great articles by Eugene Burmako, it is still not an easy material to just dive in.
In this particular question I'd like to find out if there is a possibility to achieve the analogous to the following code functionality using just macros:
implicit class Nonsense(val s: String) {
def ##(i:Int) = s.charAt(i)
}
So "asd" ## 0 will return 'a', for example. Can I implement macros that use infix notation? The reason to this is I'm writing a DSL for some already existing project and implicits allow making the API clear and concise, but whenever I write a new implicit class, I feel like introducing a new speed-reducing factor. And yes, I do know about value classes and stuff, I just think it would be really great if my DSL transformed into the underlying library API calls during compilation rather than in runtime.
TL;DR: can I replace implicits with macros while not changing the API? Can I write macros in infix form? Is there something even more suitable for this case? Is the trouble worth it?
UPD. To those advocating the value classes: in my case I have a little more than just a simple wrapper - they are often stacked. For example, I have an implicit class that takes some parameters, returns a lambda wrapping this parameters (i.e. partial function), and the second implicit class that is made specifically for wrapping this type of functions. I can achieve something like this:
a --> x ==> b
where first class wraps a and adds --> method, and the second one wraps the return type of a --> x and defines ==>(b). Plus it may really be the case when user creates considerable amount of objects in this fashion. I just don't know if this will be efficient, so if you could tell me that value classes cover this case - I'd be really glad to know that.
Back in the day (2.10.0-RC1) I had trouble using implicit classes for macros (sorry, I don't recollect why exactly) but the solution was to use:
an implicit def macro to convert to a class
define the infix operator as a def macro in that class
So something like the following might work for you:
implicit def toNonsense(s:String): Nonsense = macro ...
...
class Nonsense(...){
...
def ##(...):... = macro ...
...
}
That was pretty painful to implement. That being said, macro have become easier to implement since.
If you want to check what I did, because I'm not sure that applies to what you want to do, refer to this excerpt of my code (non-idiomatic style).
I won't address the relevance of that here, as it's been commented by others.