Unexpected error using tostring

classic Classic list List threaded Threaded
24 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Unexpected error using tostring

Marcus Mason
function f() end
tostring(f()) --what happens here?
This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.

This is quite odd in terms of how the code looks, now consider the following function:
function transform(f)
return function(x, ...) return f(x, ...) end
end
This looks rather redundant, but transform(tostring)(f()) will not produce an error, which is perhaps even weirder.

Is this supposed to behave like this?
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Sean Conner
It was thus said that the Great Magicks M once stated:

> function f() end
> tostring(f()) --what happens here?
> This code causes an error, which I think is not obvious, with the message "bad
> argument #1 to 'tostring' (value expected)" I believe this is because the
> number of values returned by f is 0 which means the vararg passed into
> tostring has length 0.
>
> This is quite odd in terms of how the code looks, now consider the
> following function:
> function transform(f)
> return function(x, ...) return f(x, ...) end
> end
> This looks rather redundant, but transform(tostring)(f()) will not produce
> an error, which is perhaps even weirder.
>
> Is this supposed to behave like this?

  It could be related to this:

        print(tostring())
        print(tostring(nil))

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
In reply to this post by Marcus Mason
It has nothing to do with tostring specifically, it could happen with
any function. In Lua, you need a vararg function fct(...) to
dstinguish between fct() and fct(nil), but in the C API it is much
more obrusive. You can test for nil, or for nil-or-none, and in the
case of tostring, the authors feel that none does not has a string
equivalent, so it is an error.

Op Di. 5 Mrt. 2019 om 07:21 het Magicks M <[hidden email]> geskryf:

>
> function f() end
> tostring(f()) --what happens here?
> This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.
>
> This is quite odd in terms of how the code looks, now consider the following function:
> function transform(f)
> return function(x, ...) return f(x, ...) end
> end
> This looks rather redundant, but transform(tostring)(f()) will not produce an error, which is perhaps even weirder.
>
> Is this supposed to behave like this?

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Marcus Mason
I see. It's a bit annoying that implicit nil is not returned as "nil" given that no value is supposed to be represented by nil.

On Tue, 5 Mar 2019, 08:26 Dirk Laurie, <[hidden email]> wrote:
It has nothing to do with tostring specifically, it could happen with
any function. In Lua, you need a vararg function fct(...) to
dstinguish between fct() and fct(nil), but in the C API it is much
more obrusive. You can test for nil, or for nil-or-none, and in the
case of tostring, the authors feel that none does not has a string
equivalent, so it is an error.

Op Di. 5 Mrt. 2019 om 07:21 het Magicks M <[hidden email]> geskryf:
>
> function f() end
> tostring(f()) --what happens here?
> This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.
>
> This is quite odd in terms of how the code looks, now consider the following function:
> function transform(f)
> return function(x, ...) return f(x, ...) end
> end
> This looks rather redundant, but transform(tostring)(f()) will not produce an error, which is perhaps even weirder.
>
> Is this supposed to behave like this?

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
Op Di. 5 Mrt. 2019 om 11:02 het Magicks M <[hidden email]> geskryf:
>
> I see. It's a bit annoying that implicit nil is not returned as "nil" given that no value is supposed to be represented by nil

The Manual puts it less prescriptively: "it usually represents the
absence of a useful value."

You can very easily make tostring do what you want.

    local _tostring = tostring; tostring = function(s) return _tostring(s) end

Try it out for a week or so and decide whether you still prefer it.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Gé Weijers
In reply to this post by Marcus Mason
On Mon, Mar 4, 2019 at 9:11 PM Magicks M <[hidden email]> wrote:
function f() end
tostring(f()) --what happens here?
This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.


Even stranger: this works:

tostring( ( f() ) )

The extra parentheses adjust the number of return values of 'f' to be 1, introducing a nil value. 

-- 
--

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
Op Di. 5 Mrt. 2019 om 19:18 het Gé Weijers <[hidden email]> geskryf:

>
> On Mon, Mar 4, 2019 at 9:11 PM Magicks M <[hidden email]> wrote:
>>
>> function f() end
>> tostring(f()) --what happens here?
>> This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.
>>
>
> Even stranger: this works:
>
> tostring( ( f() ) )
>
> The extra parentheses adjust the number of return values of 'f' to be 1, introducing a nil value.

