September 2017 Update

This commit is contained in:
Ingy döt Net 2017-09-23 10:01:46 +02:00
parent bba7bfd280
commit ba8067c3b7
14570 changed files with 153136 additions and 63871 deletions

View file

@ -1,3 +1,4 @@
{{omit from|Rust}}
Demonstrate how to dynamically add variables to an object (a class instance) at runtime.
This is useful when the methods/variables of an instance are based on a data file that isn't available until runtime. Hal Fulton gives an example of creating an OO CSV parser at [http://www.devsource.com/article2/0,1759,1928562,00.asp An Exercise in Metaprogramming with Ruby]. This is referred to as "monkeypatching" by Pythonistas and some others.

View file

@ -1,33 +1,25 @@
#define system.
#define extensions.
import extensions.
#class Extender :: BaseExtender
class Extender :: BaseExtender
{
#field theField.
object prop foo :: theField.
#constructor new : anObject
constructor new : anObject
[
theObject := anObject.
]
#method foo = theField.
#method set &foo : aValue
[
theField := aValue.
]
}
#symbol program =
program =
[
#var anObject := 234.
var anObject := 234.
// extending an object with a field
anObject := Extender new:anObject.
anObject := Extender new(anObject).
anObject set &foo:"bar".
anObject foo := "bar".
console writeLine:anObject:".foo=":(anObject foo).
console printLine(anObject,".foo=",anObject foo).
console readChar.
].

View file

@ -9,6 +9,7 @@ include FMS-SILib.f
:class foo
object-list inst-objects \ a dynamically growable object container
:m init: inst-objects init: ;m
:m add: ( obj -- ) inst-objects add: ;m
:m at: ( idx -- obj ) inst-objects at: ;m
;class

View file

@ -0,0 +1,30 @@
// version 1.1.2
class SomeClass {
val runtimeVariables = mutableMapOf<String, Any>()
}
fun main(args: Array<String>) {
val sc = SomeClass()
println("Create two variables at runtime: ")
for (i in 1..2) {
println(" Variable #$i:")
print(" Enter name : ")
val name = readLine()!!
print(" Enter value : ")
val value = readLine()!!
sc.runtimeVariables.put(name, value)
println()
}
while (true) {
print("Which variable do you want to inspect ? ")
val name = readLine()!!
val value = sc.runtimeVariables[name]
if (value == null) {
println("There is no variable of that name, try again")
} else {
println("Its value is '${sc.runtimeVariables[name]}'")
return
}
}
}

View file

@ -0,0 +1,37 @@
d = .dynamicvar~new
d~foo = 123
say d~foo
d2 = .dynamicvar2~new
d~bar = "Fred"
say d~bar
-- a class that allows dynamic variables. Since this is a mixin, this
-- capability can be added to any class using multiple inheritance
::class dynamicvar MIXINCLASS object
::method init
expose variables
variables = .directory~new
-- the UNKNOWN method is invoked for all unknown messages. We turn this
-- into either an assignment or a retrieval for the desired item
::method unknown
expose variables
use strict arg messageName, arguments
-- assignment messages end with '=', which tells us what to do
if messageName~right(1) == '=' then do
variables[messageName~left(messageName~length - 1)] = arguments[1]
end
else do
return variables[messageName]
end
-- this class is not a direct subclass of dynamicvar, but mixes in the
-- functionality using multiple inheritance
::class dynamicvar2 inherit dynamicvar
::method init
-- mixin init methods are not automatically invoked, so we must
-- explicitly invoke this
self~init:.dynamicvar

View file

@ -0,0 +1,35 @@
d = .dynamicvar~new
d~foo = 123
say d~foo
-- a class that allows dynamic variables. Since this is a mixin, this
-- capability can be added to any class using multiple inheritance
::class dynamicvar MIXINCLASS object
::method init
expose variables
variables = .directory~new
-- the unknown method will get invoked any time an unknown method is
-- used. This UNKNOWN method will add attribute methods for the given
-- name that will be available on all subsequent uses.
::method unknown
expose variables
use strict arg messageName, arguments
-- check for an assignment or fetch, and get the proper
-- method name
if messageName~right(1) == '=' then do
variableName = messageName~left(messageName~length - 1)
end
else do
variableName = messageName
end
-- define a pair of methods to set and retrieve the instance variable. These are
-- created at the object scope
self~setMethod(variableName, 'expose' variableName'; return' variableName)
self~setMethod(variableName'=', 'expose' variableName'; use strict arg value;' variableName '= value' )
-- reinvoke the original message. This will now go to the dynamically added
methods
forward to(self) message(messageName) arguments(arguments)