Jump to content

Send an unknown method call

From Rosetta Code
Revision as of 04:06, 2 November 2011 by rosettacode>Kernigh ({{header|Smalltalk}}: Add local link.)
Send an unknown method call is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

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>

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>

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>

Objective-C

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

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

@implementation Example - (NSNumber *)foo {

 return [NSNumber numberWithInt:42];

} @end

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

 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
 id example = [[Example alloc] init];
 SEL selector = @selector(foo); // or = NSSelectorFromString(@"foo");
 NSLog(@"%@", [example performSelector:selector withObject:nil]);
 [example release];
 
 [pool release];
 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.

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>

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>

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>

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...
Cookies help us deliver our services. By using our services, you agree to our use of cookies.