Not stranger! "Even better illustrating the inner logic of Lua, ..."
is more like it.

We have seen many posts on this list, including some by myself :-(
with the following scenario:

1. Think that you understand Lua.
2. Encounter something that does not fit in with the way you understand it.
3. Report "bug" or "error" on the list.

The solution to all of these is:

1. Read the manual.
2. Take into account what is elsewhere in the manual, not just the
place where you looked first.
3. Argue like a rabbi or a Jesuit to extract the finest possible nuamces.

And voilà! Everything is crystal clear, refined but malicious.

So I really like your example. It illustrates a fine point clearly.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Marcus Mason
 I think this will suffice for my needs.
function tostringx(...) return ... ~= nil and tostring(...) or select('#', ...) == 0 and "none" or "nil" end
And yes the seldom mentioned (expr) adjustment is also a solution (I find myself most often using this with gsub to drop that second return).
I guess my issue is really about preference, should a function that converts lua values to a readable form be to render the nothing value. (or maybe cynically it's fine to not give vararg related things enough love ;) ).

On Tue, Mar 5, 2019 at 5:34 PM Dirk Laurie <[hidden email]> wrote:
Op Di. 5 Mrt. 2019 om 19:18 het Gé Weijers <[hidden email]> geskryf:
>
> On Mon, Mar 4, 2019 at 9:11 PM Magicks M <[hidden email]> wrote:
>>
>> function f() end
>> tostring(f()) --what happens here?
>> This code causes an error, which I think is not obvious, with the message "bad argument #1 to 'tostring' (value expected)" I believe this is because the number of values returned by f is 0 which means the vararg passed into tostring has length 0.
>>
>
> Even stranger: this works:
>
> tostring( ( f() ) )
>
> The extra parentheses adjust the number of return values of 'f' to be 1, introducing a nil value.

Not stranger! "Even better illustrating the inner logic of Lua, ..."
is more like it.

We have seen many posts on this list, including some by myself :-(
with the following scenario:

1. Think that you understand Lua.
2. Encounter something that does not fit in with the way you understand it.
3. Report "bug" or "error" on the list.

The solution to all of these is:

1. Read the manual.
2. Take into account what is elsewhere in the manual, not just the
place where you looked first.
3. Argue like a rabbi or a Jesuit to extract the finest possible nuamces.

And voilà! Everything is crystal clear, refined but malicious.

So I really like your example. It illustrates a fine point clearly.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Andrew Starks-2
In reply to this post by Dirk Laurie-2


On 3/5/19, 11:34 AM, "[hidden email] on behalf of Dirk Laurie" <[hidden email] on behalf of [hidden email]> wrote:

    The solution to all of these is:
   
    1. Read the manual.
    2. Take into account what is elsewhere in the manual, not just the
    place where you looked first.
    3. Argue like a rabbi or a Jesuit to extract the finest possible nuamces.
   
    And voilà! Everything is crystal clear, refined but malicious.
   
    So I really like your example. It illustrates a fine point clearly.


Yes. This is important. It is not enough to read the manual like an American sitting in a Starbucks with half his brain in the Facebooks and Twitters.

The reference manual must be studied. Each word is carefully balanced against the others. Remove one, and whole sections of Lua evaporate into JavaScript. If you read something that says "usually" or "normally", the author is talking to you... he's teasing you... inviting you to find the exception...

Did Lua promise you something? Hmmm... probably not. Read again. Un-focus your eyes. Meditate. Breathe in the economy of words. Once you've held the whole Lua Reference Manual in your mind, the edges become its defining shape and everything else rings false...


;)

-Andrew
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Roberto Ierusalimschy
>     The solution to all of these is:
>    
>     1. Read the manual.
>     2. Take into account what is elsewhere in the manual, not just the
>     place where you looked first.
>     3. Argue like a rabbi or a Jesuit to extract the finest possible nuamces.
>    
>     And voilà! Everything is crystal clear, refined but malicious.
>    
>     So I really like your example. It illustrates a fine point clearly.
>
>
> Yes. This is important. It is not enough to read the manual like an American sitting in a Starbucks with half his brain in the Facebooks and Twitters.
>
> The reference manual must be studied. Each word is carefully balanced against the others. Remove one, and whole sections of Lua evaporate into JavaScript. If you read something that says "usually" or "normally", the author is talking to you... he's teasing you... inviting you to find the exception...
>
> Did Lua promise you something? Hmmm... probably not. Read again. Un-focus your eyes. Meditate. Breathe in the economy of words. Once you've held the whole Lua Reference Manual in your mind, the edges become its defining shape and everything else rings false...

Perfect! Maybe this is not always true yet, but it is our goal :-)

-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Petite Abeille
In reply to this post by Andrew Starks-2


> On Mar 5, 2019, at 18:59, Andrew Starks <[hidden email]> wrote:
>
> like an American

While on the subject of national stereotypes...

Dear United Kingdom... https://www.youtube.com/watch?v=C3oBDj5a3VE









Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

sur-behoffski
In reply to this post by Marcus Mason
G'day,

[Sorry about unthreaded post... I read via the digest...]

Section 2.2 of my 5.1 manual states:

         [...]

         There are 8 basic types in Lua: nil, boolean, number, string
         function, userdata, thread and table.

         Nil is the type of the value nil, whose main property is to be
         different from any other value; it usually represents the
         absence of a useful value.

         [...]

Typing in that portion of the manual by hand, I tend to feel that
there is tension between an "implicit nil" and an "explicit nil",
with "implicit nil" possibly being the best description for:

         tostring(f())

Another name for "implicit nil" might be "none", which links into the
discussion thread descriptions and the C API.  You could even split
"none" into two variants (the naming here is awkward, sorry):

         none-that-will-coerce-to-nil-upon-evaluation
         none-that-cannot-be-coerced-to-nil

My suspicion is that, with a help of a very careful author, the
description might be able to become clearer about these cases,
although this tends to run against the tendency (especially in the
first sections) to be terse, taut and economical with words --
describing essential properties, with meanings not mandated being
undefined.

Hope this helps,

sur-behoffski etc etc.


Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Egor Skriptunoff-2
On Thu, Mar 7, 2019 at 6:26 AM sur-behoffski wrote:

Section 2.2 of my 5.1 manual states:

         [...]

         There are 8 basic types in Lua: nil, boolean, number, string
         function, userdata, thread and table.

         Nil is the type of the value nil, whose main property is to be
         different from any other value; it usually represents the
         absence of a useful value.

         [...]

Typing in that portion of the manual by hand, I tend to feel that
there is tension between an "implicit nil" and an "explicit nil",
with "implicit nil" possibly being the best description for:

         tostring(f())

Another name for "implicit nil" might be "none", which links into the
discussion thread descriptions and the C API.  You could even split
"none" into two variants (the naming here is awkward, sorry):
In other words,
         none-that-will-coerce-to-nil-upon-evaluation
         none-that-cannot-be-coerced-to-nil


Exactly!
For some strange reason, Lua is not conceptually clear about nil.
Nil is defined as absence of value.
And this definition works well with Lua tables (all absent keys have value nil).
This definition works well also with multiple assignment in Lua.
But tuples in Lua are inconsistent with the definition of nil.
IMO, any tuple of values should be think of as padded by nils to infinity.
There should not be any difference between the following statements:
   return
   return nil
   return nil, nil
Neither in Lua, nor in C API a user should be able to distinguish between LUA_TNONE and LUA_TNIL.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
Op Do. 7 Mrt. 2019 om 07:49 het Egor Skriptunoff
<[hidden email]> geskryf:

>
> On Thu, Mar 7, 2019 at 6:26 AM sur-behoffski wrote:
>>
>>
>> Section 2.2 of my 5.1 manual states:
>>
>>          [...]
>>
>>          There are 8 basic types in Lua: nil, boolean, number, string
>>          function, userdata, thread and table.
>>
>>          Nil is the type of the value nil, whose main property is to be
>>          different from any other value; it usually represents the
>>          absence of a useful value.
>>
>>          [...]
>>
>> Typing in that portion of the manual by hand, I tend to feel that
>> there is tension between an "implicit nil" and an "explicit nil",
>> with "implicit nil" possibly being the best description for:
>>
>>          tostring(f())
>>
>> Another name for "implicit nil" might be "none", which links into the
>> discussion thread descriptions and the C API.  You could even split
>> "none" into two variants (the naming here is awkward, sorry):
>> In other words,
>>          none-that-will-coerce-to-nil-upon-evaluation
>>          none-that-cannot-be-coerced-to-nil
>>
>
> Exactly!
> For some strange reason, Lua is not conceptually clear about nil.
> Nil is defined as absence of value.
> And this definition works well with Lua tables (all absent keys have value nil).
> This definition works well also with multiple assignment in Lua.
> But tuples in Lua are inconsistent with the definition of nil.
> IMO, any tuple of values should be think of as padded by nils to infinity.
> There should not be any difference between the following statements:
>    return
>    return nil
>    return nil, nil
> Neither in Lua, nor in C API a user should be able to distinguish between LUA_TNONE and LUA_TNIL.

That would dictate policy. It's not the Lua way.

Instead, recommend that programmers should not lazily `return` when
they mean `return nil`.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
Op Do. 7 Mrt. 2019 om 07:57 het Dirk Laurie <[hidden email]> geskryf:
>
> Op Do. 7 Mrt. 2019 om 07:49 het Egor Skriptunoff
> <[hidden email]> geskryf:

> > For some strange reason, Lua is not conceptually clear about nil.

Lua is crystal clear abut nil. (Lua 5.4 work1 muddied the waters, but
work2 returned to orthodoxy.)

> > Nil is defined as absence of value.

It is not so defined.

It is defined as a value whose princlipal property is to be different
from every other value. Absence of value is just one application.
First return value when the second is an error object is another.

> > But tuples in Lua are inconsistent with the definition of nil.

Not so. On the contrary, tuples make it obvious that "absence of
value" is not the definition.

> > IMO, any tuple of values should be think of as padded by nils to infinity.

So select('#',...) might as well return math.huge?

> > Neither in Lua, nor in C API a user should be able to distinguish between LUA_TNONE and LUA_TNIL.

In the C API, LUA_TNONE means you have tried to read above the top of
the stack. It is totally necessary to know whether this has happened.
Must I explain why?

Occasionally it does not matter whether you went over the top or read
an acttual nil, and for that purpose the API has lua_isnoneornil. You
are in effect saying there should not be lua_isnil and lua_isnone too.

-- Dirk

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Marcus Mason
In reply to this post by Dirk Laurie-2
I'm not sure an intangible second class value to represent a concept is the lua way either. The only reason it exists is due to the way the C API retreives arguments from the stack. Without select, which is a C function, there would not even be a way to check this in lua. Eliminating it would arguably be more minimalistic? There's always been a discontinuity with arguments, a lua function which binds 1 argument to a parameter can be called with f() and f(nil) indistinguishably (without using C functions to check) which is not the case for C function calls.

On Thu, 7 Mar 2019, 06:31 Dirk Laurie, <[hidden email]> wrote:
Op Do. 7 Mrt. 2019 om 07:49 het Egor Skriptunoff
<[hidden email]> geskryf:
>
> On Thu, Mar 7, 2019 at 6:26 AM sur-behoffski wrote:
>>
>>
>> Section 2.2 of my 5.1 manual states:
>>
>>          [...]
>>
>>          There are 8 basic types in Lua: nil, boolean, number, string
>>          function, userdata, thread and table.
>>
>>          Nil is the type of the value nil, whose main property is to be
>>          different from any other value; it usually represents the
>>          absence of a useful value.
>>
>>          [...]
>>
>> Typing in that portion of the manual by hand, I tend to feel that
>> there is tension between an "implicit nil" and an "explicit nil",
>> with "implicit nil" possibly being the best description for:
>>
>>          tostring(f())
>>
>> Another name for "implicit nil" might be "none", which links into the
>> discussion thread descriptions and the C API.  You could even split
>> "none" into two variants (the naming here is awkward, sorry):
>> In other words,
>>          none-that-will-coerce-to-nil-upon-evaluation
>>          none-that-cannot-be-coerced-to-nil
>>
>
> Exactly!
> For some strange reason, Lua is not conceptually clear about nil.
> Nil is defined as absence of value.
> And this definition works well with Lua tables (all absent keys have value nil).
> This definition works well also with multiple assignment in Lua.
> But tuples in Lua are inconsistent with the definition of nil.
> IMO, any tuple of values should be think of as padded by nils to infinity.
> There should not be any difference between the following statements:
>    return
>    return nil
>    return nil, nil
> Neither in Lua, nor in C API a user should be able to distinguish between LUA_TNONE and LUA_TNIL.

That would dictate policy. It's not the Lua way.

Instead, recommend that programmers should not lazily `return` when
they mean `return nil`.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Dirk Laurie-2
Op Do. 7 Mrt. 2019 om 09:36 het Magicks M <[hidden email]> geskryf:
>
> I'm not sure an intangible second class value to represent a concept is the lua way either.

The phrase "intangible second class value" deserves a compliment. It
misleads the reader by taking for granterd that 'none' is a concept,
represented by some kind of value.  Actually T_NONE is just a name for
an integer constant in C. There is no concept 'none', let alone a
value of whatever class to rpresent it. It might as well have been
called "missing" or "absent".

Read the manual carefully. Carefully. Every bit of it. In particular, this part:

~~~~
lua_type

[-0, +0, –]

int lua_type (lua_State *L, int index);

Returns the type of the value in the given valid index, or LUA_TNONE
for a non-valid (but acceptable) index. The types returned by lua_type
are coded by the following constants defined in lua.h: LUA_TNIL (0),
LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION,
LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA.
~~~~

> The only reason it exists is due to the way the C API retreives arguments from the stack.

This statement is so vague that it is not even wrong.

T_NONE exists because Lua calls are allowed to provide any number of
arguments, and it is not a priori an error to provide fewer values
tnan the function woukl have been able to use.

It is not good enough just to say that missing arguments are nil. For
example, the library function table.insert, since
table.insert(tbl,key,nil) and table.insert(tbl,item) do different
things. You really need to know whether that third argument is
actually present.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Viacheslav Usov
In reply to this post by Marcus Mason
On Thu, Mar 7, 2019 at 8:26 AM Magicks M <[hidden email]> wrote:

> The only reason it exists is due to the way the C API retreives arguments from the stack. Without select, which is a C function, there would not even be a way to check this in lua. Eliminating it would arguably be more minimalistic? There's always been a discontinuity with arguments, a lua function which binds 1 argument to a parameter can be called with f() and f(nil) indistinguishably (without using C functions to check) which is not the case for C function calls.

This reminds of a similar discussion a couple of years ago where I said:

> I should say that the TNONE vs TNIL difference is very arcane and confusing. And this difference only exists for C functions, and one can make a C function conform with the documented behaviour (3.4.11), or not.

and

> Another problem is that your language above implies that we somehow must expect that setmetatable should behave like a "C function" and not a like a Lua function. Why? I do not think "because it is implemented in C is a sensible answer for someone who has no idea about the implementation of Lua. And why, indeed, should we expect that C functions behave differently? The difference is explained very compactly at the end of section 4.3, but it only makes sense for a C programmer, not for a Lua programmer (a pure Lua programmer would not even look there), who still sees there "virtual type LUA_TNONE, which behaves like a nil value". Does that imply that every user of Lua should understand the arcane details of Lua's C language API? I think that would be too much to expect.

It was a lengthy thread, too.

Cheers,
V.
Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Marcus Mason
In reply to this post by Dirk Laurie-2
I will try to elaborate on what I meant in my previous statement. 

The concept I am referring to is the absence of a value, I'm not using concept to talk about something discussed in the manual or defined by lua necessarily. Just an abstract idea.

I did not intend the phrase "intangible second class value" to be read as hyperbole, perhaps I owe an explanation to my wording. 

Let's look at a very simple function declaration: 
function f(x) 
   return  x
end

If I call it f()  what is x? The answer is nil, but this is the same when we call f(nil). When we are just considering a pure lua function there is no way to know how f was called. There is no lua value to represent the difference. This to me satifies the definition "unable to be touched; not having physical presence." (intangible). Second class because we have to go through the process of using select with a vararg.

It is not good enough just to say that missing arguments are nil.
 
I do agree with you here, I was simply suggesting that removing this "missing", such that we couldn't use a roundabout method to check, would be more in line with lua's design as a whole.
I would be in favour of a value in lua to distinguish the two cases and not actually removing it though. Either way a proper mechanism or none at all is what I think is needed.

On Thu, 7 Mar 2019, 14:31 Dirk Laurie, <[hidden email]> wrote:
Op Do. 7 Mrt. 2019 om 09:36 het Magicks M <[hidden email]> geskryf:
>
> I'm not sure an intangible second class value to represent a concept is the lua way either.

The phrase "intangible second class value" deserves a compliment. It
misleads the reader by taking for granterd that 'none' is a concept,
represented by some kind of value.  Actually T_NONE is just a name for
an integer constant in C. There is no concept 'none', let alone a
value of whatever class to rpresent it. It might as well have been
called "missing" or "absent".

Read the manual carefully. Carefully. Every bit of it. In particular, this part:

~~~~
lua_type

[-0, +0, –]

int lua_type (lua_State *L, int index);

Returns the type of the value in the given valid index, or LUA_TNONE
for a non-valid (but acceptable) index. The types returned by lua_type
are coded by the following constants defined in lua.h: LUA_TNIL (0),
LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE, LUA_TFUNCTION,
LUA_TUSERDATA, LUA_TTHREAD, and LUA_TLIGHTUSERDATA.
~~~~

> The only reason it exists is due to the way the C API retreives arguments from the stack.

This statement is so vague that it is not even wrong.

T_NONE exists because Lua calls are allowed to provide any number of
arguments, and it is not a priori an error to provide fewer values
tnan the function woukl have been able to use.

It is not good enough just to say that missing arguments are nil. For
example, the library function table.insert, since
table.insert(tbl,key,nil) and table.insert(tbl,item) do different
things. You really need to know whether that third argument is
actually present.

Reply | Threaded
Open this post in threaded view
|

Re: Unexpected error using tostring

Andrew Starks-2
Responses within....

From: "[hidden email]" <[hidden email]> on behalf of Magicks M <[hidden email]>

Let's look at a very simple function declaration: 
function f(x) 
   return  x
end

If I call it f()  what is x? The answer is nil, but this is the same when we call f(nil). When we are just considering a pure lua function there is no way to know how f was called. There is no lua value to represent the difference. This to me satifies the definition "unable to be touched; not having physical presence." (intangible). Second class because we have to go through the process of using select with a vararg.
-------

AS: The definition of `function f(x) end` means that there is one value, `x`. Because Lua adjusts the arguments to match the definition, filling in handy `nil` where you failed to provide a value, the value will always be `nil`. There is no ambiguity, unless you define f as `f(...)`, but even here, no ambiguity if you assign the first value of `...` to `x`:

```
function f(...)
    local x = ... --1 value will always be returned, regardless of the value of select('#', ...)
    return x
    -- return (...) -- gives you one value always, too.
end


```
----
> It is not good enough just to say that missing arguments are nil.

-----

AS: It has always been good enough for me, without exception. There are a few times when I was surprised by the way parts of the API worked with nil/one return value/no return value. Once I considered the design or had it explained, it made sense. I've never had anything that was hard to do because of the way Lua treats missing arguments and `nil`.
------------
<snip>

The concept that `nil` is bringing to our attention is Mu: (https://en.wikipedia.org/wiki/Mu_(negative))
Unknown. Neither true or false, just absent. Un. Outside of reason or cause.

I think the reason why this comes up repeatedly is because the concept of `nil` is hard for humans to grasp and probably harder to design into a language. You have to stop at some point and "some point" is never going to be completely satisfying.

When you try to describe `nil`, it comes into existence and needs to be represented. Representing something that represents the absence of anything results in a difference between modeled intent and reality and so you recursive pattern. Once you bring nothing into representable value, it's Turtles all the way down: https://en.wikipedia.org/wiki/Turtles_all_the_way_down

So, at some non-representation level, you have to be able to express whether the answer to your question was `nil` (how many of them you got), or no answer at all. That can't be a value of any kind, and so something like `select` is reasonable.

When trying to solve a pragmatic problem while programming in any language, it's easy to critique design choices like this one. How a language handles false and nil have a big impact on its design.

-Andrew




12