lua-users home
lua-l archive

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


the missing love (from my part) is because the proposed isxxxxx() functions can be easily created on top of the most minimal required function to detect the difference of types.

Having read most of it I think my preference would be a ˋsubtype()ˋ function, that would honor an ˋ__subtypeˋ metamethod (and, optionally, in absence of ˋ__subtypeˋ would return the name of a metatable).

everything else can be easily built as an extension on top of this.

Thijs

sorry for top posting, on mobile...


Andrew Starks <andrew.starks@trms.com>schreef:


On Wed, Jul 24, 2013 at 1:45 AM, Philipp Janda <siffiejoe@gmx.net> wrote:
> Am 24.07.2013 06:41 schröbte Miles Bader:
>

<snip>
>
> How about a compromise:
>
> If called like this:
>
>     type( v )
>
> the `type` function returns one of the eight basic type names like it is
> now.
> If called with extra string arguments:
>
>     type( v, "integer" )
>
> it returns the first extra string argument that matches the type of the
> value, or nil if none matches.

I'm still not sure why `type.isfloat(x)` (etc) isn't getting any love,
but this works too and as you point out...
>
> This way we can use it as predicate for overlapping types:
>
>    if type( v, "float" ) then ... end
>
> and still dispatch on the type:
>
>    callbacks[ type( v ) ]( x, y, z )
>
> and even combine those two methods:
>
>    callbacks[ type( v, "callable", "indexable" ) or type( v ) ]( x, y, z )

... has the advantage of being able to check it against multiple type
properties.

>
> But I think the reason to introduce type predicates (virtual types such as
> "callable") is a reason to *not* use them for the integer/float distinction:
> there may be other objects that implement float-like or integer-like
> interfaces, and we would still have the same problem as with functions and
> is_callable ...
>
> IMHO, virtual types would be better handled with something like:
>
>    has"__index,__newindex,__len,__ipairs"( v )    --> array-like type or
> table
>    has"__call"( f )   --> callable type or function
>
> with some additional logic to handle the predefined capabilities of numbers,
> strings, tables, and functions.
>
>>
>> -miles
>>
>
> Philipp


This all points to a larger conversation about Lua's type system, as
opposed to what one can slightly change/add in order to find out if a
number is a float.

Does Lua need facilities beyond a string name associated with a
value's basic (sometimes vague) type?

I think I'm saying mostly the same thing, but how about "interfaces",
which I think gets at "has" and answers most of what subtypes is
after.

Example: A number supports the float and integer interface.

Example: My object, with all of the arithmetic metamethods defined,
includes this field in its metatable:

mt.__interface = "number"


Now libraries that respect interfaces know that my object can be
treated as a number.

For multiple interfaces:

mt.__interface = {"ordinal", "string"}

I'm not sure how it could look, but one could imagine functions having
an interface that included supported arguments and expected return
values. I would imagine that this would not be in the language. It
would only be facilitated by this sort of thing.


-Andrew


On Wed, Jul 24, 2013 at 1:45 AM, Philipp Janda <siffiejoe@gmx.net> wrote:
> Am 24.07.2013 06:41 schröbte Miles Bader:
>
>> Thijs Schreijer <thijs@thijsschreijer.nl> writes:
>>>
>>> Then I would rather have a single type() function and replace its
>>> number' return value with the new types. Big incompatibility but the
>>> new integer division operator already is. Incompatible but clean.
>>
>>
>> Predicates are actually _more_ clean, and yet aren't incompatible
>> ("isnumber" and "isinteger"/"isfloat" can exist simultaneously).
>>
>> If you are worried about function namespace pollution (I'm not,
>> particularly, but ...), it's also possible to use a predicate-style
>> solution with a separate type namespace, e.g. "istype(OBJ, TYPE)",
>> where TYPE is 'number', 'float', 'table', etc.
>
>
> How about a compromise:
>
> If called like this:
>
>     type( v )
>
> the `type` function returns one of the eight basic type names like it is
> now.
> If called with extra string arguments:
>
>     type( v, "integer" )
>
> it returns the first extra string argument that matches the type of the
> value, or nil if none matches.
>
> This way we can use it as predicate for overlapping types:
>
>    if type( v, "float" ) then ... end
>
> and still dispatch on the type:
>
>    callbacks[ type( v ) ]( x, y, z )
>
> and even combine those two methods:
>
>    callbacks[ type( v, "callable", "indexable" ) or type( v ) ]( x, y, z )
>
> But I think the reason to introduce type predicates (virtual types such as
> "callable") is a reason to *not* use them for the integer/float distinction:
> there may be other objects that implement float-like or integer-like
> interfaces, and we would still have the same problem as with functions and
> is_callable ...
>
> IMHO, virtual types would be better handled with something like:
>
>    has"__index,__newindex,__len,__ipairs"( v )    --> array-like type or
> table
>    has"__call"( f )   --> callable type or function
>
> with some additional logic to handle the predefined capabilities of numbers,
> strings, tables, and functions.
>
>>
>> -miles
>>
>
> Philipp
>
>
>
>