A tricky way to determine Lua version

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

A tricky way to determine Lua version

Egor Skriptunoff-2
Hi!

I want to share simple program that determines Lua version.

local f, t = function()return function()end end, {nil,
   [false]  = 'Lua 5.1',
   [true]   = 'Lua 5.2',
   [1/'-0'] = 'Lua 5.3',
   [1]      = 'LuaJIT' }
local version = t[1] or t[1/0] or t[f()==f()]


The curious fact about this program is that it doesn't depend on anything
that can be changed.
It does not use any standard library function or any global variable
(as they may be withdrawn from sandboxed environment).
It does not rely on the name of "_ENV" upvalue
(as it can be renamed when Lua is being built).

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

Re: A tricky way to determine Lua version

Ulrich Schmidt


Am 21.05.2016 um 07:18 schrieb Egor Skriptunoff:
> I want to share simple program that determines Lua version.
>
> local f, t = function()return function()end end, {nil,
>    [false]  = 'Lua 5.1',
>    [true]   = 'Lua 5.2',
>    [1/'-0'] = 'Lua 5.3',
>    [1]      = 'LuaJIT' }
> local version = t[1] or t[1/0] or t[f()==f()]

I like it. Its a nice pice of code. Thank you for sharing this. :)

> -- Egor

Ulrich

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Sean Conner
In reply to this post by Egor Skriptunoff-2
It was thus said that the Great Egor Skriptunoff once stated:

> Hi!
>
> I want to share simple program that determines Lua version.
>
> local f, t = function()return function()end end, {nil,
>    [false]  = 'Lua 5.1',
>    [true]   = 'Lua 5.2',
>    [1/'-0'] = 'Lua 5.3',
>    [1]      = 'LuaJIT' }
> local version = t[1] or t[1/0] or t[f()==f()]

  Nice.  

  I couldn't resist writing my own version.  

local version = ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
        ("").dump(function() end):sub(5,5)]

  Mine relies upon strings still having a metatable.

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Vadim A. Misbakh-Soloviov
>   Mine relies upon strings still having a metatable.
But lacks luajit ;)

--
wbr,
mva

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Sean Conner
It was thus said that the Great Vadim A. Misbakh-Soloviov once stated:
> >   Mine relies upon strings still having a metatable.
> But lacks luajit ;)

  Nah.  If version is nil, it's LuaJIT.

  -spc (nil can't be a table key, see ... )


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Ulrich Schmidt

Am 21.05.2016 um 09:13 schrieb Sean Conner:
> It was thus said that the Great Vadim A. Misbakh-Soloviov once stated:
>>>   Mine relies upon strings still having a metatable.
>> But lacks luajit ;)
>
>   Nah.  If version is nil, it's LuaJIT.
>
>   -spc (nil can't be a table key, see ... )

Thats all true. I still like Egors version because it is simple to use.
(without nil tests.) and the results can be changed eg.

function needs_setfenv()
   local f, t = function() return function() end end, {nil,
      [false]  = true,  --'5.1',
      [true]   = false, --'5.2',
      [1/'-0'] = false, --'5.3',
      [1]      = true,  --'JIT'
      }
   return t[1] or t[1/0] or t[f()==f()];
end;


Ulrich

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Satoru Kawahara
In reply to this post by Vadim A. Misbakh-Soloviov
How about?

local version = setmetatable({nil, [1] = "LuaJIT"}, {__index = {"Lua 5." .. string.dump(function()end):byte(5, 5) % 16}})[1]

On Sat, May 21, 2016 at 3:53 PM, Vadim A. Misbakh-Soloviov <[hidden email]> wrote:
>   Mine relies upon strings still having a metatable.
But lacks luajit ;)

--
wbr,
mva




--
Kawahara Satoru
College of Information Science
University of Tsukuba
Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Sean Conner
In reply to this post by Ulrich Schmidt
It was thus said that the Great Ulrich Schmidt once stated:

>
> Am 21.05.2016 um 09:13 schrieb Sean Conner:
> >It was thus said that the Great Vadim A. Misbakh-Soloviov once stated:
> >>>  Mine relies upon strings still having a metatable.
> >>But lacks luajit ;)
> >
> >  Nah.  If version is nil, it's LuaJIT.
> >
> >  -spc (nil can't be a table key, see ... )
>
> Thats all true. I still like Egors version because it is simple to use.
> (without nil tests.) and the results can be changed eg.
>
> function needs_setfenv()
>   local f, t = function() return function() end end, {nil,
>      [false]  = true,  --'5.1',
>      [true]   = false, --'5.2',
>      [1/'-0'] = false, --'5.3',
>      [1]      = true,  --'JIT'
>      }
>   return t[1] or t[1/0] or t[f()==f()];
> end;

  Hmm ... okay, how about:

local version = ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
        ("").dump(function() end):sub(5,5)] or "LuaJIT"

