An Idea: Proxying

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

An Idea: Proxying

Stefan Ginsberg-2
I have an idea for Lua that I wish to share. It is called proxying, or envelopment of values, and is an extension to the Lua core adding a new type of value: proxy. The purpose of this value is to encapsulate other values, and it is implemented as such:

typedef struct Proxy {
  CommonHeader;
  TValue value;
  Table *metatable;
} Proxy;

The base library function 'envelop', using core lua_envelop, can be used to create a proxy by encapsulating a provided value through an associated metatable:

proxy = envelop(value, metatable)

This is similar to using an empty table with setmetatable, but the feature of "envelopment" means the proxied value is passed to metamethods instead of the proxy. This encapsulation works in the following way:

prx = envelop(val, meta)
val == self
prx(...) --> meta.__call(self, ...)
val = prx[idx] --> meta.__index(self, idx)
prx[idx] = val --> meta.__newindex(self, idx, val)

That is, 'val' and not 'prx' is passed to methods of 'meta'. An exception is garbage collection which will take the finalized proxy as its argument, to distinguish from the handling of the value. Another exception is '__metatable' which also applies to the proxy.

A proxy is a convenient value to use for interfacing, OOP, etc, and compared to using an empty table it is both more efficient and succinct than using closures to achieve the same goal.

Provided is a proof-of-concept implementation: https://pastebin.com/tR0L3kgw
Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Coda Highland
On Sun, Jan 26, 2020 at 6:00 AM Stefan Ginsberg <[hidden email]> wrote:
I have an idea for Lua that I wish to share. It is called proxying, or envelopment of values, and is an extension to the Lua core adding a new type of value: proxy.

It should be noted that the idea of a proxy already exists in Lua. See <https://www.lua.org/pil/13.4.4.html>. 

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Stefan Ginsberg-2
I choose to call it proxy because of the similarity. An alternative would have been "capsule", but the former is more fitting I believe for this kind of value.

On Mon, Jan 27, 2020 at 1:45 AM Coda Highland <[hidden email]> wrote:
On Sun, Jan 26, 2020 at 6:00 AM Stefan Ginsberg <[hidden email]> wrote:
I have an idea for Lua that I wish to share. It is called proxying, or envelopment of values, and is an extension to the Lua core adding a new type of value: proxy.

It should be noted that the idea of a proxy already exists in Lua. See <https://www.lua.org/pil/13.4.4.html>. 

/s/ Adam
Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Tim Hill
In reply to this post by Stefan Ginsberg-2


On Jan 26, 2020, at 3:59 AM, Stefan Ginsberg <[hidden email]> wrote:

I have an idea for Lua that I wish to share. It is called proxying, or envelopment of values, and is an extension to the Lua core adding a new type of value: proxy. The purpose of this value is to encapsulate other values, and it is implemented as such:

typedef struct Proxy {
  CommonHeader;
  TValue value;
  Table *metatable;
} Proxy;

The base library function 'envelop', using core lua_envelop, can be used to create a proxy by encapsulating a provided value through an associated metatable:

proxy = envelop(value, metatable)

This is similar to using an empty table with setmetatable, but the feature of "envelopment" means the proxied value is passed to metamethods instead of the proxy. This encapsulation works in the following way:

prx = envelop(val, meta)
val == self
prx(...) --> meta.__call(self, ...)
val = prx[idx] --> meta.__index(self, idx)
prx[idx] = val --> meta.__newindex(self, idx, val)

That is, 'val' and not 'prx' is passed to methods of 'meta'. An exception is garbage collection which will take the finalized proxy as its argument, to distinguish from the handling of the value. Another exception is '__metatable' which also applies to the proxy.

A proxy is a convenient value to use for interfacing, OOP, etc, and compared to using an empty table it is both more efficient and succinct than using closures to achieve the same goal.

Provided is a proof-of-concept implementation: https://pastebin.com/tR0L3kgw

What problem are you trying to solve here?

—Tm

Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Stefan Ginsberg-2
The problem (if one would call it that) is that using empty tables with closures is a bit inelegant in comparison.
This is an extension providing a new way to encapsulate values, and that is simply what it does.
If anything is solved it is the absence of a userdata-like value to Lua code (such as newproxy implemented).

On Tue, Jan 28, 2020 at 2:21 AM Tim Hill <[hidden email]> wrote:


On Jan 26, 2020, at 3:59 AM, Stefan Ginsberg <[hidden email]> wrote:

I have an idea for Lua that I wish to share. It is called proxying, or envelopment of values, and is an extension to the Lua core adding a new type of value: proxy. The purpose of this value is to encapsulate other values, and it is implemented as such:

typedef struct Proxy {
  CommonHeader;
  TValue value;
  Table *metatable;
} Proxy;

The base library function 'envelop', using core lua_envelop, can be used to create a proxy by encapsulating a provided value through an associated metatable:

proxy = envelop(value, metatable)

This is similar to using an empty table with setmetatable, but the feature of "envelopment" means the proxied value is passed to metamethods instead of the proxy. This encapsulation works in the following way:

prx = envelop(val, meta)
val == self
prx(...) --> meta.__call(self, ...)
val = prx[idx] --> meta.__index(self, idx)
prx[idx] = val --> meta.__newindex(self, idx, val)

That is, 'val' and not 'prx' is passed to methods of 'meta'. An exception is garbage collection which will take the finalized proxy as its argument, to distinguish from the handling of the value. Another exception is '__metatable' which also applies to the proxy.

A proxy is a convenient value to use for interfacing, OOP, etc, and compared to using an empty table it is both more efficient and succinct than using closures to achieve the same goal.

Provided is a proof-of-concept implementation: https://pastebin.com/tR0L3kgw

What problem are you trying to solve here?

—Tm

Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Griffin Rock
In reply to this post by Stefan Ginsberg-2
> The purpose of this value is to encapsulate other values
> similar to using an empty table with setmetatable ...
> the proxied value is passed to metamethods instead of the proxy
the implementation is shorter than the suggestion, and doesn't require any changes to the core language, let alone a new type.

local proxied,metatable = {},{} -- symbols to prevent namespace conflict
local Proxy = {} -- class
loop(function (meta)
  Proxy[meta] = function (self, ...)
    local method = self[metatable][meta]
    if method then return method(self[proxied], ...); end
  end
end) "__call" "__add" "__sub" "__mul" -- etc
function envelop (p,m)
  return setmetatable({[proxied]=p, [metatable]=m}, Proxy)
end

Reply | Threaded
Open this post in threaded view
|

Re: An Idea: Proxying

Griffin Rock
oops, I said:
> loop(function (meta) ...
but forgot the implementation of loop (though you probably guessed it):

function loop (f)
  local function g(...)
    f(...)
    return g
  end
  return g
end