Re: local 'in' syntax
- From: Laurent Deniau <Laurent.Deniau@xxxxxxx>
- To: "luajit@xxxxxxxxxxxxx" <luajit@xxxxxxxxxxxxx>
- Date: Wed, 4 May 2016 14:05:30 +0000
--
Laurent Deniau http://cern.ch/mad
Accelerators Beam Physics mad@xxxxxxx<mailto:mad@xxxxxxx>
CERN, CH-1211 Geneva 23 Tel: +41 (0) 22 767 4647
On 04 May 2016, at 03:12, Eric Man
<meric.au@xxxxxxxxx<mailto:meric.au@xxxxxxxxx>> wrote:
Following this thread, gave me the idea on how to implement this feature in
plain lua as a hack, so one can import like:
local exp, log, sin, cos, tan within (math, 5)
without having to use incompatible syntax.
https://gist.github.com/meric/1883adb92044b75237bb0b42a63d5ed4
I have not figured out how to phase the "5" out. It's used to figure out how
many local variables to be assigned.
With numbers, I find it even more dangerous than simple table field
specification in the RHS. To avoid that, I would go for a solution like below.
Best,
Laurent.
local getlocal, setlocal = debug.getlocal, debug.setlocal
local function from_err(k, msg)
local info = debug.getinfo(3)
io.stderr:write(string.format(
"%s:%s:%d: local variable '%s' %s in import block\n",
info.source:sub(2),info.name,info.currentline,k,msg))
os.exit()
end
local function from(t)
local i, ii = 1
while true do
local k, v = getlocal(2, i)
if k == "import" then ii, i, k = i, v or i+1 end
if k == nil then break end
i = i + 1
end
assert(ii, "'import' not found")
while true do
local k, v = getlocal(2, i)
if k == nil then break
elseif v ~= nil then from_err(k, "initialized")
elseif t[k] == nil then from_err(k, "not found")
end
setlocal(2, i, t[k])
i = i + 1
end
setlocal(2, ii, i)
end
local function test(val)
local import,
exp, log from (math)
local sub from (string)
local sin, cos, tan from (math)
assert(exp == math.exp)
assert(log == math.log)
assert(sin == math.sin)
assert(cos == math.cos)
assert(tan == math.tan)
return exp(val), tan(val)
end
local import,
asin, acos, atan from (math)
print(asin(1), atan(1), test(1))
On Wed, May 4, 2016 at 7:34 AM, Demi Obenour
<demetriobenour@xxxxxxxxx<mailto:demetriobenour@xxxxxxxxx>> wrote:
I like this idea a lot. It solves a really annoying problem.
On Mon, May 2, 2016 at 11:16 AM, Laurent Deniau
<Laurent.Deniau@xxxxxxx<mailto:Laurent.Deniau@xxxxxxx>> wrote:
On 02 May 2016, at 16:28, Elias Hogstvedt
<eliashogstvedt@xxxxxxxxx<mailto:eliashogstvedt@xxxxxxxxx>> wrote:
So you don’t use FFI nor JIT options, nor table.new or other useful features
part of LuaJIT? You don’t use _ENV in Lua PUC? Does it means that you will
stay with Lua 5.1 forever? (just to be provocative ;-)
I use these things but if I were to make a public lua module I would probably
check for the availability of ffi and other things. When you have difference in
syntax this becomes difficult. This change wouldn't break anything existing and
I probably wouldn't mind if lua had this syntax really. I just wanted to point
out the slippery slope (from your previous lambda patch) here.
Which is a good thing IMHO… Globals are error prone, except for very well
established names.
People choose their own variable names and so you often have to go to the top
of the file to see what the function originally is. It's very clear what
table.insert is but it's not immediately clear what tinsert, insert, add, push,
ti, etc is. It also breaks syntax highlighting if you use that.
Right, that is why I will not implement the ‘as’ of Python...
And I never said that it should be part of the trunk, I provide the patches
for who might be interested. Most users don’t even compile LuaJIT or Lua,
they just use the default downloaded version.
And it probably sounds like I think you want these to be part of the trunk. I
just like discussing. :)
I propose, people dispose…
For example, I will not propose my next patch as it is more related to math
specific applications and it changes the semantic of Lua for one very special
case of coercion that I dislike… Since I disagree with this semantic, I will
change it in my application…
Best,
Laurent.
On Mon, May 2, 2016 at 2:51 PM, Laurent Deniau
<Laurent.Deniau@xxxxxxx<
mailto:Laurent.Deniau@xxxxxxx>> wrote:
On 02 May 2016, at 13:37, Elias Hogstvedt
<eliashogstvedt@xxxxxxxxx<
mailto:eliashogstvedt@xxxxxxxxx>> wrote:
Syntactically backwards compatible.
So you don’t use FFI nor JIT options, nor table.new or other useful features
part of LuaJIT? You don’t use _ENV in Lua PUC? Does it means that you will stay
with Lua 5.1 forever? (just to be provocative ;-)
If you're writing a lua module with your syntax it would only work in that
specific version of lua (as I'm sure you know). I'm interested in the idea of
moving away from lua syntax but then it should be a clear distinction and it
shouldn't be called lua anymore. One of the reasons I like lua is because it
has a very simple syntax that's easy to understand.
This localize thing isn't very on topic here but you've proposed a change in
syntax to make this problem easier to deal with.
you can see it as a missing feature of Lua, that many other programming
languages have. For example in Python it is the ‘from' qualifier of an
‘import'. The fact that modules are tables in Lua makes this feature even more
generic and useful, e.g. to extract component from tables to enhance
readability:
local x, y, z in vec
— here are lengthy expressions with x, y, z
instead of
local x, y, z = vec.x, vec,y, vec.z — easy to swap .x and .y by mistake in LHS
vs. RHS.
— here are lengthy expressions with x, y, z
My main issue with this localize everything mentality is that it makes globals
useless.
Which is a good thing IMHO… Globals are error prone, except for very well
established names.
When should we use globals? Would you localize math functions if luajit
optimized accessing globals in a way that made it just as optimal?
Are you sure that math functions are globals? I would say that math is global,
but not the functions. And yes I prefer by far
local sin, cos, tan in math
— use sin, cos, … as I would in math code.
I prefer to close (in the CS meaning) as much as possible, so this feature
enforces also better design in your application.
It seems like a hack or a workaround to me.
I don't know much about jit and compilers but I would've thought if you used
math.sin in a function it would skip looking up _G and math for the sin
function and just use it directly unless _G or the math table changes which
would recompile the function. Is that a naive way of going about it?
In fact, optimisation is one concern, readability is more important for me. For
example I have actually statement like below to avoid my code looking like Java
with lengthy.dot.path.down.to.functions:
local gmath = require 'gmath'
local is_number, is_complex, is_scalar,
is_matrix, is_cmatrix, is_amatrix,
is_vector, , is_cvector, , is_avector,
real, imag, conj, ident, min,
abs, arg, exp, log, sqrt, proj,
sin, cos, tan, sinh, cosh, tanh,
asin, acos, atan, asinh, acosh, atanh,
unm, mod, pow, tostring =
gmath.is<
http://gmath.is/>_number, gmath.is<
http://gmath.is/>_complex,
gmath.is<
http://gmath.is/>_scalar,
gmath.is<
http://gmath.is/>_matrix, gmath.is<
http://gmath.is/>_cmatrix,
gmath.isa_matrix,
gmath.is<
http://gmath.is/>_vector, gmath.is<
http://gmath.is/>_cvector,
gmath.is<
http://gmath.is/>_avector,
gmath.real, gmath.imag, gmath.conj, gmath.ident, gmath.min,
gmath.abs, gmath.arg, gmath.exp, gmath.log, gmath.sqrt, gmath.proj,
gmath.sin, gmath.cos, gmath.tan, gmath.sinh, gmath.cosh, gmath.tanh,
gmath.asin, gmath.acos, gmath.atan, gmath.asinh, gmath.acosh, gmath.atanh,
gmath.unm, gmath.mod, gmath.pow, gmath.tostring
will be soon converted to:
local is_number, is_complex, is_scalar,
is_matrix, is_cmatrix, is_amatrix, is_vector, , is_cvector, , is_avector,
real, imag, conj, ident, min, abs, arg, exp, log, sqrt, proj,
sin, cos, tan, sinh, cosh, tanh, asin, acos, atan, asinh, acosh, atanh,
unm, mod, pow, tostring in require ‘gmath'
The big difference, is if I need to add one more function from the gmath
module, I don’t need to carefully check the shift in LHS vs. RHS, nor wrap the
lines on the LHS according the length of the (longer) lines on the RHS...
As I said, I like when a language is minimal like Lua, but in some cases (e.g.
DSL) expressive power and readability matter. What is important, is that
syntactic extensions do not affect the semantic of the language which is
already very complete. Modifying the semantic must be done with care! And I
never said that it should be part of the trunk, I provide the patches for who
might be interested. Most users don’t even compile LuaJIT or Lua, they just use
the default downloaded version.
Best,
Laurent.
On Mon, May 2, 2016 at 12:38 PM, Laurent Deniau
<Laurent.Deniau@xxxxxxx<
mailto:Laurent.Deniau@xxxxxxx>> wrote:
On 01 May 2016, at 12:35, Elias Hogstvedt
<eliashogstvedt@xxxxxxxxx<
mailto:eliashogstvedt@xxxxxxxxx>> wrote:
As you've probably noticed lua users aren't too keen on modifying the Lua
syntax. I personally like seeing efforts like this because I think it's
interesting but I would never use it myself. Being compatible with Lua
syntactically is something I think is important.
LuaJIT is already not compatible with Lua 5.2 and 5.3. so it’s a fake argument
unless you stick to 5.1 + few extensions.
On the other hand this whole "local sin = math.sin" thing is annoying to both
read and write.
Not only, now that the patch is supporting expr on the RHS, it also allows to
simplify your module design, i.e. they can return array of values without any
loss of clarity on the user side. I have many cases like this where I was
creating “fake” modules to return single value (i.e. constructors) belonging
internally to the same module:
local vector = require “vector" — returns xmatrix.vector, load matrix first
local cvector = require “cvector" — returns xmatrix.cvector, load matrix first
local matrix = require “matrix” — returns xmatrix.matrix
local cmatrix = require “cmatrix” — returns xmatrix.cmatrix, load matrix first
with all the intricacy to load in the right order the requirements (e.g. matrix
module itself). With local ‘in’ syntax, I just need a single module
local matrix in require “matrix” — ok and simple
local vector, cvector, matrix, cmatrix in require “matrix” — ok and simple,
same syntax...
So for me, it is not convenient and less error prone, it also affects
(simplify) the way you organise your module. I would not spend my time to add
only syntactic sugar, unless it has a deep impact on software design. This is
the case for the two patches I recently proposed. And I don’t have any other
need in mind about syntax. Maybe in the coming year I will give a try to
compile FNEW when there is no upvalue (to allow better optimisation of local
use of lambda) or extend the sink optimisation to a bit bigger size (e.g. 512
bytes) and small VLA , but it’s a rather harder thing and I have no idea how to
do it.
I don't wanna do it in my own code unless it shows actual performance
benefits from a user point of view. Especially when I think this can be
automated through preprocessing. (replace all instances of math.sin with
math_sin and add local math_sin = math.sin on top of the script)
I'll probably experiment with this now. I haven't tried this local thing that
much but the times I did I don't remember seeing any performance benefits.
However looking up something in _G that is nil seems especially slow.
Best,
Laurent.
--
Laurent Deniau
http://cern.ch/mad
Accelerators Beam Physics mad@xxxxxxx<
mailto:mad@xxxxxxx>
CERN, CH-1211 Geneva 23 Tel: +41 (0) 22 767
4647<tel:%2B41%20%280%29%2022%20767%204647>
On Sat, Apr 30, 2016 at 8:33 PM, Laurent Deniau
<Laurent.Deniau@xxxxxxx<
mailto:Laurent.Deniau@xxxxxxx>> wrote:
On 30 Apr 2016, at 20:30, Laurent Deniau
<Laurent.Deniau@xxxxxxx<
mailto:Laurent.Deniau@xxxxxxx>> wrote:
Dear All,
I have extended the parser of LuaJIT to support the local ‘in’ table notation
in Lua. This extension is particularly useful for LuaJIT considering the
frequent needs to have local copy for performance reason. The patch is very
minimal and simple and extends the parser with only 13 lines.
The syntax extension allows to write:
local exp, log, sin, cos, tan in math
in place of:
local exp, log, sin, cos, tan in math.exp, math.log, math.sin, math.cos,
math.tan
I wanted to mean =
local exp, log, sin, cos, tan = math.exp, math.log, math.sin, math.cos, math.tan
and avoid mismatch between variables and fields.
The patch is activated by
XCFLAGS+= -DLUAJIT_LOCAL_INTABLE
in Makefile, and it can be found here:
https://github.com/MethodicalAcceleratorDesign/MAD/blob/master/lib/patches/lj_intable.patch
Best,
Laurent.
--
Laurent Deniau
http://cern.ch/mad
Accelerators Beam Physics mad@xxxxxxx<
mailto:mad@xxxxxxx>
CERN, CH-1211 Geneva 23 Tel: +41 (0) 22 767
4647<tel:%2B41%20%280%29%2022%20767%204647>
Other related posts: