Send an unknown method call: Difference between revisions

From Rosetta Code
Content added Content deleted
(add omit from Ada)
m (→‎{{header|Sidef}}: added another way of doing this, using Object.method())
Line 529: Line 529:
<lang ruby>class Example {
<lang ruby>class Example {
method foo(x) {
method foo(x) {
42 + x;
42 + x
}
}
}
}


var name = 'foo';
var name = 'foo'
var obj = Example();
var obj = Example()

say obj.(name)(5); # prints: 47</lang>
say obj.(name)(5) # prints: 47
say obj.method(name)(5) # =//=</lang>


=={{header|Smalltalk}}==
=={{header|Smalltalk}}==

Revision as of 10:19, 19 August 2016

Task
Send an unknown method call
You are encouraged to solve this task according to the task description, using any language you may know.

Invoke an object method where the name of the method to be invoked can be generated at run time.

Cf

AutoHotkey

This object has 3 methods, and asks the user to name one to call. Instead of using Func(), one could use a class definition. <lang AHK>obj := {mA: Func("mA"), mB: Func("mB"), mC: Func("mC")} InputBox, methodToCall, , Which method should I call? obj[methodToCall].()

mA(){

MsgBox Method A

} mB(){

MsgBox Method B

} mC(){

MsgBox Method C

} </lang>

Bracmat

<lang Bracmat>(task=

 ( oracle
 =   (predicate="is made of green cheese")
     (generateTruth=.str$(!arg " " !(its.predicate) "."))
     (generateLie=.str$(!arg " " !(its.predicate) "!"))
 )

& new$oracle:?SourceOfKnowledge & put

 $ "You may ask the Source of Eternal Wisdom ONE thing.

Enter \"Truth\" or \"Lie\" on the next line and press the <Enter> key. " & whl

 ' ( get':?trueorlie:~Truth:~Lie
   & put$"Try again\n"
   )

& put$(str$("You want a " !trueorlie ". About what?" \n)) & get'(,STR):?something & (SourceOfKnowledge..str$(generate !trueorlie))$!something ); </lang>

Example:
{?} !task
You may ask the Source of Eternal Wisdom ONE thing.
Enter "Truth" or "Lie" on the next line and press the <Enter> key.
"Lie"
You want a Lie. About what?
The sea
{!} The sea is made of green cheese!

C#

<lang csharp>using System;

class Example {

   public int foo(int x)
   {
       return 42 + x;
   }

}

class Program {

   static void Main(string[] args)
   {
       var example = new Example();
       var method = "foo";
       
       var result = (int)example.GetType().GetMethod(method).Invoke(example, new object[]{ 5 });
       Console.WriteLine("{0}(5) = {1}", method, result);
   }

} </lang>

Output:
 foo(5) = 47

Caché ObjectScript

$METHOD executes a named instance method for a specified instance of a designated class.

<lang cos>Class Unknown.Example Extends %RegisteredObject {

Method Foo() { Write "This is foo", ! }

Method Bar() { Write "This is bar", ! }

}</lang>

Examples:
USER>Set obj=##class(Unknown.Example).%New()
USER>Do $Method(obj, "Foo")
This is foo
USER>Do $Method(obj, "Bar")
This is bar

Common Lisp

Unknown methods are called just like any other function. Find the method-naming symbol using INTERN then call it with FUNCALL. <lang lisp>(funcall (intern "SOME-METHOD") my-object a few arguments)</lang>

Déjà Vu

<lang dejavu>local :object { :add @+ } local :method :add

!. object! method 1 2</lang>

Output:
3

E

This example goes well with the object named example in Respond to an unknown method call#E.

<lang e>for name in ["foo", "bar"] {

   E.call(example, name, [])

}</lang>

Elena

<lang elena>#import system.

  1. import extensions.
  1. class Example

{

   #method foo : x
       = x + 42.

}

  1. symbol program =

[

   #var example := Example new.
   #var methodSignature := "foo".
   
   #var result := example::(Signature new &literal:methodSignature) eval:5.
   
   console writeLine:methodSignature:"(":5:") = ":result.

].</lang>

Forth

Works with: Forth

Works with any ANS Forth

Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html <lang forth>include FMS-SI.f include FMS-SILib.f

var x \ instantiate a class var object named x

test
 heap> string locals| s |
 '!' s +: ':' s +:  \ build the message "!:" into string s
 42 x s @: evaluate \ retrieve the text from s and execute it 
 x p: ; \ lastly, send the p: message to x to print it

test \ => 42 ok </lang>

Go

<lang go>package main

import (

   "fmt"
   "reflect"

)

type example struct{}

// the method must be exported to be accessed through reflection. func (example) Foo() int {

   return 42

}

func main() {

   // create an object with a method
   var e example
   // get the method by name
   m := reflect.ValueOf(e).MethodByName("Foo")
   // call the method with no argments
   r := m.Call(nil)
   // interpret first return value as int
   fmt.Println(r[0].Int()) // => 42

}</lang>

Groovy

<lang grrovy>class Example {

   def foo(value) {
       "Invoked with '$value'"
   }

}

def example = new Example() def method = "foo" def arg = "test value"

assert "Invoked with 'test value'" == example."$method"(arg)</lang>

Icon and Unicon

<lang Unicon>procedure main()

  x := foo()    # create object
  x.m1()        # static call of m1 method
  #  two examples where the method string can be dynamically constructed ...
  "foo_m1"(x)   # ... need to know class name and method name to construct name
  x.__m["m1"]   # ... general method (better)

end

class foo(a,b,c) # define object method m1(x) end end</lang>

For more information on this see Respond to an unknown method call.

Io

String literal "foo" may be replaced by any expression resulting in a string. <lang Io>Example := Object clone Example foo := method(x, 42+x)

name := "foo" Example clone perform(name,5) println // prints "47"</lang>

J

Solution: There are multiple ways to evoke code at runtime. The most common is ". y (evaluate the code in the string y, producing a noun), but there's also 'name'~ (which will modify J's stack by replacing the two tokens 'name' and ~ with the named object) as well as x 128!:2 y (apply the verb described by x to the noun y).

There are other methods as well, e.g., @.,`:, and ^:, though these are designed to consume gerunds (pre-parsed ASTs) rather than strings (though, of course, a pre-processor can always be provided to convert strings into ASTs before feeding them to these operators).

Example:<lang j> sum =: +/

  prod =: */
  count =: #
  nameToDispatch =: 'sum'    NB. pick a name already defined
  ". nameToDispatch,' 1 2 3'

6

  nameToDispatch~ 1 2 3

6

  nameToDispatch (128!:2) 1 2 3

6

  nameToDispatch =: 'count'  NB. pick another name
  ". nameToDispatch,' 1 2 3'

3

  nameToDispatch~ 1 2 3

3

  nameToDispatch (128!:2) 1 2 3

3</lang>

Java

Using reflection <lang java>import java.lang.reflect.Method;

class Example {

 public int foo(int x) {
   return 42 + x;
 }

}

public class Main {

 public static void main(String[] args) throws Exception {
   Object example = new Example();
   String name = "foo";
   Class<?> clazz = example.getClass();
   Method meth = clazz.getMethod(name, int.class);
   Object result = meth.invoke(example, 5); // result is int wrapped in an object (Integer)
   System.out.println(result);        // prints "47"
 }

}</lang>

JavaScript

String literal "foo" may be replaced by any expression resulting in a string <lang javascript>example = new Object; example.foo = function(x) {

   return 42 + x;

};

name = "foo"; example[name](5) # => 47</lang>

Lasso

<lang Lasso>define mytype => type { public foo() => { return 'foo was called' } public bar() => { return 'this time is was bar' } } local(obj = mytype, methodname = tag('foo'), methodname2 = tag('bar'))

  1. obj->\#methodname->invoke
  2. obj->\#methodname2->invoke</lang>
Output:
foo was called
this time is was bar

Logtalk

For this task, we first define a simple object with a single method: <lang logtalk>:- object(foo).

:- public(bar/1). bar(42).

- end_object.</lang>Second, we define another object that asks the user for a message to be sent to the first object:<lang logtalk>
- object(query_foo).

:- public(query/0). query :- write('Message: '), read(Message), foo::Message. write('Reply: '), write(Message), nl.

- end_object.</lang>After compiling and loading both objects, we can try:
| ?- query_foo::query.
Message: bar(X).
Reply: bar(42)

Lua

Don't forget to pass the object for methods! <lang lua>local example = { } function example:foo (x) return 42 + x end

local name = "foo" example[name](example, 5) --> 47</lang>

Mathematica

Creates a dialog box where one can type a function (Sin, Cos, Tan ...) and then a second dialog box for a value. <lang>ToExpression[Input["function? E.g. Sin",]][Input["value? E.g. 0.4123"]]</lang>

Output:
Input: Sin
Input: 3.1415
Output: 0.0000926536


MATLAB / Octave

<lang Matlab>

 funName = 'foo';   % generate function name
 feval (funNAME, ...)  % evaluation function with optional parameters
 funName = 'a=atan(pi)';   % generate function name
 eval (funName, 'printf(Error\n)')

</lang>

Objective-C

<lang objc>#import <Foundation/Foundation.h>

@interface Example : NSObject - (NSNumber *)foo; @end

@implementation Example - (NSNumber *)foo {

 return @42;

} @end

int main (int argc, const char *argv[]) {

 @autoreleasepool {
   id example = [[Example alloc] init];
   SEL selector = @selector(foo); // or = NSSelectorFromString(@"foo");
   NSLog(@"%@", [example performSelector:selector]);
 
 }
 return 0;

}</lang> The performSelector: ... methods can only be used with methods with 0 - 2 object arguments, and an object or void return type. For all other calls, one can create an NSInvocation object and invoke it, or directly call one of the objc_msgSend family of runtime functions.

Oforth

A method object can be retrieved from its name using asMethod. <lang Oforth>16 "sqrt" asMethod perform</lang>

Others :

  asFuntion  : retrieve a function
  asClass    : retrieve a class
  asProperty : retrieve a property

A generic way to search a word into the dictionary in to use find method : <lang Oforth>16 "sqrt" Word find perform</lang>

PARI/GP

<lang parigp>foo()=5; eval(Str("foo","()"))</lang>

Perl

<lang perl>package Example; sub new {

   bless {}

} sub foo {

   my ($self, $x) = @_;
   return 42 + $x;

}

package main; my $name = "foo"; print Example->new->$name(5), "\n"; # prints "47"</lang>

Perl 6

Just for the fun of it, we'll mix in an anonymous role into an integer instead of defining a class. <lang perl6>my $object = 42 but role { method add-me($x) { self + $x } } my $name = 'add-me'; say $object."$name"(5); # 47</lang> The double quotes are required, by the way; without them the variable would be interpreted as a hard ref to a method.

PHP

<lang php><?php class Example {

 function foo($x) {
   return 42 + $x;
 }

}

$example = new Example();

$name = 'foo'; echo $example->$name(5), "\n"; // prints "47"

// alternately: echo call_user_func(array($example, $name), 5), "\n"; ?></lang>

PicoLisp

This can be done with the 'send' function. <lang PicoLisp>(send (expression) Obj arg1 arg2)</lang>

Pike

with [] instead of -> a string can be used to name a method: <lang Pike>string unknown = "format_nice"; object now = Calendar.now(); now[unknown]();</lang>

Python

String literal "foo" may be replaced by any expression resulting in a string <lang python>class Example(object):

    def foo(self, x):
            return 42 + x

name = "foo" getattr(Example(), name)(5) # => 47</lang>

Qi

<lang qi> (define foo -> 5)

(define execute-function

 Name -> (eval [(INTERN Name)]))

(execute-function "foo") </lang>

Racket

<lang racket>

  1. lang racket

(define greeter

 (new (class object% (super-new)
        (define/public (hello name)
          (displayln (~a "Hello " name "."))))))
normal method call

(send greeter hello "World")

sending an unknown method

(define unknown 'hello) (dynamic-send greeter unknown "World") </lang>

Ruby

You may replace :foo, :bar or "bar" with any expression that returns a Symbol or String.

<lang ruby>class Example

 def foo
   42
 end
 def bar(arg1, arg2, &block)
   block.call arg1, arg2
 end

end

symbol = :foo Example.new.send symbol # => 42 Example.new.send( :bar, 1, 2 ) { |x,y| x+y } # => 3 args = [1, 2] Example.new.send( "bar", *args ) { |x,y| x+y } # => 3</lang>

Object#send can also call protected and private methods, skipping the usual access checks. Ruby 1.9 adds Object#public_send, which only calls public methods.

Works with: Ruby version 1.9

<lang ruby>class Example

 private
 def privacy; "secret"; end
 public
 def publicity; "hi"; end

end

e = Example.new e.public_send :publicity # => "hi" e.public_send :privacy # raises NoMethodError e.send :privacy # => "secret"</lang>

Scala

Library: Scala

<lang scala>class Example {

 def foo(x: Int): Int = 42 + x

}

object Main extends App {

 val example = new Example
 val meth = example.getClass.getMethod("foo", classOf[Int])
 assert(meth.invoke(example, 5.asInstanceOf[AnyRef]) == 47.asInstanceOf[AnyRef], "Not confirm expectation.")
 println(s"Successfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart} ms]")

}</lang>

Sidef

<lang ruby>class Example {

   method foo(x) {
       42 + x
   }

}

var name = 'foo' var obj = Example()

say obj.(name)(5) # prints: 47 say obj.method(name)(5) # =//=</lang>

Smalltalk

<lang smalltalk>Object subclass: #Example.

Example extend [

 foo: x [
   ^ 42 + x ] ].

symbol := 'foo:' asSymbol. " same as symbol := #foo: "

Example new perform: symbol with: 5. " returns 47 "</lang> The perform:with:with: family of methods exist for methods with 0 - 2 (3 in GNU Smalltalk) arguments. For methods with more arguments, use perform:withArguments:, which takes an array of arguments.

Tcl

Method names are really just strings, i.e., ordinary values that can be produced by any mechanism: <lang tcl>package require Tcl 8.6 oo::class create Example {

   method foo {} {return 42}
   method 1 {s} {puts "fee$s"}
   method 2 {s} {puts "fie$s"}
   method 3 {s} {puts "foe$s"}
   method 4 {s} {puts "fum$s"}

} set eg [Example new] set mthd [format "%c%c%c" 102 111 111]; # A "foo" by any other means would smell as sweet puts [$eg $mthd] for {set i 1} {$i <= 4} {incr i} {

   $eg $i ...

}</lang>

The above produces this output:
42
fee...
fie...
foe...
fum...

zkl

<lang zkl>name:="len"; "this is a test".resolve(name)() //-->14</lang>