And you can change it just as easily:

local version = ({Q=true,R=false,S=false})[
        ("").dump(function() end):sub(5,5)] or true

  -spc (Okay, so a few comments might be nice ... 8-)


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Jonathan Goble
On Sat, May 21, 2016 at 3:42 AM, Sean Conner <[hidden email]> wrote:

> It was thus said that the Great Ulrich Schmidt once stated:
>>
>> Am 21.05.2016 um 09:13 schrieb Sean Conner:
>> >It was thus said that the Great Vadim A. Misbakh-Soloviov once stated:
>> >>>  Mine relies upon strings still having a metatable.
>> >>But lacks luajit ;)
>> >
>> >  Nah.  If version is nil, it's LuaJIT.
>> >
>> >  -spc (nil can't be a table key, see ... )
>>
>> Thats all true. I still like Egors version because it is simple to use.
>> (without nil tests.) and the results can be changed eg.
>>
>> function needs_setfenv()
>>   local f, t = function() return function() end end, {nil,
>>      [false]  = true,  --'5.1',
>>      [true]   = false, --'5.2',
>>      [1/'-0'] = false, --'5.3',
>>      [1]      = true,  --'JIT'
>>      }
>>   return t[1] or t[1/0] or t[f()==f()];
>> end;
>
>   Hmm ... okay, how about:
>
> local version = ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
>         ("").dump(function() end):sub(5,5)] or "LuaJIT"
>
> And you can change it just as easily:
>
> local version = ({Q=true,R=false,S=false})[
>         ("").dump(function() end):sub(5,5)] or true
>
>   -spc (Okay, so a few comments might be nice ... 8-)

After looking at the suggestions in this thread and experimenting with
a few of them, I like the version by Egor in the OP the best. Why?
Because unlike the other suggestions, it works without any environment
at all.

That means that a rock requiring different dependencies depending on
version (such as one requiring a third-party bitwise operations
library on 5.1 but using the native bitwise stuff on 5.2 and later)
should be able to use that test in the rockspec (which luarocks
executes in a completely empty environment) to adjust dependencies on
the fly during installation based on the Lua version it's running
through. That would not be possible with any of the other methods
proposed, because they rely on the standard libraries.

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Sean Conner
It was thus said that the Great Jonathan Goble once stated:

> On Sat, May 21, 2016 at 3:42 AM, Sean Conner <[hidden email]> wrote:
> >>
> >   Hmm ... okay, how about:
> >
> > local version = ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
> >         ("").dump(function() end):sub(5,5)] or "LuaJIT"
> >
> > And you can change it just as easily:
> >
> > local version = ({Q=true,R=false,S=false})[
> >         ("").dump(function() end):sub(5,5)] or true
> >
> >   -spc (Okay, so a few comments might be nice ... 8-)
>
> After looking at the suggestions in this thread and experimenting with
> a few of them, I like the version by Egor in the OP the best. Why?
> Because unlike the other suggestions, it works without any environment
> at all.

[spc]lucy:/tmp>cat ex.lua
return ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
        ("").dump(function() end):sub(5,5)] or "LuaJIT"

[spc]lucy:/tmp>lua-51
Lua 5.1.5  Copyright (C) 1994-2012 Lua.org, PUC-Rio
> x = loadfile("ex.lua")
> setfenv(x,{})
> y = x()
> print(y)
Lua 5.1
>
[spc]lucy:/tmp>lua-53
Lua 5.3.2  Copyright (C) 1994-2015 Lua.org, PUC-Rio
> x = loadfile("ex.lua","t",{})
> y = x()
> print(y)
Lua 5.3
>

Unless luarocks removes the metatable from strings, my method still works.

  -spc (Will have to try this in a rockspec ... )

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Dirk Laurie-2
In reply to this post by Egor Skriptunoff-2
2016-05-21 7:18 GMT+02:00 Egor Skriptunoff <[hidden email]>:

> I want to share simple program that determines Lua version.
>
> local f, t = function()return function()end end, {nil,
>    [false]  = 'Lua 5.1',
>    [true]   = 'Lua 5.2',
>    [1/'-0'] = 'Lua 5.3',
>    [1]      = 'LuaJIT' }
> local version = t[1] or t[1/0] or t[f()==f()]
>
> The curious fact about this program is that it doesn't depend on anything
> that can be changed.
> It does not use any standard library function or any global variable
> (as they may be withdrawn from sandboxed environment).
> It does not rely on the name of "_ENV" upvalue
> (as it can be renamed when Lua is being built).

This program is worthy of a leading code golfer.

Just getting to understand why it works is an education by itself.

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Soni L.
In reply to this post by Sean Conner


On 21/05/16 04:42 AM, Sean Conner wrote:

