[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: The good old string metatable
- From: Sean Conner <sean@...>
- Date: Thu, 21 Jul 2016 12:19:39 -0400
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!)