Why can't I call the methods method on a Perl 6's ClassHOW object? - metaclass

I can call ^methods on an object and list the method names I can call:
my $object = 'Camelia';
my #object_methods = $object.^methods;
#object_methods.map( { .gist } ).sort.join("\n").say;
^methods returns a list which I store in #object_methods, then later I transform that list of method thingys by calling gist on each one to get the human-sensible form of that method thingy.
But, the ^ in ^methods is an implied .HOW, as show at the end of the object documentation this should work too:
my $object = 'Camelia';
my #object_methods = $object.HOW.methods;
But, I get an error:
Too few positionals passed; expected 2 arguments but got 1
in any methods at gen/moar/m-Metamodel.nqp line 490
in block <unit> at...
And, for what it's worth, this is an awful error message for a language that's trying to be person-friendly about that sort of thing. The file m-Metamodel.nqp isn't part of my perl6 installation. It's not even something I can google because, as the path suggests, it's something that a compilation generates. And, that compilation depends on the version.

A regular method call via . passes the invocant as implicit first argument to the method. A meta-method call via .^ passes two arguments: the meta-object as invocant, and the instance as first positional argument.
For example
$obj.^can('sqrt')
is syntactic sugar for
$obj.HOW.can($obj, 'sqrt')
In your example, this would read
my #object_methods = $object.HOW.methods($object);

Related

Julia Error - Constructor not found when defined

Copied this into a jupyter notebook cell but can't get it to run and the message doesn't really help. Everything looks right.
mutable struct CircularArray{T} <: AbstractArray{T,1}
data::Array{T,1}
first::Int
CircularArray{T}(length::Int) where {T} = new{T}(Array{T, 1}(undef, length), 1)
end
a = CircularArray(10)
MethodError: no method matching CircularArray(::Int64)
I think the error is clear: you need to define CircularArray(length::Int). What you implemented, however, is a parametric constructor. To call your parametric constructor, you need to pass the parameter T with your constructor call, e.g.
a = CircularArray{Float64}(10);
You can also implement non-parametric constructor for a default type of your choice. For example;
CircularArray(length::Int) = CircularArray{Float64}(length)
After this your call to this constructor, CircularArray(10);, won't give a MethodError: no method matching CircularArray(::Int64).
Note the ; at the end of the commands. You need to define other methods (like size) for your array type so that display can work. Otherwise, you may get an error in REPL if you omit ; after the evaluations that return a CircularArray.

julia introspection - get name of variable passed to function

In Julia, is there any way to get the name of a passed to a function?
x = 10
function myfunc(a)
# do something here
end
assert(myfunc(x) == "x")
Do I need to use macros or is there a native method that provides introspection?
You can grab the variable name with a macro:
julia> macro mymacro(arg)
string(arg)
end
julia> #mymacro(x)
"x"
julia> #assert(#mymacro(x) == "x")
but as others have said, I'm not sure why you'd need that.
Macros operate on the AST (code tree) during compile time, and the x is passed into the macro as the Symbol :x. You can turn a Symbol into a string and vice versa. Macros replace code with code, so the #mymacro(x) is simply pulled out and replaced with string(:x).
Ok, contradicting myself: technically this is possible in a very hacky way, under one (fairly limiting) condition: the function name must have only one method signature. The idea is very similar the answers to such questions for Python. Before the demo, I must emphasize that these are internal compiler details and are subject to change. Briefly:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
Base.arg_decl_parts(fobj.env.defs)[2][1][1]
end
foo (generic function with 1 method)
julia> foo(1)
"x"
Let me re-emphasize that this is a bad idea, and should not be used for anything! (well, except for backtrace display). This is basically "stupid compiler tricks", but I'm showing it because it can be kind of educational to play with these objects, and the explanation does lead to a more useful answer to the clarifying comment by #ejang.
Explanation:
bt = backtrace() generates a ... backtrace ... from the current position. bt is an array of pointers, where each pointer is the address of a frame in the current call stack.
Profile.lookup(bt[3]) returns a LineInfo object with the function name (and several other details about each frame). Note that bt[1] and bt[2] are in the backtrace-generation function itself, so we need to go further up the stack to get the caller.
Profile.lookup(...).func returns the function name (the symbol :foo)
eval(current_module(), Profile.lookup(...)) returns the function object associated with the name :foo in the current_module(). If we modify the definition of function foo to return fobj, then note the equivalence to the foo object in the REPL:
julia> function foo(x)
bt = backtrace()
fobj = eval(current_module(), symbol(Profile.lookup(bt[3]).func))
end
foo (generic function with 1 method)
julia> foo(1) == foo
true
fobj.env.defs returns the first Method entry from the MethodTable for foo/fobj
Base.decl_arg_parts is a helper function (defined in methodshow.jl) that extracts argument information from a given Method.
the rest of the indexing drills down to the name of the argument.
Regarding the restriction that the function have only one method signature, the reason is that multiple signatures will all be listed (see defs.next) in the MethodTable. As far as I know there is no currently exposed interface to get the specific method associated with a given frame address. (as an exercise for the advanced reader: one way to do this would be to modify the address lookup functionality in jl_getFunctionInfo to also return the mangled function name, which could then be re-associated with the specific method invocation; however, I don't think we currently store a reverse mapping from mangled name -> Method).
Note also that (1) backtraces are slow (2) there is no notion of "function-local" eval in Julia, so even if one has the variable name, I believe it would be impossible to actually access the variable (and the compiler may completely elide local variables, unused or otherwise, put them in a register, etc.)
As for the IDE-style introspection use mentioned in the comments: foo.env.defs as shown above is one place to start for "object introspection". From the debugging side, Gallium.jl can inspect DWARF local variable info in a given frame. Finally, JuliaParser.jl is a pure-Julia implementation of the Julia parser that is actively used in several IDEs to introspect code blocks at a high level.
Another method is to use the function's vinfo. Here is an example:
function test(argx::Int64)
vinfo = code_lowered(test,(Int64,))
string(vinfo[1].args[1][1])
end
test (generic function with 1 method)
julia> test(10)
"argx"
The above depends on knowing the signature of the function, but this is a non-issue if it is coded within the function itself (otherwise some macro magic could be needed).

Why to pass a template parameter in Qt method

I'm trying to read some example code about implicit creation of QVariants from enum values.
About the following line of code:
QVariant::fromValue<Qt::PenStyle>(Qt::SolidLine)
I don't really understand what is the purpose of Qt::PenStyle in the above expression.
I think Qt::SolidLine is unique.
The syntax is OK?
Shouldn't it be something like:
QVariant::fromValue(Qt::SolidLine)
?
Sorry if this question seems dumb.
You can use this form:
1) QVariant::fromValue(Qt::SolidLine)
QVariant::fromValue(const T & value) is a template method. When you call a template method or function you can specify for what type of argument this method should be called. If you don't do that a compiler tries to do it for you. That is why 1) is equal to this:
2) QVariant::fromValue<Qt::PenStyle>(Qt::SolidLine)
But you can call this method for int and pass enum value (if you are not at c++11):
3) QVariant::fromValue<int>(Qt::SolidLine)
or even force creating of QPen:
4) QVariant::fromValue<QPen>(Qt::SolidLine)
EDIT:
If someone is suprised by 4 and want to know how it works: it is the same as if there was a method (actually it is created during the compilation):
QVariant::fromValue(const QPen& pen);
When you call this method with Qt::SolidLine compiler uses an implicit constructor QPen(Qt::PenStyle style) to create a new temporary QPen object and pass it as an argument to the method fromValue.