> It was thus said that the Great Ulrich Schmidt once stated:
>> Am 21.05.2016 um 09:13 schrieb Sean Conner:
>>> It was thus said that the Great Vadim A. Misbakh-Soloviov once stated:
>>>>>   Mine relies upon strings still having a metatable.
>>>> But lacks luajit ;)
>>>   Nah.  If version is nil, it's LuaJIT.
>>>
>>>   -spc (nil can't be a table key, see ... )
>> Thats all true. I still like Egors version because it is simple to use.
>> (without nil tests.) and the results can be changed eg.
>>
>> function needs_setfenv()
>>    local f, t = function() return function() end end, {nil,
>>       [false]  = true,  --'5.1',
>>       [true]   = false, --'5.2',
>>       [1/'-0'] = false, --'5.3',
>>       [1]      = true,  --'JIT'
>>       }
>>    return t[1] or t[1/0] or t[f()==f()];
>> end;
>    Hmm ... okay, how about:
>
> local version = ({Q="Lua 5.1",R="Lua 5.2",S="Lua 5.3"})[
>          ("").dump(function() end):sub(5,5)] or "LuaJIT"
>
> And you can change it just as easily:
>
> local version = ({Q=true,R=false,S=false})[
>          ("").dump(function() end):sub(5,5)] or true
I'm not sure if that does what you think it does... (false or true = true)
>
>    -spc (Okay, so a few comments might be nice ... 8-)
>
>

--
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.


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Sean Conner
It was thus said that the Great Soni L. once stated:
> On 21/05/16 04:42 AM, Sean Conner wrote:
>
> >And you can change it just as easily:
> >
> >local version = ({Q=true,R=false,S=false})[
> >         ("").dump(function() end):sub(5,5)] or true
>
> I'm not sure if that does what you think it does... (false or true = true)

  Um ... yeah.  Oops.

  -spc


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Alexey Melnichuk-2
In reply to this post by Jonathan Goble
Здравствуйте, Jonathan.

Вы писали 21 мая 2016 г., 11:01:08:

> On Sat, May 21, 2016 at 3:42 AM, Sean Conner <[hidden email]> wrote:
>> It was thus said that the Great Ulrich Schmidt once stated:

> After looking at the suggestions in this thread and experimenting with
> a few of them, I like the version by Egor in the OP the best. Why?
> Because unlike the other suggestions, it works without any environment
> at all.

> That means that a rock requiring different dependencies depending on
> version (such as one requiring a third-party bitwise operations
> library on 5.1 but using the native bitwise stuff on 5.2 and later)
> should be able to use that test in the rockspec (which luarocks
> executes in a completely empty environment) to adjust dependencies on
> the fly during installation based on the Lua version it's running
> through. That would not be possible with any of the other methods
> proposed, because they rely on the standard libraries.

But  in real life it will not works ether :) I have different LuaRocks
for  each  Lua  version.  But  all LuaRocks  runs using Lua 5.1. So version
in such case will be always `Lua 5.1`.



--
С уважением,
 Alexey                          mailto:[hidden email]


---
Это сообщение проверено на вирусы антивирусом Avast.
https://www.avast.com/antivirus


Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Egor Skriptunoff-2
In reply to this post by Egor Skriptunoff-2


On Sat, May 21, 2016 at 8:18 AM, Egor Skriptunoff wrote:

simple program that determines Lua version.

local f, t = function()return function()end end, {nil,
   [false]  = 'Lua 5.1',
   [true]   = 'Lua 5.2',
   [1/'-0'] = 'Lua 5.3',
   [1]      = 'LuaJIT' }
local version = t[1] or t[1/0] or t[f()==f()]


The curious fact about this program is that it doesn't depend on anything
that can be changed.


Here is an update of Lua version detector.
Support for 5.0 and 5.4 was added.
 
