It was thus said that the Great Soni L. once stated:
Remember there were multiple threads about adding semantic meaning to
specific string objects, etc?
For example, say you want a date string, that acts like a string, but
has added methods: (using io.write here to indicate its stringness)
local date = Date.new("1/1/1970")
io.write(date, "\n") --> 1970-01-01-T00:00:00.000+00:00
date = date:add("10y")
io.write(date, "\n") --> 1980-01-01-T00:00:00.000+00:00
io.write(date:as("ISO 8601"), "\n") --> 1980-01-01-T00:00:00.000+00:00
local t = {}
t[date] = true
io.write(next(t), "\n") --> 1980-01-01-T00:00:00.000+00:00
The way to do this is to do this:
I see (I think) what you are trying to do, but if I were to implement
this, I would make a separate date "type" and write a __tostring() method
for it. So the only difference I would see is:
local date = Date.new("January 8, 1969")
io.write(tostring(date),"\n")
date = date + "10y" -- I mean, if you have a new type, go all out!
io.write(tostring(date),"\n")
local t = setmetatable({}, {__mode = "k"})
function Date.new(date, format)
local processedDate = getDateString(date, format)
t[processedDate] = {date_metadata_here}
return processedDate
end
function string:as(format)
if t[self] then
return convertDate(self, format)
else
error("Not a date object")
end
end
Now I'm confused. It appears as if Date.new() returns an actual string as
opposed to a userdata or table and that you have monkey patched the string
metatable to include the add() and as() methods. If that is the case, then
that's shortsighted. I use your Date module, and Dirk's (hypothetical)
string encoding module, where you can do:
io.write(header:as("quoted-printable"),value:as("base-64"),"\n")
And well ... your :as() and Dirk's (hypothetical) :as() don't mix. The
issue here is that strings all share a single metatable, so for your method
to work, that would have to change (and I do believe there was a discussion
about that (ah yes, http://lua-users.org/lists/lua-l/2015-05/msg00021.html).
However, this causes conflicts and interning issues and stuff. So let's
look at proposals to solve this:
There is a metamethod proposal that would make this better. Not perfect,
but way better. It's __key. It would provide a general-purpose solution
to this age-old problem:
local mt = {
__index = {}
__key = function(self) return self.date end
}
function Date.new(date, format)
local processedDate = getDateString(date, format)
return setmetatable({date=processedDate}, mt)
end
function mt.__index:as(format)
return convertDate(self, format)
end
I'm afraid I don't see how this is supposed to work. From the other
thread,
io.write(date)
won't trigger the __key metamethod because it's not being used as a key.
Unless you are now changing the semantics of __key. Perhaps a line-by-line
running commentary of not only the definition of your example, but use as
well is required.
-spc (Or here's a radical idea---try implementing it!)