Send an unknown method call: Difference between revisions
(→{{header|Picat}}: code tag for functions) |
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
||
Line 12: | Line 12: | ||
=={{header|AutoHotkey}}== |
=={{header|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. |
This object has 3 methods, and asks the user to name one to call. Instead of using Func(), one could use a class definition. |
||
< |
<syntaxhighlight lang="ahk">obj := {mA: Func("mA"), mB: Func("mB"), mC: Func("mC")} |
||
InputBox, methodToCall, , Which method should I call? |
InputBox, methodToCall, , Which method should I call? |
||
obj[methodToCall].() |
obj[methodToCall].() |
||
Line 25: | Line 25: | ||
MsgBox Method C |
MsgBox Method C |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Bracmat}}== |
=={{header|Bracmat}}== |
||
< |
<syntaxhighlight lang="bracmat">(task= |
||
( oracle |
( oracle |
||
= (predicate="is made of green cheese") |
= (predicate="is made of green cheese") |
||
Line 47: | Line 47: | ||
& (SourceOfKnowledge..str$(generate !trueorlie))$!something |
& (SourceOfKnowledge..str$(generate !trueorlie))$!something |
||
); |
); |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out|Example}} |
{{out|Example}} |
||
<pre>{?} !task |
<pre>{?} !task |
||
Line 58: | Line 58: | ||
=={{header|C sharp|C#}}== |
=={{header|C sharp|C#}}== |
||
< |
<syntaxhighlight lang="csharp">using System; |
||
class Example |
class Example |
||
Line 79: | Line 79: | ||
} |
} |
||
} |
} |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{out}} |
{{out}} |
||
foo(5) = 47 |
foo(5) = 47 |
||
Line 87: | Line 87: | ||
$METHOD executes a named instance method for a specified instance of a designated class. |
$METHOD executes a named instance method for a specified instance of a designated class. |
||
< |
<syntaxhighlight lang="cos">Class Unknown.Example Extends %RegisteredObject |
||
{ |
{ |
||
Line 100: | Line 100: | ||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
{{out|Examples}} |
{{out|Examples}} |
||
<pre> |
<pre> |
||
Line 112: | Line 112: | ||
=={{header|Clojure}}== |
=={{header|Clojure}}== |
||
< |
<syntaxhighlight lang="clojure"> |
||
(import '[java.util Date]) |
(import '[java.util Date]) |
||
(import '[clojure.lang Reflector]) |
(import '[clojure.lang Reflector]) |
||
Line 132: | Line 132: | ||
;; then we run the code using eval |
;; then we run the code using eval |
||
(eval `(. date1 ~(symbol method) date2)) |
(eval `(. date1 ~(symbol method) date2)) |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Common Lisp}}== |
=={{header|Common Lisp}}== |
||
Unknown methods are called just like any other function. Find the method-naming symbol using INTERN then call it with FUNCALL. |
Unknown methods are called just like any other function. Find the method-naming symbol using INTERN then call it with FUNCALL. |
||
< |
<syntaxhighlight lang="lisp">(funcall (intern "SOME-METHOD") my-object a few arguments)</syntaxhighlight> |
||
=={{header|Déjà Vu}}== |
=={{header|Déjà Vu}}== |
||
< |
<syntaxhighlight lang="dejavu">local :object { :add @+ } |
||
local :method :add |
local :method :add |
||
!. object! method 1 2</ |
!. object! method 1 2</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>3</pre> |
<pre>3</pre> |
||
Line 150: | Line 150: | ||
This example goes well with the object named <code>example</code> in [[Respond to an unknown method call#E]]. |
This example goes well with the object named <code>example</code> in [[Respond to an unknown method call#E]]. |
||
< |
<syntaxhighlight lang="e">for name in ["foo", "bar"] { |
||
E.call(example, name, []) |
E.call(example, name, []) |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Elena}}== |
=={{header|Elena}}== |
||
ELENA 4.1 : |
ELENA 4.1 : |
||
< |
<syntaxhighlight lang="elena">import extensions; |
||
class Example |
class Example |
||
Line 173: | Line 173: | ||
console.printLine(methodSignature,"(",5,") = ",result) |
console.printLine(methodSignature,"(",5,") = ",result) |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
Line 181: | Line 181: | ||
=={{header|Factor}}== |
=={{header|Factor}}== |
||
Factor's object model is such that objects themselves don't contain methods — generic words do. So there is nothing different about invoking an unknown method than invoking an unknown word in general. |
Factor's object model is such that objects themselves don't contain methods — generic words do. So there is nothing different about invoking an unknown method than invoking an unknown word in general. |
||
< |
<syntaxhighlight lang="factor">USING: accessors kernel math prettyprint sequences words ; |
||
IN: rosetta-code.unknown-method-call |
IN: rosetta-code.unknown-method-call |
||
Line 193: | Line 193: | ||
! must specify vocab to look up a word |
! must specify vocab to look up a word |
||
"rosetta-code.unknown-method-call" |
"rosetta-code.unknown-method-call" |
||
lookup-word execute . ! 47</ |
lookup-word execute . ! 47</syntaxhighlight> |
||
=={{header|Forth}}== |
=={{header|Forth}}== |
||
Line 201: | Line 201: | ||
Needs the FMS-SI (single inheritance) library code located here: |
Needs the FMS-SI (single inheritance) library code located here: |
||
http://soton.mpeforth.com/flag/fms/index.html |
http://soton.mpeforth.com/flag/fms/index.html |
||
< |
<syntaxhighlight lang="forth">include FMS-SI.f |
||
include FMS-SILib.f |
include FMS-SILib.f |
||
Line 212: | Line 212: | ||
x p: 42 \ send the print message ( p: ) to x to verify the contents |
x p: 42 \ send the print message ( p: ) to x to verify the contents |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Go}}== |
=={{header|Go}}== |
||
< |
<syntaxhighlight lang="go">package main |
||
import ( |
import ( |
||
Line 238: | Line 238: | ||
// interpret first return value as int |
// interpret first return value as int |
||
fmt.Println(r[0].Int()) // => 42 |
fmt.Println(r[0].Int()) // => 42 |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Groovy}}== |
=={{header|Groovy}}== |
||
< |
<syntaxhighlight lang="grrovy">class Example { |
||
def foo(value) { |
def foo(value) { |
||
"Invoked with '$value'" |
"Invoked with '$value'" |
||
Line 251: | Line 251: | ||
def arg = "test value" |
def arg = "test value" |
||
assert "Invoked with 'test value'" == example."$method"(arg)</ |
assert "Invoked with 'test value'" == example."$method"(arg)</syntaxhighlight> |
||
==Icon and {{header|Unicon}}== |
==Icon and {{header|Unicon}}== |
||
< |
<syntaxhighlight lang="unicon">procedure main() |
||
x := foo() # create object |
x := foo() # create object |
||
x.m1() # static call of m1 method |
x.m1() # static call of m1 method |
||
Line 265: | Line 265: | ||
method m1(x) |
method m1(x) |
||
end |
end |
||
end</ |
end</syntaxhighlight> |
||
For more information on this see [[Respond_to_an_unknown_method_call#Icon_and_Unicon|Respond to an unknown method call]]. |
For more information on this see [[Respond_to_an_unknown_method_call#Icon_and_Unicon|Respond to an unknown method call]]. |
||
Line 271: | Line 271: | ||
=={{header|Io}}== |
=={{header|Io}}== |
||
String literal "foo" may be replaced by any expression resulting in a string. |
String literal "foo" may be replaced by any expression resulting in a string. |
||
< |
<syntaxhighlight lang="io">Example := Object clone |
||
Example foo := method(x, 42+x) |
Example foo := method(x, 42+x) |
||
name := "foo" |
name := "foo" |
||
Example clone perform(name,5) println // prints "47"</ |
Example clone perform(name,5) println // prints "47"</syntaxhighlight> |
||
=={{header|J}}== |
=={{header|J}}== |
||
Line 283: | Line 283: | ||
There are other methods as well, e.g., '''<tt>@.</tt>''','''<tt>`:</tt>''', and '''<tt>^:</tt>''', 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). |
There are other methods as well, e.g., '''<tt>@.</tt>''','''<tt>`:</tt>''', and '''<tt>^:</tt>''', 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''':< |
'''Example''':<syntaxhighlight lang="j"> sum =: +/ |
||
prod =: */ |
prod =: */ |
||
count =: # |
count =: # |
||
Line 303: | Line 303: | ||
3 |
3 |
||
nameToDispatch (128!:2) 1 2 3 |
nameToDispatch (128!:2) 1 2 3 |
||
3</ |
3</syntaxhighlight> |
||
=={{header|Java}}== |
=={{header|Java}}== |
||
Using reflection |
Using reflection |
||
< |
<syntaxhighlight lang="java">import java.lang.reflect.Method; |
||
class Example { |
class Example { |
||
Line 324: | Line 324: | ||
System.out.println(result); // prints "47" |
System.out.println(result); // prints "47" |
||
} |
} |
||
}</ |
}</syntaxhighlight> |
||
=={{header|JavaScript}}== |
=={{header|JavaScript}}== |
||
String literal "foo" may be replaced by any expression resulting in a string |
String literal "foo" may be replaced by any expression resulting in a string |
||
< |
<syntaxhighlight lang="javascript">example = new Object; |
||
example.foo = function(x) { |
example.foo = function(x) { |
||
return 42 + x; |
return 42 + x; |
||
Line 334: | Line 334: | ||
name = "foo"; |
name = "foo"; |
||
example[name](5) # => 47</ |
example[name](5) # => 47</syntaxhighlight> |
||
=={{header|Julia}}== |
=={{header|Julia}}== |
||
{{works with|Julia|0.6}} |
{{works with|Julia|0.6}} |
||
< |
<syntaxhighlight lang="julia">const functions = Dict{String,Function}( |
||
"foo" => x -> 42 + x, |
"foo" => x -> 42 + x, |
||
"bar" => x -> 42 * x) |
"bar" => x -> 42 * x) |
||
@show functions["foo"](3) |
@show functions["foo"](3) |
||
@show functions["bar"](3)</ |
@show functions["bar"](3)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 352: | Line 352: | ||
=={{header|Kotlin}}== |
=={{header|Kotlin}}== |
||
When you try to compile the following program, it will appear to the compiler that the local variable 'c' is assigned but never used and a warning will be issued accordingly. You can get rid of this warning by compiling using the -nowarn flag. |
When you try to compile the following program, it will appear to the compiler that the local variable 'c' is assigned but never used and a warning will be issued accordingly. You can get rid of this warning by compiling using the -nowarn flag. |
||
< |
<syntaxhighlight lang="scala">// Kotlin JS version 1.1.4-3 |
||
class C { |
class C { |
||
Line 364: | Line 364: | ||
val f = "c.foo" |
val f = "c.foo" |
||
js(f)() // invokes c.foo dynamically |
js(f)() // invokes c.foo dynamically |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 372: | Line 372: | ||
=={{header|Lasso}}== |
=={{header|Lasso}}== |
||
< |
<syntaxhighlight lang="lasso">define mytype => type { |
||
public foo() => { |
public foo() => { |
||
return 'foo was called' |
return 'foo was called' |
||
Line 382: | Line 382: | ||
local(obj = mytype, methodname = tag('foo'), methodname2 = tag('bar')) |
local(obj = mytype, methodname = tag('foo'), methodname2 = tag('bar')) |
||
#obj->\#methodname->invoke |
#obj->\#methodname->invoke |
||
#obj->\#methodname2->invoke</ |
#obj->\#methodname2->invoke</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>foo was called |
<pre>foo was called |
||
Line 388: | Line 388: | ||
=={{header|Lingo}}== |
=={{header|Lingo}}== |
||
< |
<syntaxhighlight lang="lingo">obj = script("MyClass").new() |
||
-- ... |
-- ... |
||
method = #foo |
method = #foo |
||
arg1 = 23 |
arg1 = 23 |
||
res = call(method, obj, arg1)</ |
res = call(method, obj, arg1)</syntaxhighlight> |
||
=={{header|Logtalk}}== |
=={{header|Logtalk}}== |
||
For this task, we first define a simple object with a single method: |
For this task, we first define a simple object with a single method: |
||
< |
<syntaxhighlight lang="logtalk">:- object(foo). |
||
:- public(bar/1). |
:- public(bar/1). |
||
bar(42). |
bar(42). |
||
:- end_object.</ |
:- end_object.</syntaxhighlight>Second, we define another object that asks the user for a message to be sent to the first object:<syntaxhighlight lang="logtalk"> |
||
:- object(query_foo). |
:- object(query_foo). |
||
Line 412: | Line 412: | ||
write(Message), nl. |
write(Message), nl. |
||
:- end_object.</ |
:- end_object.</syntaxhighlight>After compiling and loading both objects, we can try: |
||
| ?- query_foo::query. |
| ?- query_foo::query. |
||
Message: bar(X). |
Message: bar(X). |
||
Line 419: | Line 419: | ||
=={{header|Lua}}== |
=={{header|Lua}}== |
||
Don't forget to pass the object for methods! |
Don't forget to pass the object for methods! |
||
< |
<syntaxhighlight lang="lua">local example = { } |
||
function example:foo (x) return 42 + x end |
function example:foo (x) return 42 + x end |
||
local name = "foo" |
local name = "foo" |
||
example[name](example, 5) --> 47</ |
example[name](example, 5) --> 47</syntaxhighlight> |
||
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
=={{header|Mathematica}}/{{header|Wolfram Language}}== |
||
Creates a dialog box where one can type a function (Sin, Cos, Tan ...) and then a second dialog box for a value. |
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"]]</ |
<syntaxhighlight lang="text">ToExpression[Input["function? E.g. Sin",]][Input["value? E.g. 0.4123"]]</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
<pre>Input: Sin |
<pre>Input: Sin |
||
Line 436: | Line 436: | ||
<syntaxhighlight lang="matlab"> |
|||
<lang Matlab> |
|||
funName = 'foo'; % generate function name |
funName = 'foo'; % generate function name |
||
feval (funNAME, ...) % evaluation function with optional parameters |
feval (funNAME, ...) % evaluation function with optional parameters |
||
Line 442: | Line 442: | ||
funName = 'a=atan(pi)'; % generate function name |
funName = 'a=atan(pi)'; % generate function name |
||
eval (funName, 'printf(''Error\n'')') |
eval (funName, 'printf(''Error\n'')') |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Objective-C}}== |
=={{header|Objective-C}}== |
||
< |
<syntaxhighlight lang="objc">#import <Foundation/Foundation.h> |
||
@interface Example : NSObject |
@interface Example : NSObject |
||
Line 466: | Line 466: | ||
} |
} |
||
return 0; |
return 0; |
||
}</ |
}</syntaxhighlight> |
||
The <code>performSelector: ...</code> methods can only be used with methods with 0 - 2 object arguments, and an object or <code>void</code> return type. For all other calls, one can create an <code>NSInvocation</code> object and invoke it, or directly call one of the <code>objc_msgSend</code> family of runtime functions. |
The <code>performSelector: ...</code> methods can only be used with methods with 0 - 2 object arguments, and an object or <code>void</code> return type. For all other calls, one can create an <code>NSInvocation</code> object and invoke it, or directly call one of the <code>objc_msgSend</code> family of runtime functions. |
||
Line 472: | Line 472: | ||
A method object can be retrieved from its name using asMethod. |
A method object can be retrieved from its name using asMethod. |
||
< |
<syntaxhighlight lang="oforth">16 "sqrt" asMethod perform</syntaxhighlight> |
||
Others : |
Others : |
||
Line 480: | Line 480: | ||
A generic way to search a word into the dictionary in to use find method : |
A generic way to search a word into the dictionary in to use find method : |
||
< |
<syntaxhighlight lang="oforth">16 "sqrt" Word find perform</syntaxhighlight> |
||
=={{header|PARI/GP}}== |
=={{header|PARI/GP}}== |
||
< |
<syntaxhighlight lang="parigp">foo()=5; |
||
eval(Str("foo","()"))</ |
eval(Str("foo","()"))</syntaxhighlight> |
||
=={{header|Perl}}== |
=={{header|Perl}}== |
||
< |
<syntaxhighlight lang="perl">package Example; |
||
sub new { |
sub new { |
||
bless {} |
bless {} |
||
Line 498: | Line 498: | ||
package main; |
package main; |
||
my $name = "foo"; |
my $name = "foo"; |
||
print Example->new->$name(5), "\n"; # prints "47"</ |
print Example->new->$name(5), "\n"; # prints "47"</syntaxhighlight> |
||
=={{header|Phix}}== |
=={{header|Phix}}== |
||
Not specifically anything to do with objects, but you can construct routine names at runtime: |
Not specifically anything to do with objects, but you can construct routine names at runtime: |
||
<!--< |
<!--<syntaxhighlight lang="phix">(phixonline)--> |
||
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span> |
||
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Hello</span><span style="color: #0000FF;">()</span> |
<span style="color: #008080;">procedure</span> <span style="color: #000000;">Hello</span><span style="color: #0000FF;">()</span> |
||
Line 514: | Line 514: | ||
<span style="color: #7060A8;">call_proc</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #000000;">erm</span><span style="color: #0000FF;">),{})</span> |
<span style="color: #7060A8;">call_proc</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">routine_id</span><span style="color: #0000FF;">(</span><span style="color: #000000;">erm</span><span style="color: #0000FF;">),{})</span> |
||
<!--</ |
<!--</syntaxhighlight>--> |
||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
< |
<syntaxhighlight lang="php"><?php |
||
class Example { |
class Example { |
||
function foo($x) { |
function foo($x) { |
||
Line 531: | Line 531: | ||
// alternately: |
// alternately: |
||
echo call_user_func(array($example, $name), 5), "\n"; |
echo call_user_func(array($example, $name), 5), "\n"; |
||
?></ |
?></syntaxhighlight> |
||
=={{header|Picat}}== |
=={{header|Picat}}== |
||
For functions use <code>apply/n</code> and for predicates <code>call/n</code>. The name of the function/predicate must be an atom and strings must be converted to atom, e.g. with <code>to_atom/1</code>. |
For functions use <code>apply/n</code> and for predicates <code>call/n</code>. The name of the function/predicate must be an atom and strings must be converted to atom, e.g. with <code>to_atom/1</code>. |
||
< |
<syntaxhighlight lang="picat">go => |
||
println("Function: Use apply/n"), |
println("Function: Use apply/n"), |
||
Fun = "fib", |
Fun = "fib", |
||
Line 562: | Line 562: | ||
% A predicate |
% A predicate |
||
pyth(X,Y,Z) => |
pyth(X,Y,Z) => |
||
Z = X**2 + Y**2.</ |
Z = X**2 + Y**2.</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 574: | Line 574: | ||
=={{header|PicoLisp}}== |
=={{header|PicoLisp}}== |
||
This can be done with the '[http://software-lab.de/doc/refS.html#send send]' function. |
This can be done with the '[http://software-lab.de/doc/refS.html#send send]' function. |
||
< |
<syntaxhighlight lang="picolisp">(send (expression) Obj arg1 arg2)</syntaxhighlight> |
||
=={{header|Pike}}== |
=={{header|Pike}}== |
||
with [] instead of -> a string can be used to name a method: |
with [] instead of -> a string can be used to name a method: |
||
< |
<syntaxhighlight lang="pike">string unknown = "format_nice"; |
||
object now = Calendar.now(); |
object now = Calendar.now(); |
||
now[unknown]();</ |
now[unknown]();</syntaxhighlight> |
||
=={{header|PowerShell}}== |
=={{header|PowerShell}}== |
||
A random method using a random number: |
A random method using a random number: |
||
<syntaxhighlight lang="powershell"> |
|||
<lang PowerShell> |
|||
$method = ([Math] | Get-Member -MemberType Method -Static | Where-Object {$_.Definition.Split(',').Count -eq 1} | Get-Random).Name |
$method = ([Math] | Get-Member -MemberType Method -Static | Where-Object {$_.Definition.Split(',').Count -eq 1} | Get-Random).Name |
||
$number = (1..9 | Get-Random) / 10 |
$number = (1..9 | Get-Random) / 10 |
||
Line 595: | Line 595: | ||
$output | Format-List |
$output | Format-List |
||
</syntaxhighlight> |
|||
</lang> |
|||
{{Out}} |
{{Out}} |
||
<pre> |
<pre> |
||
Line 605: | Line 605: | ||
=={{header|Python}}== |
=={{header|Python}}== |
||
String literal "foo" may be replaced by any expression resulting in a string |
String literal "foo" may be replaced by any expression resulting in a string |
||
< |
<syntaxhighlight lang="python">class Example(object): |
||
def foo(self, x): |
def foo(self, x): |
||
return 42 + x |
return 42 + x |
||
name = "foo" |
name = "foo" |
||
getattr(Example(), name)(5) # => 47</ |
getattr(Example(), name)(5) # => 47</syntaxhighlight> |
||
=={{header|Qi}}== |
=={{header|Qi}}== |
||
<syntaxhighlight lang="qi"> |
|||
<lang qi> |
|||
(define foo -> 5) |
(define foo -> 5) |
||
Line 620: | Line 620: | ||
(execute-function "foo") |
(execute-function "foo") |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Racket}}== |
=={{header|Racket}}== |
||
< |
<syntaxhighlight lang="racket"> |
||
#lang racket |
#lang racket |
||
(define greeter |
(define greeter |
||
Line 636: | Line 636: | ||
(define unknown 'hello) |
(define unknown 'hello) |
||
(dynamic-send greeter unknown "World") |
(dynamic-send greeter unknown "World") |
||
</syntaxhighlight> |
|||
</lang> |
|||
=={{header|Raku}}== |
=={{header|Raku}}== |
||
(formerly Perl 6) |
(formerly Perl 6) |
||
Just for the fun of it, we'll mix in an anonymous role into an integer instead of defining a class. |
Just for the fun of it, we'll mix in an anonymous role into an integer instead of defining a class. |
||
<lang |
<syntaxhighlight lang="raku" line>my $object = 42 but role { method add-me($x) { self + $x } } |
||
my $name = 'add-me'; |
my $name = 'add-me'; |
||
say $object."$name"(5); # 47</ |
say $object."$name"(5); # 47</syntaxhighlight> |
||
The double quotes are required, by the way; without them the variable would be interpreted as a hard ref to a method. |
The double quotes are required, by the way; without them the variable would be interpreted as a hard ref to a method. |
||
Line 649: | Line 649: | ||
You may replace :foo, :bar or "bar" with any expression that returns a Symbol or String. |
You may replace :foo, :bar or "bar" with any expression that returns a Symbol or String. |
||
< |
<syntaxhighlight lang="ruby">class Example |
||
def foo |
def foo |
||
42 |
42 |
||
Line 662: | Line 662: | ||
Example.new.send( :bar, 1, 2 ) { |x,y| x+y } # => 3 |
Example.new.send( :bar, 1, 2 ) { |x,y| x+y } # => 3 |
||
args = [1, 2] |
args = [1, 2] |
||
Example.new.send( "bar", *args ) { |x,y| x+y } # => 3</ |
Example.new.send( "bar", *args ) { |x,y| x+y } # => 3</syntaxhighlight> |
||
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. |
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|1.9}} |
{{works with|Ruby|1.9}} |
||
< |
<syntaxhighlight lang="ruby">class Example |
||
private |
private |
||
def privacy; "secret"; end |
def privacy; "secret"; end |
||
Line 677: | Line 677: | ||
e.public_send :publicity # => "hi" |
e.public_send :publicity # => "hi" |
||
e.public_send :privacy # raises NoMethodError |
e.public_send :privacy # raises NoMethodError |
||
e.send :privacy # => "secret"</ |
e.send :privacy # => "secret"</syntaxhighlight> |
||
=={{header|Scala}}== |
=={{header|Scala}}== |
||
{{libheader|Scala}}< |
{{libheader|Scala}}<syntaxhighlight lang="scala">class Example { |
||
def foo(x: Int): Int = 42 + x |
def foo(x: Int): Int = 42 + x |
||
} |
} |
||
Line 691: | Line 691: | ||
assert(meth.invoke(example, 5.asInstanceOf[AnyRef]) == 47.asInstanceOf[AnyRef], "Not confirm expectation.") |
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]") |
println(s"Successfully completed without errors. [total ${scala.compat.Platform.currentTime - executionStart} ms]") |
||
}</ |
}</syntaxhighlight> |
||
=={{header|Sidef}}== |
=={{header|Sidef}}== |
||
< |
<syntaxhighlight lang="ruby">class Example { |
||
method foo(x) { |
method foo(x) { |
||
42 + x |
42 + x |
||
Line 704: | Line 704: | ||
say obj.(name)(5) # prints: 47 |
say obj.(name)(5) # prints: 47 |
||
say obj.method(name)(5) # =//=</ |
say obj.method(name)(5) # =//=</syntaxhighlight> |
||
=={{header|Smalltalk}}== |
=={{header|Smalltalk}}== |
||
< |
<syntaxhighlight lang="smalltalk">Object subclass: #Example. |
||
Example extend [ |
Example extend [ |
||
Line 715: | Line 715: | ||
symbol := 'foo:' asSymbol. " same as symbol := #foo: " |
symbol := 'foo:' asSymbol. " same as symbol := #foo: " |
||
Example new perform: symbol with: 5. " returns 47 "</ |
Example new perform: symbol with: 5. " returns 47 "</syntaxhighlight> |
||
The <code>perform:with:with:</code> family of methods exist for methods with 0 - 2 (3 in [[GNU Smalltalk]]) arguments. For methods with more arguments, use <code>perform:withArguments:</code>, which takes an array of arguments. |
The <code>perform:with:with:</code> family of methods exist for methods with 0 - 2 (3 in [[GNU Smalltalk]]) arguments. For methods with more arguments, use <code>perform:withArguments:</code>, which takes an array of arguments. |
||
Line 727: | Line 727: | ||
The first case is used for interfacing with legacy Objective-C libraries. Objective-C is heavily dynamic with Smalltalk-style message passing. So Swift must be able to participate in this. |
The first case is used for interfacing with legacy Objective-C libraries. Objective-C is heavily dynamic with Smalltalk-style message passing. So Swift must be able to participate in this. |
||
< |
<syntaxhighlight lang="swift">import Foundation |
||
class MyUglyClass: NSObject { |
class MyUglyClass: NSObject { |
||
Line 738: | Line 738: | ||
let someObject: NSObject = MyUglyClass() |
let someObject: NSObject = MyUglyClass() |
||
someObject.perform(NSSelectorFromString("myUglyFunction"))</ |
someObject.perform(NSSelectorFromString("myUglyFunction"))</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 748: | Line 748: | ||
One of Swift's goals is to able to effectively bridge to dynamic languages such as Python and JavaScript. In order to facilitate more natural APIs, Swift provides the <code>@dynamicCallable</code> and <code>@dynamicMemberLookup</code> attributes which allow for runtime handling of method calls. |
One of Swift's goals is to able to effectively bridge to dynamic languages such as Python and JavaScript. In order to facilitate more natural APIs, Swift provides the <code>@dynamicCallable</code> and <code>@dynamicMemberLookup</code> attributes which allow for runtime handling of method calls. |
||
< |
<syntaxhighlight lang="swift">@dynamicCallable |
||
protocol FunDynamics { |
protocol FunDynamics { |
||
var parent: MyDynamicThing { get } |
var parent: MyDynamicThing { get } |
||
Line 832: | Line 832: | ||
.subtract(adding: 10, subtracting: 14) |
.subtract(adding: 10, subtracting: 14) |
||
print(thing.n)</ |
print(thing.n)</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 840: | Line 840: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
Method names are really just strings, i.e., ordinary values that can be produced by any mechanism: |
Method names are really just strings, i.e., ordinary values that can be produced by any mechanism: |
||
< |
<syntaxhighlight lang="tcl">package require Tcl 8.6 |
||
oo::class create Example { |
oo::class create Example { |
||
method foo {} {return 42} |
method foo {} {return 42} |
||
Line 853: | Line 853: | ||
for {set i 1} {$i <= 4} {incr i} { |
for {set i 1} {$i <= 4} {incr i} { |
||
$eg $i ... |
$eg $i ... |
||
}</ |
}</syntaxhighlight> |
||
{{out|The above produces this output}} |
{{out|The above produces this output}} |
||
42 |
42 |
||
Line 862: | Line 862: | ||
=={{header|Wren}}== |
=={{header|Wren}}== |
||
< |
<syntaxhighlight lang="ecmascript">import "meta" for Meta |
||
class Test { |
class Test { |
||
Line 875: | Line 875: | ||
for (method in ["foo", "bar"]) { |
for (method in ["foo", "bar"]) { |
||
Meta.eval("test.%(method)()") |
Meta.eval("test.%(method)()") |
||
}</ |
}</syntaxhighlight> |
||
{{out}} |
{{out}} |
||
Line 884: | Line 884: | ||
=={{header|zkl}}== |
=={{header|zkl}}== |
||
< |
<syntaxhighlight lang="zkl">name:="len"; "this is a test".resolve(name)() //-->14</syntaxhighlight> |
||
{{omit from|Ada}} |
{{omit from|Ada}} |
Revision as of 13:44, 28 August 2022
You are encouraged to solve this task according to the task description, using any language you may know.
- Task
Invoke an object method where the name of the method to be invoked can be generated at run time.
- Related tasks
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.
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
}
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
);
- 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#
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);
}
}
- Output:
foo(5) = 47
Caché ObjectScript
$METHOD executes a named instance method for a specified instance of a designated class.
Class Unknown.Example Extends %RegisteredObject
{
Method Foo()
{
Write "This is foo", !
}
Method Bar()
{
Write "This is bar", !
}
}
- Examples:
USER>Set obj=##class(Unknown.Example).%New() USER>Do $Method(obj, "Foo") This is foo USER>Do $Method(obj, "Bar") This is bar
Clojure
(import '[java.util Date])
(import '[clojure.lang Reflector])
(def date1 (Date.))
(def date2 (Date.))
(def method "equals")
;; Two ways of invoking method "equals" on object date1
;; using date2 as argument
;; Way 1 - Using Reflector class
;; NOTE: The argument date2 is passed inside an array
(Reflector/invokeMethod date1 method (object-array [date2]))
;; Way 2 - Using eval
;; Eval runs any piece of valid Clojure code
;; So first we construct a piece of code to do what we want (where method name is inserted dynamically),
;; then we run the code using eval
(eval `(. date1 ~(symbol method) date2))
Common Lisp
Unknown methods are called just like any other function. Find the method-naming symbol using INTERN then call it with FUNCALL.
(funcall (intern "SOME-METHOD") my-object a few arguments)
Déjà Vu
local :object { :add @+ }
local :method :add
!. object! method 1 2
- Output:
3
E
This example goes well with the object named example
in Respond to an unknown method call#E.
for name in ["foo", "bar"] {
E.call(example, name, [])
}
Elena
ELENA 4.1 :
import extensions;
class Example
{
foo(x)
= x + 42;
}
public program()
{
var example := new Example();
var methodSignature := "foo";
var invoker := new MessageName(methodSignature);
var result := invoker(example,5);
console.printLine(methodSignature,"(",5,") = ",result)
}
- Output:
foo(5) = 47
Factor
Factor's object model is such that objects themselves don't contain methods — generic words do. So there is nothing different about invoking an unknown method than invoking an unknown word in general.
USING: accessors kernel math prettyprint sequences words ;
IN: rosetta-code.unknown-method-call
TUPLE: foo num ;
C: <foo> foo
GENERIC: add5 ( x -- y )
M: foo add5 num>> 5 + ;
42 <foo> ! construct a foo
"add" "5" append ! construct a word name
! must specify vocab to look up a word
"rosetta-code.unknown-method-call"
lookup-word execute . ! 47
Forth
Works with any ANS Forth
Needs the FMS-SI (single inheritance) library code located here: http://soton.mpeforth.com/flag/fms/index.html
include FMS-SI.f
include FMS-SILib.f
var x \ instantiate a class var object named x
\ Use a standard Forth string and evaluate it.
\ This is equivalent to sending the !: message to object x
42 x s" !:" evaluate
x p: 42 \ send the print message ( p: ) to x to verify the contents
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
}
Groovy
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)
Icon and 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
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.
Example := Object clone
Example foo := method(x, 42+x)
name := "foo"
Example clone perform(name,5) println // prints "47"
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:
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
Java
Using reflection
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"
}
}
JavaScript
String literal "foo" may be replaced by any expression resulting in a string
example = new Object;
example.foo = function(x) {
return 42 + x;
};
name = "foo";
example[name](5) # => 47
Julia
const functions = Dict{String,Function}(
"foo" => x -> 42 + x,
"bar" => x -> 42 * x)
@show functions["foo"](3)
@show functions["bar"](3)
- Output:
(functions["foo"])(3) = 45 (functions["bar"])(3) = 126
Kotlin
When you try to compile the following program, it will appear to the compiler that the local variable 'c' is assigned but never used and a warning will be issued accordingly. You can get rid of this warning by compiling using the -nowarn flag.
// Kotlin JS version 1.1.4-3
class C {
fun foo() {
println("foo called")
}
}
fun main(args: Array<String>) {
val c = C()
val f = "c.foo"
js(f)() // invokes c.foo dynamically
}
- Output:
foo called
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'))
#obj->\#methodname->invoke
#obj->\#methodname2->invoke
- Output:
foo was called this time is was bar
Lingo
obj = script("MyClass").new()
-- ...
method = #foo
arg1 = 23
res = call(method, obj, arg1)
Logtalk
For this task, we first define a simple object with a single method:
:- object(foo).
:- public(bar/1).
bar(42).
:- end_object.
Second, we define another object that asks the user for a message to be sent to the first object:
:- object(query_foo).
:- public(query/0).
query :-
write('Message: '),
read(Message),
foo::Message.
write('Reply: '),
write(Message), nl.
:- end_object.
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!
local example = { }
function example:foo (x) return 42 + x end
local name = "foo"
example[name](example, 5) --> 47
Mathematica/Wolfram Language
Creates a dialog box where one can type a function (Sin, Cos, Tan ...) and then a second dialog box for a value.
ToExpression[Input["function? E.g. Sin",]][Input["value? E.g. 0.4123"]]
- Output:
Input: Sin Input: 3.1415 Output: 0.0000926536
MATLAB / Octave
funName = 'foo'; % generate function name
feval (funNAME, ...) % evaluation function with optional parameters
funName = 'a=atan(pi)'; % generate function name
eval (funName, 'printf(''Error\n'')')
Objective-C
#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;
}
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.
16 "sqrt" asMethod perform
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 :
16 "sqrt" Word find perform
PARI/GP
foo()=5;
eval(Str("foo","()"))
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"
Phix
Not specifically anything to do with objects, but you can construct routine names at runtime:
with javascript_semantics procedure Hello() ?"Hello" end procedure string erm = "Hemmm" for i=3 to 5 do erm[i]+=-1+(i=5)*3 end for call_proc(routine_id(erm),{})
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";
?>
Picat
For functions use apply/n
and for predicates call/n
. The name of the function/predicate must be an atom and strings must be converted to atom, e.g. with to_atom/1
.
go =>
println("Function: Use apply/n"),
Fun = "fib",
A = 10,
% Convert F to an atom
println(apply(to_atom(Fun),A)),
nl,
println("Predicate: use call/n"),
Pred = "pyth",
call(Pred.to_atom,3,4,Z),
println(z=Z),
% Pred2 is an atom so it can be used directly with call/n.
Pred2 = pyth,
call(Pred.to_atom,13,14,Z2),
println(z2=Z2),
nl.
% A function
fib(1) = 1.
fib(2) = 1.
fib(N) = fib(N-1) + fib(N-2).
% A predicate
pyth(X,Y,Z) =>
Z = X**2 + Y**2.
- Output:
Function: Use apply/n 55 Predicate: use call/n z = 25 z2 = 365
PicoLisp
This can be done with the 'send' function.
(send (expression) Obj arg1 arg2)
Pike
with [] instead of -> a string can be used to name a method:
string unknown = "format_nice";
object now = Calendar.now();
now[unknown]();
PowerShell
A random method using a random number:
$method = ([Math] | Get-Member -MemberType Method -Static | Where-Object {$_.Definition.Split(',').Count -eq 1} | Get-Random).Name
$number = (1..9 | Get-Random) / 10
$result = [Math]::$method($number)
$output = [PSCustomObject]@{
Method = $method
Number = $number
Result = $result
}
$output | Format-List
- Output:
Method : Atan Number : 0.5 Result : 0.463647609000806
Python
String literal "foo" may be replaced by any expression resulting in a string
class Example(object):
def foo(self, x):
return 42 + x
name = "foo"
getattr(Example(), name)(5) # => 47
Qi
(define foo -> 5)
(define execute-function
Name -> (eval [(INTERN Name)]))
(execute-function "foo")
Racket
#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")
Raku
(formerly Perl 6) Just for the fun of it, we'll mix in an anonymous role into an integer instead of defining a class.
my $object = 42 but role { method add-me($x) { self + $x } }
my $name = 'add-me';
say $object."$name"(5); # 47
The double quotes are required, by the way; without them the variable would be interpreted as a hard ref to a method.
Ruby
You may replace :foo, :bar or "bar" with any expression that returns a Symbol or String.
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
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.
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"
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]")
}
Sidef
class Example {
method foo(x) {
42 + x
}
}
var name = 'foo'
var obj = Example()
say obj.(name)(5) # prints: 47
say obj.method(name)(5) # =//=
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 "
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.
Swift
Generally speaking, pure Swift is a very statically typed language, and calling unknown methods is impossible. However, Swift provides a few ways in which instances of specially marked objects can receive unknown method calls.
Objective-C Compatibility Using @objc
The first case is used for interfacing with legacy Objective-C libraries. Objective-C is heavily dynamic with Smalltalk-style message passing. So Swift must be able to participate in this.
import Foundation
class MyUglyClass: NSObject {
@objc
func myUglyFunction() {
print("called myUglyFunction")
}
}
let someObject: NSObject = MyUglyClass()
someObject.perform(NSSelectorFromString("myUglyFunction"))
- Output:
called myUglyFunction
Dynamic Language Interop with @dynamicCallable and @dynamicMemberLookup
One of Swift's goals is to able to effectively bridge to dynamic languages such as Python and JavaScript. In order to facilitate more natural APIs, Swift provides the @dynamicCallable
and @dynamicMemberLookup
attributes which allow for runtime handling of method calls.
@dynamicCallable
protocol FunDynamics {
var parent: MyDynamicThing { get }
func dynamicallyCall(withArguments args: [Int]) -> MyDynamicThing
func dynamicallyCall(withKeywordArguments args: [String: Int]) -> MyDynamicThing
}
extension FunDynamics {
func dynamicallyCall(withKeywordArguments args: [String: Int]) -> MyDynamicThing {
if let add = args["adding"] {
parent.n += add
}
if let sub = args["subtracting"] {
parent.n -= sub
}
return parent
}
}
@dynamicMemberLookup
class MyDynamicThing {
var n: Int
init(n: Int) {
self.n = n
}
subscript(dynamicMember member: String) -> FunDynamics {
switch member {
case "subtract":
return Subtracter(parent: self)
case "add":
return Adder(parent: self)
case _:
return Nuller(parent: self)
}
}
}
struct Nuller: FunDynamics {
var parent: MyDynamicThing
func dynamicallyCall(withArguments args: [Int]) -> MyDynamicThing { parent }
}
struct Subtracter: FunDynamics {
var parent: MyDynamicThing
func dynamicallyCall(withArguments args: [Int]) -> MyDynamicThing {
switch args.count {
case 1:
parent.n -= args[0]
case _:
print("Unknown call")
}
return parent
}
}
struct Adder: FunDynamics {
var parent: MyDynamicThing
func dynamicallyCall(withArguments arg: [Int]) -> MyDynamicThing {
switch arg.count {
case 1:
parent.n += arg[0]
case _:
print("Unknown call")
}
return parent
}
}
let thing =
MyDynamicThing(n: 0)
.add(20)
.divide(2) // Unhandled call, do nothing
.subtract(adding: 10, subtracting: 14)
print(thing.n)
- Output:
16
Tcl
Method names are really just strings, i.e., ordinary values that can be produced by any mechanism:
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 ...
}
- The above produces this output:
42 fee... fie... foe... fum...
Wren
import "meta" for Meta
class Test {
construct new() {}
foo() { System.print("Foo called.") }
bar() { System.print("Bar called.") }
}
var test = Test.new()
for (method in ["foo", "bar"]) {
Meta.eval("test.%(method)()")
}
- Output:
Foo called. Bar called.
zkl
name:="len"; "this is a test".resolve(name)() //-->14
- Programming Tasks
- Object oriented
- AutoHotkey
- Bracmat
- C sharp
- Caché ObjectScript
- Clojure
- Common Lisp
- Déjà Vu
- E
- Elena
- Factor
- Forth
- Go
- Groovy
- Unicon
- Io
- J
- Java
- JavaScript
- Julia
- Kotlin
- Lasso
- Lingo
- Logtalk
- Lua
- Mathematica
- Wolfram Language
- MATLAB
- Octave
- Objective-C
- Oforth
- PARI/GP
- Perl
- Phix
- PHP
- Picat
- PicoLisp
- Pike
- PowerShell
- Python
- Qi
- Racket
- Raku
- Ruby
- Scala
- Sidef
- Smalltalk
- Swift
- Tcl
- Wren
- Zkl
- Ada/Omit
- Axe/Omit
- BASIC/Omit
- C/Omit
- C++/Omit
- GUISS/Omit
- Nim/Omit
- Rust/Omit
- ZX Spectrum Basic/Omit