caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* invoke function from its name as string
@ 2008-03-13  4:07 Ludovic Coquelle
  2008-03-13  5:04 ` Ludovic Coquelle
  2008-03-13  9:44 ` Berke Durak
  0 siblings, 2 replies; 8+ messages in thread
From: Ludovic Coquelle @ 2008-03-13  4:07 UTC (permalink / raw)
  To: caml-list

First, hello everyone as it is my first message to this list ;)

I'm trying to solve this problem:
I have a module name and function name in string variables,
and I would like to call this function, like :
let mod = "MyMod" in
let fn = "my_fun" in
what_come_here mod fn

Can this problem be solved?
Was thinking that camlp4 could help ... not sure as it change the
syntax tree but I don't see how to get access to module name 'mod'.

Any pointer are greatly appreciated :)
thanks


^ permalink raw reply	[flat|nested] 8+ messages in thread

* invoke function from its name as string
  2008-03-13  4:07 invoke function from its name as string Ludovic Coquelle
@ 2008-03-13  5:04 ` Ludovic Coquelle
  2008-03-13  6:49   ` [Caml-list] " Andrej Bauer
  2008-03-13  9:44 ` Berke Durak
  1 sibling, 1 reply; 8+ messages in thread
From: Ludovic Coquelle @ 2008-03-13  5:04 UTC (permalink / raw)
  To: caml-list

(re-send as it seems it didn't go through)

First, hello everyone as it is my first message to this list ;)

 I'm trying to solve this problem:
 I have a module name and function name in string variables,
 and I would like to call this function, like :
 let mod = "MyMod" in
 let fn = "my_fun" in
 what_come_here mod fn

 Can this problem be solved?
 Was thinking that camlp4 could help ... not sure as it change the
 syntax tree but I don't see how to get access to module name 'mod'.

 Any pointer are greatly appreciated :)
 thanks


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13  5:04 ` Ludovic Coquelle
@ 2008-03-13  6:49   ` Andrej Bauer
  2008-03-13  7:10     ` Ludovic Coquelle
  0 siblings, 1 reply; 8+ messages in thread
From: Andrej Bauer @ 2008-03-13  6:49 UTC (permalink / raw)
  To: caml-list; +Cc: lcoquelle

Ludovic Coquelle wrote:
> (re-send as it seems it didn't go through)

It did.

> First, hello everyone as it is my first message to this list ;)
> 
>  I'm trying to solve this problem:
>  I have a module name and function name in string variables,
>  and I would like to call this function, like :
>  let mod = "MyMod" in
>  let fn = "my_fun" in
>  what_come_here mod fn
> 
>  Can this problem be solved?

If you are new to ocaml then we can help you much better if you explain
what problem you are trying to solve. It looks like you are trying to
write in Ocaml something that is common in Python/perl/shell. There is
likely to be a different, better way of doing the same thing in Ocaml.

Best regards,

Andrej


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13  6:49   ` [Caml-list] " Andrej Bauer
@ 2008-03-13  7:10     ` Ludovic Coquelle
  2008-03-13 16:41       ` Andrej Bauer
  0 siblings, 1 reply; 8+ messages in thread
From: Ludovic Coquelle @ 2008-03-13  7:10 UTC (permalink / raw)
  To: Andrej.Bauer; +Cc: caml-list

On Thu, Mar 13, 2008 at 2:49 PM, Andrej Bauer
<Andrej.Bauer@fmf.uni-lj.si> wrote:
> Ludovic Coquelle wrote:
>  > (re-send as it seems it didn't go through)
>
>  It did.

Sorry for the double post (gmail probably filtered the mail I sent to list).

>  > First, hello everyone as it is my first message to this list ;)
>  >
>  >  I'm trying to solve this problem:
>  >  I have a module name and function name in string variables,
>  >  and I would like to call this function, like :
>  >  let mod = "MyMod" in
>  >  let fn = "my_fun" in
>  >  what_come_here mod fn
>  >
>  >  Can this problem be solved?
>
>  If you are new to ocaml then we can help you much better if you explain
>  what problem you are trying to solve. It looks like you are trying to
>  write in Ocaml something that is common in Python/perl/shell. There is
>  likely to be a different, better way of doing the same thing in Ocaml.
>
>  Best regards,
>
>  Andrej
>

Thanks for this answer.
Problem I'm trying to solve is the following:

I use 'make_suite' which is a program that do regex matching on source
code to extract a list of function that looks like OUnit tests; from
this list, it write an ocaml source code file which is a test case
that call all the previous functions found.
(see: http://skydeck.com/blog/programming/unit-test-in-ocaml-with-ounit/)

Now, instead of having a program which write a source file that I have
to compile and run, I would prefer if I can change 'make_suite' to
create the test case and run it directly.

Thus, I have a list of function's names as string and I would like a
list of functions.
Is this possible?
Is there a better way to achieve automatic test case construction?

PS: this is not a *real problem* to use an intermediate file; just
wanna learn if we can do without :)


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13  4:07 invoke function from its name as string Ludovic Coquelle
  2008-03-13  5:04 ` Ludovic Coquelle
