How can I get the methods defined in a module? - f#-interactive

I'm trying to consume an F# assembly from Fsi, but can't seem to find a way to get a list of methods defined in a module so I can call them.
Here's a sample file I'm trying to do this with. In following the "exposing methods that are cross language friendly", I've added a namespace to the top of the file and added a module to contain the let bound methods that were there previously. I'd like to avoid moving everything into static classes if possible.
Can I use reflection, or write the module in another way that helps me find the available methods and proper casing of the methods?

If I correctly understood the problem, I would proceed as follows:
1) Get the desired assembly. For example, the assembly that is currently being executed can be obtained by
System.Reflection.Assembly.GetExecutingAssembly
2) Then I would take all the types defined in the obtained assembly by calling GetTypes. If you want to filter out modules you could write something like.
let modules = Array.filter (fun x -> FSharpType.IsModule x) (assembly.GetTypes())
The documentation for the FSharpType class can be found here. It is included in the Microsoft.FSharp.Reflection namespace.
3) After, you can obtain the methods in a module by calling GetMethods method on a single module. For example, to print them all, you could write something like:
let methods = [| for t in modules do for m in t.GetMethods() -> m |]
for m in methods do
printfn "%A" m
methods is an array containing MethodInfo elements. GetMethods takes an optional parameter of type BindingFlags that can filter out some methods. Take a look at the documentation.
You can also invoke actions by calling the Invoke method on a MethodInfo object.
Hope this was useful.

Related

Rust - Can I make this diesel dsl::find() function more generic?

