lua-users home
lua-l archive

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


It was thus said that the Great Daurnimator once stated:
> On 3 September 2018 at 02:51, Dirk Laurie <dirk.laurie@gmail.com> wrote:
> > BTW that library is a beautiful example of how to write C API code
> > that compiles on all Lua versions from 5.0 to 5.4 with only this
> > version-dependent test:
> >
> > #if (LUA_VERSION_NUM >= 502)
> > #define luaL_register(L,n,f)    luaL_newlib(L,f)
> > #endif
> 
> 
> I object: people should be writing against the newest lua version
> available at the time, and using the preprocessor to gain *backwards*
> compatibility.
> Defining *older* functions in terms of new ones (forwards
> compatibility) is in my opinion, an antipattern used for quicker
> porting.

  But there's still an issue.  Take the following hypthetical Lua 5.1 code:

	static luaL_Reg const m_foo_reg[] = { /* ... */ };

	int luaopen_foo(lua_State *L)
	{
	  luaL_register(L,"foo",m_foo_reg);
	  return 1;
	}

The semantics of Lua 5.1 include the creation of the global "foo".  If I go
ahead and do this:

	#if LUA_VERSION_NUM == 501
	#  define luaL_newlib(state,reg) luaL_register((state),NULL,(reg))
	#endif

	static luaL_Reg const m_foo_reg[] = { /* ... */ };

	int luaopen_foo(lua_State *L)
	{
	  luaL_newlib(L,m_foo_reg);
	  return 1;
	}

This can *break* code on Lua 5.1---the global "foo" is not created. Yes, I
could get around this [1]:

	#if (LUA_VERSION_NUM == 501)
	#  define luaL_newlib(state,reg) luaL_register((state),"foo",(reg))
	#endif

but I'm not happy with that solution for this particular case.  What I
normally do is:

	static luaL_Reg const m_foo_reg[] = { /* ... */ };

	int luaopen_foo(lua_State *L)
	{
	# if LUA_VERSION_NUM == 501
	  luaL_register(L,"foo",m_foo_reg);
	#else
	  luaL_newlib(L,m_foo_reg);
	#endif
	  return 1;
	}

which I'm not happy with either, but I think is "better" in that the name of
the module is closer to it's use than buried in a #define elsewhere.  Yes, I
could do the #define closer to this point, but that breaks my own coding
style.

  Another problematic pair of functions is lua_objlen() (Lua 5.1) and
luaL_len() (Lua 5.2+).  luaL_len() is *not* a direct replacement for
lua_objlen(), because one raises an error and one doesn't. 

  -spc 

[1]	As I did here:
	https://github.com/spc476/lua-conmanorg/blob/380c78b15d0211f794be5ff94daefc0fed30e333/src/tls.c#L48