@ 2008-03-13  9:44 ` Berke Durak
  1 sibling, 0 replies; 8+ messages in thread
From: Berke Durak @ 2008-03-13  9:44 UTC (permalink / raw)
  To: Ludovic Coquelle, Caml-list List

Ludovic Coquelle a écrit :
> First, hello everyone as it is my first message to this list ;)
> 
> I'm trying to solve this problem:
> I have a module name and function name in string variables,
> and I would like to call this function, like :
> let mod = "MyMod" in
> let fn = "my_fun" in
> what_come_here mod fn
> 
> Can this problem be solved?

There is a Turkish saying stating that "There is a solution to every
problem in a democracy"!

So here you go.

Note that since you're asking for a hackish operation, I felt authorized
to use a hackish solution, using Dynlink.

File alpha.ml:

let f () = Printf.printf "Alpha.f\n%!"

--

File foo.ml:

module A = Alpha

let _ = Dynlink.init ()

let call md fn =
   let oc = open_out "x.ml" in
   Printf.fprintf oc "let _ = %s.%s ()\n" md fn;
   close_out oc;
   if Sys.command "ocamlbuild x.byte" <> 0 then failwith "Duh";
   try
     Dynlink.add_interfaces ["alpha"] ["_build"];
     Dynlink.loadfile "_build/x.cmo"
   with
   | Dynlink.Error e ->
     Printf.printf "Too bad: %s\n%!" (Dynlink.error_message e)

let _ =
   call Sys.argv.(1) Sys.argv.(2)

--

% ocamlbuild.native -tags use_dynlink foo.byte
% ./foo.byte Alpha f
Alpha.f

-- 
Berke DURAK


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13  7:10     ` Ludovic Coquelle
@ 2008-03-13 16:41       ` Andrej Bauer
  2008-03-13 17:03         ` Andrew Gacek
  0 siblings, 1 reply; 8+ messages in thread
From: Andrej Bauer @ 2008-03-13 16:41 UTC (permalink / raw)
  To: Ludovic Coquelle, Caml