I have a function that uses diesel to get an object from a DB based off the given ID:
fn get_db_site(pool: web::Data<Pool>, site_id: u32) -> Result<Site, diesel::result::Error> {
let conn = pool.get().unwrap();
dsl::site.find(site_id).get_result::<Site>(&conn)
}
This function is going to be exactly the same for every table I want to run it on so I'm hoping to put it in it's own utils file so I don't have to type the same thing in every time. The only problem is in order to call that find I need to do
crate::schema::site::dsl::site.find and I'm not sure how I can make that call generic to take any type. I know there are type arguments but I don't think that would work here
I normally advise against making diesel things more generic as this leads to really complex trait bounds quite fast. You normally never want to do this in application code. (It's a different thing for libraries that need to be generic). I normally compare the situation with plain SQL. For example if someone complains that users::table.find(pk) feels like duplication, ask yourself the following question: Would you feel that SELECT … FROM users is duplicated in the corresponding query SELECT … FROM users WHERE id = $. (The diesel dsl statement is basically the same).
So to answer your actual question, the generic functions needs to look something like this:
(Not sure if I got all bounds right without testing)
fn get_db_thing<T, U, PK>(pool: web::Data<Pool>, primary_key: PK) -> Result<U, diesel::result::Error>
where T: Table + HasTable<Table = T>,
T: FindDsl<PK>,
U: Queryable<SqlTypeOf<Find<T, PK>>, Pg>
{
let conn = pool.get().unwrap();
T::table().find(primary_key).get_result::<U>(&conn)
}
As you can see the list of trait bounds is already much longer than just having the load inline in the corresponding functions. In addition all the details added while constructing the query would now be required as generic function argument. At least the type for T cannot be inferred by the compiler, so from a code size point of view this solution is not "simpler" than just not making it generic.

Is it possible to extend a class by using a string as a module ? - Ruby 2.7.1

I am doing some tests with Ruby 2.7.1 on FreeBSD 12.1. I know how to extend a class with module with for instance this :
class Myclass
def mymethod
extend Mymodule
end
end
But is it possible to obtain the same result with something that looks like this :
class Myclass
def mymethod
var = "Mymodule"
extend var
end
end
If I do this like that, I off-course obtain an error, since extend is pointing to a string and not a module.
Here are some explanations - it would be useful in the following application for instance :
Imagine you have a folder with a lots of ruby scripts, all of them are module with obvious name. For instance abcd.rb will contain the module Abcd. So I create a file list and save it in an array. Then I can load or require all these file listed in this array. Since the name of modules are predictable, I just have to do some .sub, .chop and .capitalize method to the indices of my array in order to obtain a viable result that looks just like the name of a module.
The idea would be to create a mean of extending my main class with all these modules automatically. In this idea, any modules added to the folder will be automatically loaded and ready for use.
But since the result of my array operations are not "pure" modules names but String I got stuck right here.
So, is there any way to achieve this (maybe I use a wrong path to do so) or is not possible ?
Thanks in advance !
You can't extend "arbitrary string", but you can convert that to a module first:
class Myclass
def mymethod
var = "Mymodule"
extend self.class.const_get(var)
end
end
Where const_get can easily resolve simple module names like X and X::Y.
There's also the constantize method in ActiveSupport, bundled with Rails, which does something similar:
extend var.constantize

How can I make functions available to ClojureScript's eval?

In this blog post by Dmitri Sotnikov a function eval-str is provided for running a string containing ClojureScript:
(defn eval-str [s]
(eval (empty-state)
(read-string s)
{:eval js-eval
:source-map true
:context :expr}
(fn [result] result)))
If I have some function x that I want to be able to call from inside the eval string, how can I do that?
There are two parts to the answer, assuming x is a var associated with a ClojureScript function:
The compiler analysis metadata for x needs to be present in the state passed as the first argument to cljs.js/eval. This is so that, during compilation, things like the arity of x is known, for example.
The JavaScript implementation of the function associated with x needs to be present in the JavaScript runtime. (This is especially true if the function is actually called during the cljs.js/eval call, and not just referenced.)
If x is a core function (say the var #'cljs.core/map for example), then both of these conditions is automatically satisfied. In particular, the metadata will be produced when cljs.js/empty-state is called (assuming :dump-core is true), and the implementation of the core functions will have already been loaded into the JavaScript runtime.
But, let's say x is a wholly new function that you wish to have compiled in the self-hosted environment. The “trick” is to set up and reuse compiler state: For example put the result of (cljs.js.empty-state) into a var, and pass it to every cljs.js/eval call. If you do that, and one of the cljs.js/eval calls involves compiling a defn for x, then the compiler state will be modified (it is actually an atom), with the result being that the compiler metadata for x will be put in the state, along with, of course, the JavaScript implementation for x being set within the JavaScript environment (by virtue of evaluating the JavaScript produced for the defn).
If, on the other hand, x is a function that is part of your “ambient” ClojureScript environment (say, pre-compiled via the JVM ClojureScript compiler, but nevertheless available in the JavaScript runtime), then it will be up to you to somehow to arrange to get the compiler analysis metadata for x into the state passed to cljs.js/eval. If you look at the output of the JVM-based compiler, you will see <ns-name>.cache.json files containing such metadata. Take a look at the data that is in these files and you can ascertain its structure; with that you can see how to swap the needed information into the compiler state under [:cljs.analyzer/namespaces <ns-name>]. The cljs.js/load-analysis-cache! function exists as a helper for this use case, and a self-contained example is at https://stackoverflow.com/a/51575204/4284484

InvalidOperationException in Fsharp.Core.dll

So I am doing a simple personal project in winforms with F#. My code used to work, but now throws this exception for seemingly no reason.
An unhandled exception of type 'System.InvalidOperationException' occurred in FSharp.Core.dll
Additional information: The initialization of an object or value resulted in an object or value being accessed recursively before it was fully initialized.
The code is a member method that is being invoked from the constructor of the form itself
do
//lots of other constructor code before this point
// render the form
form.ResumeLayout(false)
form.PerformLayout()
form.ReloadGoals
//several other members before here
member form.ReloadGoals =
let x = 10 //crashes on this line
The website where I grabbed the template for the project I am using is this one.
Unfortunately I have made some substantial additions to this.
I would be glad to post more code, but I need to know what code would be relevant exactly, as I am not exactly sure and don't want to bog down the post in extraneous code.
Also I can't really find a lot of documentation on System.InvalidOperationException.
Every time I find it, it is being used as an example of an exception you can throw on your own, not what causes it.
See The F# 3.0 Language Specification (final version, PDF), §8.6.1 Primary Constructors in Classes:
During construction, no member on the type may be called before the last value or function definition in the type
has completed; such a call results in an InvalidOperationException.
Almost certainly, your code in the question doesn't tell the full story. If you hit the above
mentioned restriction, then there's somewhere an attempt to access a field or member not fully initialized.
Some example:
type X() as this =
let x = this.X
member __.X = 42
X()
One workaround might be to encapsulate the offending code in a member of its own and call that in the constructor instead. Another would be the wrapping in a function definition.
This will be an incomplete answer, since I cannot reproduce the problem (using F# interactive, the given example, the ReloadGoals modification, and Form.Show, the code runs fine). However, there are strange things happening:
Taken from the template, there should be a handler method for the Form.Load event, which fires when the type is fully constructed. Why is additional loading code in the constructor instead of this event handler? Load exists precisely to counter this kind of problem with unorderly initialization.
The template you are using isn't exactly sane F#. For example, initControls is a value of type unit that is evaluated where it is defined; its binding to a name is absolutely useless and should be replaced with a simple do. Writing initControls in the do block later has no effect at all. form.ResumeLayout(false); form.PerformLayout() should be equivalent to form.ResumeLayout(true), but I don't understand what these are doing in the constructor in the first place. The event handlers have two possibly unnecessary indirections: one to a delegate constructor, another to a method that has no real reason to exist -- the handlers should be lambdas or simple, private functions. Why are they public members?!
The error appearing in the question is probably caused by the usage of form in its own constructor. Move your new usage to the Load event handler, and it should work.
Personally, I would go further and ditch implementation inheritance by instantiating a plain Form and subscribing to its events. For example, in FSI, something similar to the template could be done like this:
open System.Drawing
open System.Windows.Forms
let form = new Form()
form.ClientSize <- new Size(600, 600)
form.Text <- "F# Form"
let formLabel = new Label()
formLabel.Text <- "Doubleclick test!"
formLabel.DoubleClick.Add <| fun _ -> form.Close()
form.Controls.Add(formLabel)
form.Show()
which uses no inheritance at all. (In an application, you'd use Application.Run etc instead of form.Show().) This does not run into initialization problems as easily and, additionally, is very useful if you want to encapsulate the form inside a simpler type or even just a function.

Ruby C Extension using Singleton

I only wanted to allow one instance of my C extension class to be made, so I wanted to include the singleton module.
void Init_mousetest() {
VALUE mouseclass = rb_define_class("MyMouse",rb_cObject);
rb_require("singleton");
VALUE singletonmodule = rb_const_get(rb_cObject,rb_intern("Singleton"));
rb_include_module(mouseclass,singletonmodule);
rb_funcall(singletonmodule,rb_intern("included"),1,mouseclass);
### ^ Why do I need this line here?
rb_define_method(mouseclass,"run",method_run,0);
rb_define_method(mouseclass,"spawn",method_spawn,0);
rb_define_method(mouseclass,"stop",method_stop,0);
}
As I understand it, what that line does is the same as Singleton.included(MyMouse), but if I try to invoke that, I get
irb(main):006:0> Singleton.included(MyMouse)
NoMethodError: private method `included' called for Singleton:Module
from (irb):6
from C:/Ruby19/bin/irb:12:in `<main>'
Why does rb_include_module behave differently than I would expect it to? Also any tangential discussions/explanations or related articles are appreciated. Ruby beginner here.
Also it seems like I could have just kept my extension as simple as possible and just hack some kind of interface later on to ensure I only allow one instance. Or just put my mouse related methods into a module... Any of that make sense?
according to http://www.groupsrv.com/computers/about105620.html the rb_include_module() is actually just Module#append_features.
Apparently Module#include calls Module#append_features and Module#included. So in our C code we must also call included. Since clearly something important happens there.

Resources