Function signature not found despite showing with methods(...)

I am new to Julia, so this might be trivial.
I have a function definition within a module that looks like (using URIParser):
function add!(graph::Graph,
subject::URI,
predicate::URI,
object::URI)
...
end
Outside of the module, I call:
add!(g, URIParser.URI("http://test.org/1"), URIParser.URI("http://test.org/2"), URIParser.URI("http://test.org/1"))
Which gives me this error:
ERROR: no method add!(Graph,URI,URI,URI)
in include at boot.jl:238
in include_from_node1 at loading.jl:114
at /Users/jbaran/src/RDF/src/RDF.jl:79
Weird. Because when I can see a matching signature:
julia> methods(RDF.add!)
# 4 methods for generic function "add!":
add!(graph::Graph,subject::URI,predicate::URI,object::Number) at /Users/jbaran/src/RDF/src/RDF.jl:29
add!(graph::Graph,subject::URI,predicate::URI,object::String) at /Users/jbaran/src/RDF/src/RDF.jl:36
add!(graph::Graph,subject::URI,predicate::URI,object::URI) at /Users/jbaran/src/RDF/src/RDF.jl:43
add!(graph::Graph,statement::Statement) at /Users/jbaran/src/RDF/src/RDF.jl:68
At first I thought it was my use of object::Union(...), but even when I define three functions with Number, String, and URI, I get this error.
Is there something obvious that I am missing? I am using Julia 0.2.1 x86_64-apple-darwin12.5.0, by the way.
Thanks,
Kim
This looks like you may be getting bit by the very slight difference between method extension and function shadowing.
Here's the short of it. When you write function add!(::Graph, ...); …; end;, Julia looks at just your local scope and sees if add! is defined. If it is, then it will extend that function with this new method signature. But if it's not already defined locally, then Julia creates a new local variable add! for that function.
As JMW's comment suggests, I bet that you have two independent add! functions. Base.add! and RDF.add!. In your RDF module, you're shadowing the definition of Base.add!. This is similar to how you can name a local variable pi = 3 without affecting the real Base.pi in other scopes. But in this case, you want to merge your methods with the Base.add! function and let multiple dispatch take care of the resolution.
There are two ways to get the method extension behavior:
Within your module RDF scope, say import Base: add!. This explicitly brings Base.add! into your local scope as add!, allowing method extension.
Explicitly define your methods as function Base.add!(graph::Graph, …). I like this form as it more explicitly documents your intentions to extend the Base function at the definition site.
This could definitely be better documented. There's a short reference to this in the Modules section, and there's currently a pull request that should be merged soon that will help.

php Strict Standards: Only variables should be passed by reference in "use"

While working i met this annoying message
Strict Standards: Only variables should be passed by reference in G:\xampp\htdocs\MyProject\ZendSkeletonApplication\module\Admission\src\Admission\Controller\AdmissionController.php on line 107
My code
$consoldatedCities='';
array_walk_recursive($StateCityHash, function($cityName,$cityId) use(&$consoldatedCities){$consoldatedCities[$cityId] = $cityName; }); // line 107
This is to convert multidimensional array into simple array
But the code works as i expected.. can anyone tell me how to solve this problem
Here http://php.net/manual/en/language.references.pass.php it says that "There is no reference sign on a function call - only on function definitions." Try removing the '&' from your function call code there and see if that gets rid of the message.
---Edit---
Looking at this thread here "Strict Standards: Only variables should be passed by reference" error
you could try saving your callback function into a variable before passing it to the array walk function:
$consoldatedCities=array();
$callbackFcn=
function($cityName,$cityId) use(&$consoldatedCities)
{
$consoldatedCities[$cityId] = $cityName;
};
array_walk_recursive($StateCityHash, $callbackFcn);

Resources