Ludovic Coquelle wrote:
> Thanks for this answer.
> Problem I'm trying to solve is the following:
> 
> I use 'make_suite' which is a program that do regex matching on source
> code to extract a list of function that looks like OUnit tests; from
> this list, it write an ocaml source code file which is a test case
> that call all the previous functions found.
> (see: http://skydeck.com/blog/programming/unit-test-in-ocaml-with-ounit/)

I looked at the blog post. The idea is to interleave the source code 
with special test functions and extract those automatically. You have 
chosen to do this by searching the source code with regular expressions, 
looking for functions with a certain name. If I may be honest and will 
all due respect: this is a really horrible idea. It is fragile, 
sensitive to mistakes, you have no guarantee that all the test functions 
were actually found (say what if someone mispells the name of one of 
them slightly), and so on. It is just really bad.

How about the following solution, in which I naively assume that test 
functions are supposed to return bool, but this is easily fixed. Define 
a module "Test" somewhat like this:

---test.ml----
(** The list of tests registered by the source code. *)
let tests = ref []

(** Register a function as a test. *)
let register name test =
   tests := (name, test) :: !tests

(** Run all tests, maybe we can combine this with OUnit? *)
let run_tests () =
   List.iter
     (fun (name,test) ->
        if not (test ()) then failwith ("FAILED: " ^ name))
     !tests
-------------

In your source code, whenever you want to have a test you just write:

Test.register "some_name" (fun () ->
   (*test code here*)
*)

This is essentially the same overhead as what you have in your current 
solution, except that it is robust, ocaml will check that it is ok, and 
you do not have to come up with names of test functions of the form 
test_... all the time. The names of tests are strings, they can be more 
descriptive.

To run your program, you do not do anything special. There will be a 
small initialization cost when the test functions are collected in the list.

Tu run the tests, you link your source code with something like

---runtest.ml---

Test.run_tests ()

---------------

You can easily extend this idea to using OUnit inside test.ml or do 
whatever you like. The important thing is that you do not search the 
source code in a naive and fragile way that requires to programmer to 
follow arbitrary naming conventions.

Best regards,

Andrej


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13 16:41       ` Andrej Bauer
@ 2008-03-13 17:03         ` Andrew Gacek
  2008-03-14  0:53           ` Ludovic Coquelle
  0 siblings, 1 reply; 8+ messages in thread
From: Andrew Gacek @ 2008-03-13 17:03 UTC (permalink / raw)
  To: Andrej.Bauer; +Cc: Ludovic Coquelle, Caml

Andrej's solution is interesting since it lets you interleave the
regular code with the test code. For my own code, I keep all tests
isolated to separate files and in each file I maintain the tests as a
list of anonymous functions. As a made-up example I might have

let list_tests =
  "List" >::: [
    "Empty list has length zero" >::
      (fun () ->
         assert_equal 0 (List.length [])) ;

    "Empty list appended to empty list is empty list" >::
      (fun () ->
         assert_equal [] ([] @ [])) ;

    ...

  ]

This structure makes it very easy to add new tests and does not
require me to come up with
convoluted_test_function_names_with_undersctores. The downside is that
tests end up being indented so much.

-Andrew

On Thu, Mar 13, 2008 at 11:41 AM, Andrej Bauer
<Andrej.Bauer@fmf.uni-lj.si> wrote:
> Ludovic Coquelle wrote:
>  > Thanks for this answer.
>  > Problem I'm trying to solve is the following:
>  >
>  > I use 'make_suite' which is a program that do regex matching on source
>  > code to extract a list of function that looks like OUnit tests; from
>  > this list, it write an ocaml source code file which is a test case
>  > that call all the previous functions found.
>  > (see: http://skydeck.com/blog/programming/unit-test-in-ocaml-with-ounit/)
>
>  I looked at the blog post. The idea is to interleave the source code
>  with special test functions and extract those automatically. You have
>  chosen to do this by searching the source code with regular expressions,
>  looking for functions with a certain name. If I may be honest and will
>  all due respect: this is a really horrible idea. It is fragile,
>  sensitive to mistakes, you have no guarantee that all the test functions
>  were actually found (say what if someone mispells the name of one of
>  them slightly), and so on. It is just really bad.
>
>  How about the following solution, in which I naively assume that test
>  functions are supposed to return bool, but this is easily fixed. Define
>  a module "Test" somewhat like this:
>
>  ---test.ml----
>  (** The list of tests registered by the source code. *)
>  let tests = ref []
>
>  (** Register a function as a test. *)
>  let register name test =
>    tests := (name, test) :: !tests
>
>  (** Run all tests, maybe we can combine this with OUnit? *)
>  let run_tests () =
>    List.iter
>      (fun (name,test) ->
>         if not (test ()) then failwith ("FAILED: " ^ name))
>      !tests
>  -------------
>
>  In your source code, whenever you want to have a test you just write:
>
>  Test.register "some_name" (fun () ->
>    (*test code here*)
>  *)
>
>  This is essentially the same overhead as what you have in your current
>  solution, except that it is robust, ocaml will check that it is ok, and
>  you do not have to come up with names of test functions of the form
>  test_... all the time. The names of tests are strings, they can be more
>  descriptive.
>
>  To run your program, you do not do anything special. There will be a
>  small initialization cost when the test functions are collected in the list.
>
>  Tu run the tests, you link your source code with something like
>
>  ---runtest.ml---
>
>  Test.run_tests ()
>
>  ---------------
>
>  You can easily extend this idea to using OUnit inside test.ml or do
>  whatever you like. The important thing is that you do not search the
>  source code in a naive and fragile way that requires to programmer to
>  follow arbitrary naming conventions.
>
>  Best regards,
>
>  Andrej
>
>
>
>  _______________________________________________
>  Caml-list mailing list. Subscription management:
>  http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
>  Archives: http://caml.inria.fr
>  Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>  Bug reports: http://caml.inria.fr/bin/caml-bugs
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] invoke function from its name as string
  2008-03-13 17:03         ` Andrew Gacek
@ 2008-03-14  0:53           ` Ludovic Coquelle
  0 siblings, 0 replies; 8+ messages in thread
From: Ludovic Coquelle @ 2008-03-14  0:53 UTC (permalink / raw)
  To: Andrew Gacek; +Cc: Andrej.Bauer, Caml

I like the "global test registry" of Andrej and will give it a try
(adapted to OUnit).
Thanks for all the advices!

On Fri, Mar 14, 2008 at 1:03 AM, Andrew Gacek <andrew.gacek@gmail.com> wrote:
> Andrej's solution is interesting since it lets you interleave the
>  regular code with the test code. For my own code, I keep all tests
>  isolated to separate files and in each file I maintain the tests as a
>  list of anonymous functions. As a made-up example I might have
>
>  let list_tests =
>   "List" >::: [
>     "Empty list has length zero" >::
>       (fun () ->
>          assert_equal 0 (List.length [])) ;
>
>     "Empty list appended to empty list is empty list" >::
>       (fun () ->
>          assert_equal [] ([] @ [])) ;
>
>     ...
>
>   ]
>
>  This structure makes it very easy to add new tests and does not
>  require me to come up with
>  convoluted_test_function_names_with_undersctores. The downside is that
>  tests end up being indented so much.
>
>  -Andrew
>
>  On Thu, Mar 13, 2008 at 11:41 AM, Andrej Bauer
>
> <Andrej.Bauer@fmf.uni-lj.si> wrote:
>
>
> > Ludovic Coquelle wrote:
>  >  > Thanks for this answer.
>  >  > Problem I'm trying to solve is the following:
>  >  >
>  >  > I use 'make_suite' which is a program that do regex matching on source
>  >  > code to extract a list of function that looks like OUnit tests; from
>  >  > this list, it write an ocaml source code file which is a test case
>  >  > that call all the previous functions found.
>  >  > (see: http://skydeck.com/blog/programming/unit-test-in-ocaml-with-ounit/)
>  >
>  >  I looked at the blog post. The idea is to interleave the source code
>  >  with special test functions and extract those automatically. You have
>  >  chosen to do this by searching the source code with regular expressions,
>  >  looking for functions with a certain name. If I may be honest and will
>  >  all due respect: this is a really horrible idea. It is fragile,
>  >  sensitive to mistakes, you have no guarantee that all the test functions
>  >  were actually found (say what if someone mispells the name of one of
>  >  them slightly), and so on. It is just really bad.
>  >
>  >  How about the following solution, in which I naively assume that test
>  >  functions are supposed to return bool, but this is easily fixed. Define
>  >  a module "Test" somewhat like this:
>  >
>  >  ---test.ml----
>  >  (** The list of tests registered by the source code. *)
>  >  let tests = ref []
>  >
>  >  (** Register a function as a test. *)
>  >  let register name test =
>  >    tests := (name, test) :: !tests
>  >
>  >  (** Run all tests, maybe we can combine this with OUnit? *)
>  >  let run_tests () =
>  >    List.iter
>  >      (fun (name,test) ->
>  >         if not (test ()) then failwith ("FAILED: " ^ name))
>  >      !tests
>  >  -------------
>  >
>  >  In your source code, whenever you want to have a test you just write:
>  >
>  >  Test.register "some_name" (fun () ->
>  >    (*test code here*)
>  >  *)
>  >
>  >  This is essentially the same overhead as what you have in your current
>  >  solution, except that it is robust, ocaml will check that it is ok, and
>  >  you do not have to come up with names of test functions of the form
>  >  test_... all the time. The names of tests are strings, they can be more
>  >  descriptive.
>  >
>  >  To run your program, you do not do anything special. There will be a
>  >  small initialization cost when the test functions are collected in the list.
>  >
>  >  Tu run the tests, you link your source code with something like
>  >
>  >  ---runtest.ml---
>  >
>  >  Test.run_tests ()
>  >
>  >  ---------------
>  >
>  >  You can easily extend this idea to using OUnit inside test.ml or do
>  >  whatever you like. The important thing is that you do not search the
>  >  source code in a naive and fragile way that requires to programmer to
>  >  follow arbitrary naming conventions.
>  >
>  >  Best regards,
>  >
>  >  Andrej
>  >
>  >
>  >
>  >  _______________________________________________
>  >  Caml-list mailing list. Subscription management:
>  >  http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
>  >  Archives: http://caml.inria.fr
>  >  Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
>  >  Bug reports: http://caml.inria.fr/bin/caml-bugs
>  >
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2008-03-14  0:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-03-13  4:07 invoke function from its name as string Ludovic Coquelle
2008-03-13  5:04 ` Ludovic Coquelle
2008-03-13  6:49   ` [Caml-list] " Andrej Bauer
2008-03-13  7:10     ` Ludovic Coquelle
2008-03-13 16:41       ` Andrej Bauer
2008-03-13 17:03         ` Andrew Gacek
2008-03-14  0:53           ` Ludovic Coquelle
2008-03-13  9:44 ` Berke Durak

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).