Recently i started to learn iolanguage. When trying out the "method" message, i wrote:
Io> f := method(getSlot("f"))
==> method(
getSlot("f")
)
Io> slotSummary
==> Object_0x97f41a8:
Lobby = Object_0x97f41a8
Protos = Object_0x97f4090
_ = nil
exit = method(...)
f = method(...)
forward = method(...)
set_ = method(...)
Io> f
==> nil
But why calling to f will return nil instead of "f" itself?
According to guide method() introduces an Object to store locals and sets the local's self pointer to the target of the message.
Thus there is no slots from target but we can get them through self:
Io> f := method(self getSlot("f"))
==> method(
self getSlot("f")
)
Io> f
==> method(
self getSlot("f")
)
Try g := block(getSlot("g")), which should do what you expect. Unfortunately, I can not explain why this is the case - sorry. I suppose it has to do with the fact that block and method set the self and proto pointer in different ways.
You can try the following within a method resp. block and compare the results:
call sender #locals object of caller
call message #message used to call this method/block
call activated #the activated method/block
call slotContext #context in which slot was found
call target #current object
Related
As I understand from docs, we don't have classes in Lua. Lua does not have the concept of class; each object defines its own behavior and has a shape of its own.
So a simple emulation of classes in Lua, following the lead from prototype-based languages, such as Self and NewtonScript would be something like.
function Account:new (o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
What I don't understand here is what does o = o do and why do we need to use setmetadatatable and the next line index = self.
What does it do and why do we need them?
Also self.o = o was pretty much understood, but o = o, wouldn't that create any conflict?
https://www.lua.org/pil/16.1.html
A = B or C is commonly used idiom, relying on short-circuit evaluation of logic operators. If the first operand B is not null or false, then the A gets value of B, and the other operand is not evaluated. If the B is null or false, then the A gets value of C.
In this particular application of the idiom the o gets default value of new empty table when the parameter o wasn't given, because the missing parameter evaluates to null value.
The parameter o is a local variable, so all the effects of assigning anything to it will stay local to the Account:new() function.
For the first line, see Vlads answer.
setmetatable(o, self) assigns self as the metatable of o. self can now contain a set of metamethods to add functionality to o (see link for more information).
__index is the metamethod called when o does not contain an indexed key. It can also be another table. In this example, __index is set to self, so if you attempt to index a nil value in o, it will look in self instead. If you only call Account:new(), self is Account.
Example from you link: you have an deposit function in Account. After you created your object o = Account:new() you can now call o:deposit(). This will look in o for deposit, fails, then looks in __index=Account for deposit, succeeds, calls it.
If you do not set the metatable, or __index, calling o:deposit() will result in an attempt to call a nil value.
I am resubmitting a question asked almost a decade ago on this site link - but which is not as generic as I would like.
What I am hoping for is a way to construct a function from a list of types, where the final output type can have an arbitrary/default value (such as 0.0 for a float, or "" for a string). So, from
[float; int; float;]
I would get something that amounts to
fun(f: float) ->
fun(i: int) ->
0.0
I am hopeful of achieving this, but am so far unable to. It would be helping me out a lot if I could see a sample that does the above.
The answer in the above link goes some of the way, but the example seems to know its function signature at compile time, which I won't, and also generates a compiler warning.
The scenario I have, for those that find context helpful, is that I want to be able to open a dll and one way or another identify a method which will have a given signature with argument-types limited to a known set of types (i.e. float, int). For each input parameter in this function signature I will run code to generate a 'buffer' object, which will have
a buffer of data items of the given type, i.e. [1.2; 3.2; 4.5]
a supplier of that data type (supplies may be intermittent so the receiving buffer may be empty at any one time)
a generator function that transforms data items before being dispatched. This function can be updated at any time.
a dispatch function. The dispatch target of bufferA will be bufferB, and for bufferB it will be a pub-sub thing where subscribers can subscribe to the end result of the calculation, in this case a stream of floats. Data accumulates in applicative style down the chain of buffers, until the final result is published as a new stream.
a regulator that turns the stream of data heading out to the consumer on or off. This ensures orderly function application.
The function from the dll will eventually be given to BufferA to apply to a float and pass the result on to buffer B (to pick up an int). However, while setting up the buffer infrastructure I only need a function with the correct signature, so a dummy value, such as 0.0, is fine.
For a function of a known signature I can handcraft the code that creates the necessary infrastructure, but I would like to be able to automate this, and ideally register dlls and have new calculated streams available plugin-style without rebuilding the application.
If you're willing to throw type safety out the window, you could do this:
let rec makeFunction = function
| ["int"] -> box 0
| ["float"] -> box 0.0
| ["string"] -> box ""
| "int" :: types ->
box (fun (_ : int) -> makeFunction types)
| "float" :: types ->
box (fun (_ : float) -> makeFunction types)
| "string" :: types ->
box (fun (_ : string) -> makeFunction types)
| _ -> failwith "Unexpected"
Here's a helper function for invoking one of these monstrosities:
let rec invokeFunction types (values : List<obj>) (f : obj) =
match types, values with
| [_], [] -> f
| ("int" :: types'), (value :: values') ->
let f' = f :?> (int -> obj)
let value' = value :?> int
invokeFunction types' values' (f' value')
| ("float" :: types'), (value :: values') ->
let f' = f :?> (float -> obj)
let value' = value :?> float
invokeFunction types' values' (f' value')
| ("string" :: types'), (value :: values') ->
let f' = f :?> (string -> obj)
let value' = value :?> string
invokeFunction types' values' (f' value')
| _ -> failwith "Unexpected"
And here it is in action:
let types = ["int"; "float"; "string"] // int -> float -> string
let f = makeFunction types
let values = [box 1; box 2.0]
let result = invokeFunction types values f
printfn "%A" result // output: ""
Caveat: This is not something I would ever recommend in a million years, but it works.
I got 90% of what I needed from this blog by James Randall, entitled compiling and executing fsharp dynamically at runtime. I was unable to avoid concretely specifying the top level function signature, but a work-around was to generate an fsx script file containing that signature (determined from the relevant MethodInfo contained in the inspected dll), then load and run that script. James' blog/ github repository also describes loading and running functions contained in script files. Having obtained the curried function from the dll, I then apply it to default arguments to get representative functions of n-1 arity using
let p1: 'p1 = Activator.CreateInstance(typeof<'p1>) :?> 'p1
let fArity2 = fArity3 p1
Creating and running a script file is slow, of course, but I only need to perform this once when setting up the calculation stream
local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(v1, v2)
v2(100);
end
b:test2(_, a.test1)
Doesn't work. Value is nil. I could find a solution doing an encapsulation in an anonymous function
b:test2(variable, function(value) a:test1(value) end)
But I find it pretty bad mkay
What is the correct syntax ?
anotherObject:aFunction(variable, object.doStuff) is the correct syntax.
Using a colon : with a function is just syntactic sugar for a call or declaration with an implicit self parameter as the first argument. If you would like to follow the pattern you've shown in your example in a cleaner way, you could use a helper function.
local function bind(t, k)
return function(...) return t[k](t, ...) end
end
You then apply it like so.
anotherObject:aFunction(variable, bind(object, 'doStuff'))
Edit: I believe the solution to your problem will require binding at some level, without resorting to modifying the Lua interpreter or using a code translation step.
This is fundamentally because functions in Lua do not carry any information about their origin. I.e., tables do not inherently own the functions that they store.
For example, the following is perfectly legitimate Lua code.
function Circle:area() -- function Circle.area(self)
-- ...
end
-- Evaluate the function in the "area" slot with Square as the self parameter.
Circle.area(Square)
Of course, you could try a paradigm shift, but it may be too late for that if you're building an entire application based on the idea of functions being tied to the table that they have been indexed from, as you said.
Therefore, I propose the following crazy solution.
local mt = {}
function mt:__index(k)
local v = self._slots[k]
if v == nil then
-- Ascend the inheritance tree.
-- This has to be done with rawget all the way up,
-- otherwise inherited functions would be repeatedly bound.
local p = self
repeat
p = rawget(p, '_parent')
if not p then break end
v = p._slots[k]
until v
end
if type(v) == 'function' then
-- Return a self-bound version of the function.
return function(...) return v(self, ...) end
end
return v
end
function mt:__newindex(k, v)
self._slots[k] = v
end
--- Demo & Tests ---
local function Object(parent)
local o = setmetatable({_slots = {}}, mt)
if parent then rawset(o, '_parent', parent) end
return o
end
local o1 = Object()
local o2 = Object(o1)
assert(o1.abc == nil, 'o1.abc should be nil')
o1.abc = 3
assert(o1.abc == 3, 'o1.abc should be 3')
assert(o2.abc == 3, 'o2.abc should be 3, inherited from o1')
o2.abc = 7
assert(o2.abc == 7, 'o2.abc should be 7, overriding o1')
assert(o1.abc == 3, 'o1.abc should be 3, unaffected by o2 setter')
function o1:test(bar)
return self.abc + bar
end
assert(type(o1.test) == 'function', 'o1.test should be a function')
assert(type(o2.test) == 'function', 'o2.test should be a function, inherited from o1')
assert(o1.test(5) == 8, 'o1.test(5) should return 3 + 5 = 8')
assert(o2.test(11) == 18, 'o2.test(11) should return 7 + 11 = 18')
function o2:test2(fn)
return self.abc + fn(7)
end
assert(o2.test2(o1.test) == 17, 'o2.test2(o1.test) should return 7 + (3 + 7) = 17')
o2.test3 = o1._slots.test -- proper function copying
assert(o2.test3(11) == 18, 'o2.test3(5) should return 7 + 11 = 18')
o2.abc = nil
assert(o2.abc == 3, 'o2.abc should be 3 again, inherited from o1 after clearing')
o2.abc = false
assert(o2.abc == false, 'o2.abc should be false, __index needs to differentiate between nil and false')
This metatable will provide you with what you want, with inherited and bound functions to boot. You will just need to make sure that all of the tables that you want to follow this pattern also follow the method of object creation shown in the example code.
To explain, each table made in this way has any new assignment redirected into the _slots sub-table and any new retrieval checked up the _parent inheritance tree. If the type of the value is a function, then it returns a new closure with the original self that started the check bound to the function found.
Obviously, calling a function from one of these objects with the : colon syntax is going to be a silly idea, since it would evaluate to o.fn(o, o), and that is probably not what you want. Another caveat is that copying functions onto these objects, from these objects, will not work as expected. o1.newfn = o2.fn will put an o2 bound function into o1, which in turn will be re-bound to o1. The end result would be something like o2.fn(o2, o1). You will have to copy functions from the _slots table.
In conclusion: Even though this works, I would not personally recommend it in the long run, since it may be confusing to anyone used to how Lua works with tables, indexing, and functions, and there will be overhead. You might be able to do away with some it via memoizing the closures, but I'll leave that decision up to you. Good luck!
Object method declared with : needs object instance as the first parameter. It gets added automatically if you call it with :, but as you passed just a function pointer, you need to pass this as well. This means whenever you pass a function in some object somewhere, you also have to pass object instance. This works:
local a = {}
function a:test1(value)
print(value)
end
local b = {}
function b:test2(obj, v2)
v2(obj, 100); -- object instance is always the first param of a ":"-style func
end
b:test2(a, a.test1) -- passing object instance and a function
Building on #ryan-stein's neat bind() solution, in a module I've found this to be slightly more concise:
local m = {}
m.__index = m
m.word = 'bar'
function m:bind(fn)
return function(...) return self[fn](self, ...) end
end
function m:foo(fn)
print("Foo " .. self.word)
end
function m:start()
hs.timer.new(42, self:bind('foo'))
end
your code will be work. the reason Ryan has said.
I doubt that in the function anotherObject:aFunction(), you were using a wrong way to call the object.stuff.The correct way as this:
local a = {}
function a:test1()
print(1)
end
local b = {}
function b:test2(v1, v2)
v2();
end
b:test2(_, a.test1)
I read this documentation page about how to invoke superclass constructor from a child class. The syntax they mention is this:
obj = obj#MySuperClass(SuperClassArguments);
I'm wondering what the purpose of # symbol in the above syntax is. Is the # symbol just a meaningless place occupier in the syntax or does the # symbol represent the function handle symbol in MATLAB?
If I use:
obj = MySuperClass(SuperClassArguments);
instead of
obj = obj#MySuperClass(SuperClassArguments);
it still works fine. So what is the purpose of using # symbol?
1) no this has nothing to do with function handles, this is the syntax used to call the superclass constructor
2) you could try it and see for yourself. Here is an example:
A.m
classdef A < handle
properties
a = 1
end
methods
function obj = A()
disp('A ctor')
end
end
end
B.m
classdef B < A
properties
b = 2
end
methods
function obj = B()
obj = obj#A(); %# correct way
%#obj = A(); %# wrong way
disp('B ctor')
end
end
end
With the correct syntax, we get:
>> b = B()
A ctor
B ctor
b =
B with properties:
b: 2
a: 1
If you use the commented line instead of the first one, you get the following error:
>> clear classes
>> b = B()
A ctor
A ctor
B ctor
When constructing an instance of class 'B', the constructor must preserve the class of the returned
object.
Error in B (line 8)
disp('B ctor')
I want to implement a method dim(x,y) which will assign spaces for a matrix(y rows, x cols).
I want to make "dim(x,y)" more powerful by passing an optional function 'filler' to it and then 'dim' will set the element located at (x,y) to filler(x,y)
my code goes as below:
List2D dim := method(x, y, z,
target := list()
filler := if(z == nil,
method(return nil),
z)
for(i, 1, y,
subTarget := list()
for(j, 1, x,
subTarget append( filler(i,j) ))
target append(subTarget) )
return target)
it worked well when 'dim' is called with 2 arguments,
but failed with
List2D dim(3,2, method(x,y, 10*x+y))
which throwed an exception at line filler := if(z == nil
The exception said nil does not respond to '*'
I realized the argument 'z' got activated undesirably when comparing with nil.
So I'm wondering how to get my 'List2D dim' work properly?
Alright so basically, you'll want something like this:
List2D dim := method(x, y,
target := list
blk := call evalArgAt(2) # Get the third argument, and evaluate it in the context of the sender
if(blk isNil, blk := block setScope(call sender))
for(i, 1, y,
subTarget := list
for(j, 1, x,
subTarget append(blk call(i, j))
target append(subTarget)
)
)
target
)
Basically, what's going on here is since your filler, you want to give it arguments, the easiest method is just to pass in a Block. You can do this with messages, but you in effect, end up setting up your own duplicate of Block anyway if you introduce a new scope, which you should. If the third argument evaluates to nil, then we'll just create a new function and set its scope to the calling context; as if the user had passed in an empty function, which has no argument arty and as such, you can pass arguments to it even if it doesn't define any parameters. The fact we scope it to the caller isn't really needed, but you should always scope blocks to the calling context if you're creating the blocks inside your method call. This will give access to the lexical scope of the calling context inside that block; which you're probably shoving some message the user has supplied in it. When ready, just call that method explicitly using the call method.
If your filler method didn't require any arguments, I'd just grab the raw message argument at the 2nd index, instead of evaluating it. This would yield some major performance improvements for some large matrices.