lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]




On 21/07/16 01:19 PM, Sean Conner wrote:
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!)


Oh. Oops. I was originally gonna talk about __arg but I removed it and forgot to change io.write back into print.

--
Disclaimer: these emails may be made public at any given time, with or without reason. If you don't agree with this, DO NOT REPLY.