lua-users home
lua-l archive

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


On Apr 25, 2018, at 12:32 PM, Hisham <h@hisham.hm> wrote:
> 
> On 25 April 2018 at 16:31, Hisham <h@hisham.hm> wrote:
>> On 25 April 2018 at 05:06, Dirk Laurie <dirk.laurie@gmail.com> wrote:
>>> 
>>> How does your library compare with pure-Lua read-only tables?
>> 
>> This works:
>> 
>> T[tuple("foo", "bar")] = 123
>> assert(T[tuple("foo", "bar")] == T[tuple("foo", "bar")])
>> 
>>> https://www.lua.org/pil/13.4.5.html
>> 
>> This doesn't:
>> 
>> T[readonly{"foo", "bar"}] = 123
>> assert(T[readonly{"foo", "bar"}] == T[readonly{"foo", "bar"}])
> 
> Or rather, this particular assert will pass because nil == nil.
> 
> Make it:
> 
> assert(T[readonly{"foo", "bar"}] == 123)
> 
>> -- Hisham
> 

Yes, that's probably the biggest difference. Some other differences though:

* Instances are interned, so only one instance of a given immutable table exists at any point in time (which is how they can be used as keys)
* Instance interning also makes equality checks work in constant time, even for deeply nested immutable tables
* next(), pairs(), ipairs() and # all have reasonable behavior with immutable tables (#Tuple(1,2,3) == 3, vs. #readOnly({1,2,3}) == 0)
* You can store nil in tables, and it will be included in # and next/pairs/ipairs iteration. e.g.

	Tuple = Immutable()
	t = Tuple("a",nil,"b",nil)
	assert(#t == 4)
	for i,v in ipairs(t) do print(i,tostring(v)) end -- prints 1 a, 2 nil, 3 b, 4 nil
	Point = Immutable({"x","y"})
	p = Point(nil,4)
	assert(#p == 2)
	for k,v in pairs(p) do print(k,tostring(v)) end -- prints x nil, y 4
	for i,v in ipairs(p) do print(i,tostring(v)) end -- prints 1 nil, 2 4

* The return value of Immutable(...) is a lot like a class, which means that it can have its own methods and class variables (provided in the optional second argument), and two different types of immutable table will never compare as equal to each other. e.g.

	Foo = Immutable({"x", "y"}, {do_thing=function(self) print("I'm a Foo") end})
	Baz = Immutable({"x", "y"}, {do_thing=function(self) print("I'm a Baz") end})
	f, b = Foo(1,2), Baz(1,2)
	assert(f != b) -- Same values, different types
	f:do_thing() -- prints "I'm a Foo"
	b:do_thing() -- prints "I'm a Baz"

* You can only set the fields you specify when the class is created (if you don't specify fields, it defaults to Tuple-like behavior). e.g.

	Foo = Immutable({"x", "y"})
	assert(not pcall(function() Foo(1,2,3,4) end)) -- Can't create a Foo with any fields besides "x" and "y"

--
Bruce

Attachment: signature.asc
Description: Message signed with OpenPGP