--[=[
local version = 'Lua 5.0'
--[[]=]
local n = '8'; repeat n = n*n until n == n*n
local t = {'Lua 5.1', nil,
  [-1/0] = 'Lua 5.2',
  [1/0]  = 'Lua 5.3',
  [2]    = 'LuaJIT'}
local version = t[2] or t[#'\z'] or t[n/'-0'] or 'Lua 5.4'
--]]

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

dyngeccetor8
On 06/28/2018 10:37 PM, Egor Skriptunoff wrote:

> On Sat, May 21, 2016 at 8:18 AM, Egor Skriptunoff wrote:
>
>>
>> simple program that determines Lua version.
>>
>> local f, t = function()return function()end end, {nil,
>>    [false]  = 'Lua 5.1',
>>    [true]   = 'Lua 5.2',
>>    [1/'-0'] = 'Lua 5.3',
>>    [1]      = 'LuaJIT' }
>> local version = t[1] or t[1/0] or t[f()==f()]
>>
>> The curious fact about this program is that it doesn't depend on anything
>> that can be changed.
>>
>
> Here is an update of Lua version detector.
> Support for 5.0 and 5.4 was added.
>
> --[=[
> local version = 'Lua 5.0'
> --[[]=]
> local n = '8'; repeat n = n*n until n == n*n
> local t = {'Lua 5.1', nil,
>   [-1/0] = 'Lua 5.2',
>   [1/0]  = 'Lua 5.3',
>   [2]    = 'LuaJIT'}
> local version = t[2] or t[#'\z'] or t[n/'-0'] or 'Lua 5.4'
> --]]

Kewl. Kudos.

-- Martin

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Coda Highland
In reply to this post by Egor Skriptunoff-2
On Thu, Jun 28, 2018 at 2:37 PM, Egor Skriptunoff
<[hidden email]> wrote:

>
>
> On Sat, May 21, 2016 at 8:18 AM, Egor Skriptunoff wrote:
>>
>>
>> simple program that determines Lua version.
>>
>> local f, t = function()return function()end end, {nil,
>>    [false]  = 'Lua 5.1',
>>    [true]   = 'Lua 5.2',
>>    [1/'-0'] = 'Lua 5.3',
>>    [1]      = 'LuaJIT' }
>> local version = t[1] or t[1/0] or t[f()==f()]
>>
>> The curious fact about this program is that it doesn't depend on anything
>> that can be changed.
>
>
>
> Here is an update of Lua version detector.
> Support for 5.0 and 5.4 was added.
>
> --[=[
> local version = 'Lua 5.0'
> --[[]=]
> local n = '8'; repeat n = n*n until n == n*n
> local t = {'Lua 5.1', nil,
>   [-1/0] = 'Lua 5.2',
>   [1/0]  = 'Lua 5.3',
>   [2]    = 'LuaJIT'}
> local version = t[2] or t[#'\z'] or t[n/'-0'] or 'Lua 5.4'
> --]]
>

Useful, but sadly this doesn't help distinguish between patch levels.

/s/ Adam

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Thijs Schreijer


> On 29 Jun 2018, at 01:58, Coda Highland <[hidden email]> wrote:
>
> On Thu, Jun 28, 2018 at 2:37 PM, Egor Skriptunoff
> <[hidden email]> wrote:
>>
>>
>> On Sat, May 21, 2016 at 8:18 AM, Egor Skriptunoff wrote:
>>>
>>>
>>> simple program that determines Lua version.
>>>
>>> local f, t = function()return function()end end, {nil,
>>>   [false]  = 'Lua 5.1',
>>>   [true]   = 'Lua 5.2',
>>>   [1/'-0'] = 'Lua 5.3',
>>>   [1]      = 'LuaJIT' }
>>> local version = t[1] or t[1/0] or t[f()==f()]
>>>
>>> The curious fact about this program is that it doesn't depend on anything
>>> that can be changed.
>>
>>
>>
>> Here is an update of Lua version detector.
>> Support for 5.0 and 5.4 was added.
>>
>> --[=[
>> local version = 'Lua 5.0'
>> --[[]=]
>> local n = '8'; repeat n = n*n until n == n*n
>> local t = {'Lua 5.1', nil,
>>  [-1/0] = 'Lua 5.2',
>>  [1/0]  = 'Lua 5.3',
>>  [2]    = 'LuaJIT'}
>> local version = t[2] or t[#'\z'] or t[n/'-0'] or 'Lua 5.4'
>> --]]
>>
>
> Useful, but sadly this doesn't help distinguish between patch levels.
>
> /s/ Adam
>

It also misses detection of LuaJIT’s 5.2 compatibility flag

Thijs
Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Pierre-Yves Gérardy
On Fri, Jun 29, 2018 at 12:32 PM, Thijs Schreijer
<[hidden email]> wrote:
> It also misses detection of LuaJIT’s 5.2 compatibility flag

Feature detection is sometimes more actionable than version detection.

Things like

    local supportsJIT = jit and jit.status() -- for efficient use of the FFI lib

    local supportsGoto = not not(loadstring or load)"::a::"

    local supportsTable__len =  not #setmetatable({},{__len = function()end})

—Pierre-Yves

Reply | Threaded
Open this post in threaded view
|

Re: A tricky way to determine Lua version

Dirk Laurie-2
2018-06-29 17:17 GMT+02:00 Pierre-Yves Gérardy <[hidden email]>:
> On Fri, Jun 29, 2018 at 12:32 PM, Thijs Schreijer
> <[hidden email]> wrote:
>> It also misses detection of LuaJIT’s 5.2 compatibility flag
>
> Feature detection is sometimes more actionable than version detection.

I love that word! Now I know Afrikaans got it from French!

In Afrikaans, "aksionabel" (in dialect spelt "aksenawel") means
"appropriate", "just right". Which I think is what you mean?

In English, it means "affording grounds for legal action".

12