How to define a function based on a previously defined function on a module? - metaprogramming

I'm trying to define a function based on a already defined function on a module.
I want to do something like this:
defmodule A do
def my_func(pid, arg1, arg2) do
send pid, "Do Something"
end
end
And after my_func is defined, I would like to define my_func(arg1, arg2) that calls my_func passing a pid that I'll get from a pool of pids for example.
My first attempt was using #on_definition but I had no success. Then I tried doing this inside the module:
Enum.each Module.definitions_in(__MODULE__, :def), fn {func_name, arity} ->
args = Enum.map(0..arity-1, fn i -> "arg_#{i}" end)
quoted = quote do
def unquote(func_name)(unquote_splicing(args)) do
....
But still I'm not having success. Anyone have any idea on how do I get this? :)

You can accomplish this like so:
defmodule Test do
def my_func(pid, arg1, arg2) do
send pid, {arg1, arg2}
end
quoted = Enum.map Module.definitions_in(__MODULE__, :def), fn {func_name, _arity} ->
quote do
def unquote(func_name)(arg1, arg2) do
pid = :some_pid
unquote(func_name)(pid, arg1, arg2)
end
end
end
Module.eval_quoted(__MODULE__, quoted)
Enum.each Module.definitions_in(__MODULE__, :def), fn {func_name, arity} ->
IO.inspect {func_name, arity}
end
end
If you compile this with elixirc test.ex, you'll see it spit out the definitions for my_func/2 and my_func/3. The problem with your initial code was that while you were mapping over and quoting the definitions, you never evaluated those quoted expressions, so they were not compiled as part of your module.

Actually, the solution by bitwalker can be simplified. You don't need to quote and do eval_quoted, since def is a macro that injects directly into AST. So this will work as well:
defmodule Test do
def my_func(pid, arg1, arg2) do
send pid, {arg1, arg2}
end
Enum.map Module.definitions_in(__MODULE__, :def), fn {func_name, _arity} ->
def unquote(func_name)(arg1, arg2) do
pid = :some_pid
unquote(func_name)(pid, arg1, arg2)
end
end
Enum.each Module.definitions_in(__MODULE__, :def), fn {func_name, arity} ->
IO.inspect {func_name, arity}
end
end

Related

How to call a Groovy Closure with an Object Array

I may be misunderstanding how to use varargs, but according to the Groovy Docs for Closures, for the function public V call(Object... args) , the arguments parameter "could be a single value or a List of values".
But when I try to do something like this:
Closure myClosure = { arg1, arg2, arg3 ->
println arg1 == null
println arg2 == null
println arg3 == null
}
Object[] argsArray = new Object[]{"John", "Jack", "Mack"}
myClosure.call(argsArray)
The compiler throws an groovy.lang.MissingMethodException: No signature of method: .call() is applicable for argument types: ([Ljava.lang.Object;)
I couldn't even get the varargs function to work when passing in an actual varargs either.
def myVarargsFunction(Object... args){
println "myVarargsFunction"
myClosure.call(args)
}
This code results in the same error (After I change the scope of Closure myClosure of course).
I don't under stand why either or these situations do not work. I know there are other ways to get this to work, I just want to understand why this doesn't work.
You can use the spread operator:
myClosure.call(*args)

Can I access a struct by name, eg A = field1, get struct.A?

Here's a psuedocode implementation of what I would be looking for within Julia:
struct Example
field1::Float64
field2::Float64
end # End struct
example = Example(1., 2.)
function modifystruct(mystruct, fieldname)
mystruct.fieldname +=10
return mystruct
end
modifystruct(example, field1)
# In this instance I would want to have example.field1 = 11.
How would I actually do this? I want to provide the fieldname as something like a string, and have my struct."whateverfieldname" get modified as such. I should add that I do NOT want to code something in like this:
function modifystruct(mystruct, fieldname)
if fieldname = "fieldname1"
mystruct.field1 +=10
end
if fieldname = "fieldname2"
mystruct.field2 +=10
end
return mystruct
end
Largely due to how versatile I want this code to be. I may be using different types of structs for my program, so the closest I can get to directly accessing by the name of the field, the better. Is there any method or implementation that can do this for me?
Sure, that's setproperty!(value, name, x) and getproperty(value, name):
function modifystruct(mystruct, fieldname)
new_field = getproperty(mystruct, fieldname) + 10
setproperty!(mystruct, fieldname, new_field)
return mystruct
end
As DecowVR rightly notes, this requires mystruct to be mutable.
If you want to do this repeatedly and with nested properties, you might be interested in lenses such as those provided by Setfield.jl.
Firstly, whould be noticed that in order to be able to modify an struct, it needs to be mutable:
julia> mutable struct Example
field1::Float64
field2::Float64
end
julia> example = Example(1., 2.)
Example(1.0, 2.0)
And now, a simple aproach would be to use Julia Symbols. A symbol is nothing else but an expression like :var. Can be used as shown:
julia> example.:field1
1.0
However, if we create a variable that stores the symbol, it won't work:
julia> v = :field1
:field1
julia> example.v
ERROR: type Example has no field v
Stacktrace:
[1] getproperty(x::Example, f::Symbol)
# Base ./Base.jl:42
[2] top-level scope
# REPL[18]:1
This is due to the order in which the Julia Interpreter works. If we want to evaluate firstly the variable, and then the expression, it is as easy as:
julia> #eval example.$v
1.0
So the complete function would be as follows:
julia> function modify_struct(mystruct::Example, fieldname::Symbol)
#eval $mystruct.$fieldname += 10
end

Does passing self in a nested function make sense?

class Example:
def outerExample(self, s):
def innerExample(self, s):
print("hello " + s)
innerExample(s)
a = Example()
a.outerExample("world")
When I use self as a parameter in the method outerFunction, I know that it is considered the instance outerFunction is called on. But does it make any sense when I use self in the nested innerFunction. Does Python consider the latter as just another argument?

How do nested expressions work in groovy?

Right now I'm doing this:
// Returns a string that needs to be manipulated
def str = callSomeFunc arg1:'sdfsdf', arg2:'blah', arg3:'sdfs'
str = str.trim()
Because this doesn't work:
def str = (callSomeFunc arg1:'sdfsdf', arg2:'blah', arg3:'sdfs').trim()
Have a look at the docs:
In some cases parentheses are required, such as when making nested
method calls or when calling a method without parameters.
In your case this will work also:
def str = callSomeFunc(arg1:'sdfsdf', arg2:'blah', arg3:'sdfs').trim()

How to overload Lua string subscript operator?

This:
debug.getmetatable("").__index = function (s, i) return s:sub(i, i) end
and this:
debug.getmetatable("").__index = _proc_lua_read
does not work.
Try
debug.getmetatable("").__index = function (s, i) return string.sub(s,i,i) end
Note that by redefining __index for strings in that way, you lose the ability to call methods on strings: note how the code does not call s:sub. For a better solution that avoids that, see http://lua-users.org/lists/lua-l/2007-11/msg00619.html . Or set __call instead:
getmetatable("").__call = string.sub

Resources