In Lua documentation, calling :seek() on a file object is supposed to return how much data has been read through the file. However, when I call this method on stdin it does not return consistent numbers.
When I open terminal and run the Lua REPL and execute io.stdin:seek() I get random numbers. In one tab I might get:
Lua 5.2.0 Copyright (C) 1994-2011 Lua.org, PUC-Rio
> =io.stdin:seek()
2091
In another tab I could get instead:
Lua 5.2.0 Copyright (C) 1994-2011 Lua.org, PUC-Rio
> =io.stdin:seek()
486
What explains this behaviour whereby calling seek() on stdin returns a number that seems to have no relevance to how much input Lua has received?
And how else might I be able to retrieve how much data has been read through stdin?
Related
See the following example:
$ lua
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> local a = 123
> print(a)
nil
This works as expected:
> local a = 123; print(a)
123
How should I understand the behavior compared to the doc?
The scope of a local variable begins at the first statement after its declaration and lasts until the last non-void statement of the innermost block that includes the declaration.
In the Lua REPL, each (multi)line is loaded as an independent chunk via luaL_loadbuffer. The same system that makes require("mod_a") independent of require("mod_b").
Therefore, the quoted sentence still applies because every time the REPL prints a > (compared to a >> which denotes a multiline) a new block starts, thereby passing the boundary of "the last non-void statement of the innermost block".
Lua REPL treats each line of code as a separate chunk (as if it was a separate Lua file).
When a chunk execution is finished, all its local variables are lost.
So, only global variables are preserved between lines.
Lua REPL is just a REPL, it is not a debugger, where you would be able to watch and modify all variables while program is running.
To use local variables in a multi-line program in Lua REPL: start with do, enter multiple commands, and finally enter end to execute the program you entered.
$ lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> do
>> local a = 123
>> print(a)
>> end
123
>
Lua version is 5.1.4, here is the details:
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
print(string.format("where id = %d", "1596856742980208710"))
output:
where id = 1596856742980208640
But when changing %d to %s:
print(string.format("where id = %s", "1596856742980208710"))
output:
where id = 1596856742980208710
What does this mean?
This is a Lua "feature" called coercion: Lua will coerce strings to numbers if a number is expected and vice versa. Lua 5.1 by default uses doubles as only number type, which may lead to a loss of precision when coercing large numbers.
Consider your first example:
print(string.format("where id = %d", "1596856742980208710"))
%d obviously expects a number. The string "1596856742980208710" is thus coerced to a number; the code is equivalent to
print(string.format("where id = %d", tonumber"1596856742980208710"))
on newer Lua versions (5.3+), this would work just fine, since the number would be converted to a 64-bit signed integer:
$ lua
Lua 5.3.4 Copyright (C) 1994-2017 Lua.org, PUC-Rio
> tonumber"1596856742980208710"
1596856742980208710
Lua 5.1 does however not have an integer type; it will convert the number to a 64-bit double:
$ lua5.1
Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> =("%d"):format(tonumber"1596856742980208710")
1596856742980208640
as you can see, the number has changed. This is because of double precision issues: The maximum safe integer that can be stored in a double is 2^53 - 1 (see e.g. JS's MAX_SAFE_INTEGER). Your number significantly exceeds that: Compare 9.007199254741e+15 against 1596856742980208710. This leads to a loss of precision in the less significant decimal places. When the number is then formatted using %d, you get the incorrect result.
Your second example:
print(string.format("where id = %s", "1596856742980208710"))
obviously works, since it treats "1596856742980208710" as a string and doesn't coerce it to a number in the first place. It is thus equivalent to a string concatenation "where id = " .. "1596856742980208710" no matter the Lua version (as "1596856742980208710" doesn't contain NULL bytes).
When I start an interactive Lua shell, io.write() adds unwanted material after the string I want it to print. print(), however does not:
[user#manjaro lua]$ lua
Lua 5.4.2 Copyright (C) 1994-2020 Lua.org, PUC-Rio
> io.write('hello world')
hello worldfile (0x7fcc979d4520)
> print('hello world')
hello world
And when I use io.write() in a program it works fine too:
--hello.lua
io.write('hello world\n')
print ('hello world')
Output:
[user#manjaro lua]$ lua hello.lua
hello world
hello world
I'm using Manjaro Linux on a Dell desktop. Can anyone tell me what's going on here? Thanks in advance.
EDIT: I should add, perhaps, that the unwanted material is always something like this:
file (0x7f346234d520)
It's always 'file' followed by what looks like a large hexadecimal number in parentheses. The exact number stays constant within one shell session but varies between different shell sessions.
"file (0x7fcc979d4520)" (or whatever address) is the return value of the io.write call, with an implicit tostring.
The lua(1) man page says
In interactive mode, lua prompts the user, reads lines from the standard input, and executes them as they are read. If the line contains an expression or list of expressions, then the line is evaluated and the results are printed.
The trouble here is that io.write('hello world') could be either an expression or a statement. Since it's a valid expression, the interpreter outputs that unwanted return value.
As a workaround, try adding a semicolon:
> io.write('hello world\n');
hello world
Although Lua usually doesn't require a semicolon for each statement if it's at the end of a line, it does allow it. And important here, it means the syntax can't be an expression, only a statement which calls the function. So the interpreter won't output the returned value.
You are just seeing the return value of io.write when you call io.write manually, interactively. When using the Lua, uh, shell, if you want to call it that, it almost always prints the return value of any function(s) you call.
file(blabblah) is the internal representation of the file you are writing to (probably just a hex memory address, but who knows?)
http://www.lua.org/manual/5.1/manual.html#pdf-dofile tells
dofile ([filename])
Opens the named file and executes its contents as a Lua chunk. When called without arguments, dofile executes the contents of the standard input (stdin). Returns all values returned by the chunk. In case of errors, dofile propagates the error to its caller (that is, dofile does not run in protected mode).
How fill stdin from lua for case when called without arguments?
If you're running a lua script or the lua interpreter in interactive mode from a command shell, calling dofile() will just get input from stdin. You'll see a blinking cursor in the shell where you can enter the lua code you want to run.
Note, running dofile in this fashion is a blocking calling, which means execution flow in your script or the lua interpreter will pause until it reads eof. Usually this means you have to enter Ctrl + Z under windows or Ctrl + D under *nix bash shell at the end.
This is an example:
-bash-4.0$ ./lua
Lua 5.3.0 (alpha) Copyright (C) 1994-2014 Lua.org, PUC-Rio
> dofile()
a = 3; print(a)
3
>
After inputting a = 3; print(a), I pressed Ctrl + D, which represents EOF on Unix. dofile() loads the input and executes it.
I'm following a lua doc page on string splitting, get an error trying it myself. For example,
Lua 5.1.4 Copyright (C) 1994-2008 Lua.org, PUC-Rio
split("a,b,c", ",")
returns
stdin:1: attempt to call global 'split' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: ?
Why is this so?
That isn't a "lua doc page". It is a wiki article explaining the concept of splitting and joining strings, not any actual functions in Lua. The Lua documentation clearly states that there is no "split" function. The wiki article is explaining how to create such a function and/or how such a function might work.
The message is clear: you have tried to call a global function named split, but is not defined.