Now that type namespaces are a thing, I think class types should be moved to a separate namespace. For example, you would use Instance.BasePart to define a type with the BasePart class, or Instance.Instance for any instance. Using “Instance” as the namespace creates a natural association with Instance.new.
In general, the following scenario can occur:
A module defines type X.
Subsequently, Roblox predefines type X (e.g. a new class was added).
The module cannot begin using predefined type X because it is shadowed by the self-defined type X.
The module cannot rename the self-defined type X without a major version change because other modules may depend on the exported type name.
New classes are added relatively often, so putting them in their own namespace eliminates this problem, at least for classes. Moreover, it reduces pollution of the top-level namespace.
It wasn’t, although it was added in 5.2 https://www.lua.org/manual/5.2/manual.html#6.4.1 https://www.lua.org/manual/5.1/manual.html#5.4.1
Some reasons for the features: \0 in patterns seems better than doing %z, would benefit utf8.charpattern as it uses %z and range [%z\x01-\x7F\xC2-\xF4][\x80-\xBF]* which if \0 were allowed in patterns could be simplified to [\x00-\x7F\xC2-\xF4][\x80-\xBF]*. %p format for whitelists/blacklists, currently to check if an instance is in a table a linear search must be done. With %p the table could be sorted once and then a binary search could be done to check if the instance is in the table. This can be done currently with tables assuming __tostring isn’t used, but all instances over ride __tostring so this isn’t possible.
local function udatasort(a,b)
return string.format("%p",a) < string.format("%p",b)
end
local function udatafind(tbl,finding)
-- binary search
local str = string.format("%p",finding)
local L = 1
local R = #tbl
while L <= R do
local M = math.floor((L+R)/2)
local strm = string.format("%p",tbl[M])
if strm < str then
L = M+1
elseif strm > str then
R = M-1
else
return M
end
end
return nil
end
local n = {}
local tbl = {}
tbl[1] = {}
tbl[2] = n
tbl[3] = {}
table.sort(tbl,udatasort)
print(tbl[udatafind(tbl,n)]==n)
A separator would be useful when you want something on every line, but no extra new line
Re: udatafind - you should be much better off with either table.find or filling a table with instances as keys and checking if the key is in that table. We’ll take a look at the other bits, %g/string.rep/string.gmatch seem straightforward at least.
table.find is O(n), while a binary search is O(log n). I think I will go with the route of filling the table and checking if the key is present, although wouldn’t this benefit from a hash length argument to table.create? Because it would fill in #tbl hash entries in the table, creating the table with a hash length of #tbl should avoid re allocating the table.
This is not a bug; we extended Lua number syntax with underscores, as it makes long numbers easier to read, for example 1_000_000. However, we don’t restrict the placement of underscores in any way - this is the standard approach taken by programming languages that have similar number literal support - so 1_0 is the same as 10 which is the same as 10__. Numbers can’t start with an underscore though - _10 is an identifier.
Could we get a notification for the change for the new Luau type checking syntax is out? (In script analysis saying the syntax changed.) I’m already using it in a game and it’d be helpful to know when the function syntax for returns is changed so I can update my code.
Also I’m currently having an issue with Luau type checking in the same game where I get these from script analysis today: (Wasn’t happening before today.) (Isn’t happening with just chat scripts, doesn’t show any syntax issues on my actual scripts either.)
I don’t know if the new type annotation syntax change have been rolled out, but the function type declaration seems to produce error while function definition does not.
--!strict
function test(foo: string): number
print(typeof(foo))
return #foo
end
print(test(1))
This is the output for the above code:
I’m assuming this is some sort of bug? What’s going on here?
Edit: Some bonus snippets as well, clarification here would be great, I’m at a loss:
--!strict
local test: NotAType = 1
print(test) --> 1
--!strict
type foo = {bar: string}
local test: foo = {foo = "Hello World", bar = 10}
print(test.foo) --> Hello World
print(test.bar) --> 10
Shouldn’t all of these scenarios not work in strict mode? I can’t find anything about the syntax for enabling strict mode changed, am I missing something here?
If you do, you should have both of these display issues in Script Analysis widget. Note that type errors don’t block your ability to run the code right now.
Studio disabled all of my beta options in the recent studio build and I was not aware of this until now. I had them all enabled. I didn’t think to check for that reason. I have no clue why, but that’s a separate issue.
edit: Studio did crash mid-session when trying to update, I can provide a crash report if you’d like, it could be related to the issue.
I’ve been rewriting my framework with type checking, and it’s been pretty smooth other than two major issues I’ve faced:
Requiring third party modules without type checking implemented, in non-strict mode, such as eryn’s “Promise” and Quenty’s “Maid” take exactly one second to require for the first time, every time. This means that it can take up to 10 seconds for any code to run, as the script is stuck requiring these modules for a long time. This is not the case with my custom libraries which are scripted with type checking. No code in the project is currently using strict mode, however all the first party code that I am writing is designed to be strict mode ready later.
I forgot I didn’t have studio API access enabled in my test place, and trying to use DataStoreService:GetGlobalDataStore() did not error, but rather the script requiring the module threw a “Requested module experienced an error while loading” error which would always throw approximately 2 seconds after initially requiring the module.
After further investigation, I’ve found niche cases where my own functions can have this behavior, too, making debugging with modules no easy task.
These two issues have made my experience really daunting, but other than that it’s been smooth sailing. Could you advise on why I’m getting such behaviors? This did not occur when all the scripts were written without heavy type checking support.
I don’t really like this update, broke some of my code:
local function noyield(f,...)
return select(2,assert(xpcall(f,debug.traceback,...)))
end
It was imo a clean wrapper to call functions and error if the function yields (very useful for non-production code). Now I have to switch to __index or a for loop iterator call (or is there a cleaner way?) to get this same behavior.
I think we can always make a yielding xpcall ourselves (is this wrong?):
But ideally the above noyield is Roblox provided and imo xpcall shouldn’t exist (if the above is just as powerful).
For loop iterator call is probably the fastest alternative. A cleaner alternative is to use coroutine.create/resume (and check status) but that can be expensive.
You could not make a yielding xpcall yourself, as the callback in xpcall executes in context of the error, making debug.traceback work.
Sorry this affected you, these things happen - it’s much better for us long term to have uniform expectations about pcall and xpcall though, and for every use case when xpcall was used to block yields there’s several opposite use cases where xpcall is desireable but didn’t work and had to be emulated.