Re: local 'in' syntax

  • From: "Soni L." <fakedme+lj@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Mon, 2 May 2016 11:47:53 -0300



On 02/05/16 09:51 AM, Laurent Deniau 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 ;-)
There is a way to use _ENV in a Lua 5.1- and LuaJIT-compatible way:

local _ENV = _ENV or (getfenv and getfenv()) or _G
_ENV.print(_ENV.string.format("%s %s", "a", "b"))
local x
do
  local _ENV = {print = _ENV.print, sformat = _ENV.string.format}
  x = function(s, ...)
    _ENV.print(_ENV.string.format(s, ...))
  end
end
x("%s %s", "a", "b")

This works on all Luas

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 ;<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 ;<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: