Another great update from the team, thanks!
Awesome! I can’t wait until Roblox has capability to catch up to other leading game-engines.
I would say having unpack as the DeFacto destructuror would be slightly harder for newcomers to understand. CFrame:GetComponents()
is straightforward syntax that explains exactly that it’s doing: returning a tuple of each component.
unpack(CFrame)
is undoubtfully more confusing than the above. What exactly are we unpacking from CFrame
, its Position or Rotation? unpack(Color3)
would be even worse, because a Color3
can be RGB
, HSV
or Hex
. Returning just the R, G, B
of a Color3
would leave the others in the dust.
:: any, any
isn’t valid syntax in a Type Ascryption.
What about ...type
?
Oh yeah just found one oversight that got ghosted when I submitted it as a bug.
I honestly hate how I have to do this workaround because apparently Instance:FindFirstChild()
return type Instance
instead of Instance?
even though the real return type is Instance?
. Because of that, I have to do this workaround that somehow just works.
technically (varThatisInstanceType :: Instance?) :: Folder?
works too
Attempting to cast directly causes this error because “unrelated types”, which is just frustrating me a lot.
native cframes when??
also will we ever see the type of performance demo’d in one of zeuxcg’s hack weeks where he got luau performing comparable to luajit?
You can actually sorta
local function findFirstChild(a: Instance, b: string)
return a:FindFirstChild(b)
end :: typeof(workspace.FindFirstChild)
I’m assuming this was written in March but published on April.
Luau is looking better now. I’ve seen several performance improvements, but none of them really affected me.
And when are we going to get this?
local constructors = {}
local objects = {}
constructors.constructor = require(modulePath)
objects.myObject = constructors.constructor.new("myValue", 1, 2, 3)
--objects.myObject has no intelliSense :(
Please elaborate.
I believe unpack(CFrame)
is no more confusing than CFrame:GetComponents()
. The use of unpack
would imply that you intend to retrieve everything a value is composed of, in this case, a CFrame
’s components.
I’m going to go out on a limb and say you lack the fundamental understanding of what a Color3
even is. Although a Color3
can be constructed with an RGB
, HSV
, or Hex
, it will always be a Color3
. A Color3
will always be [stored and read] in the format of RGB
, the range being 0-1
instead of 0-255
.
The funny thing is tostring
does that already *0-1 range, so rather than “leaving the others in the dust”, it would instead reinforce the convention already put in place.
If you mean the same treatment as Vector3, then it’s not planned.
Probably.
i don’t see why there should be a difference
vs
The improved type refinements sound particularly useful, especially the ability to preserve refinements after a conditional block and enforce ML-style exhaustive analysis. The deprecation of table.getn, the possible replacement of foreach/foreachi and the autocomplete improvements also seem like positive changes. And it’s always good to see runtime improvements, particularly the optimizations made to table.sort and math functions.
I’ve been having a lot of fun trying strict mode, but here are my remaining gripes with it:
--!strict
-- Globals seem to lack type annotations despite intellisense working fine?
-- Not sure when this started or why. First noticed this today, but might've been blind to it
local workspace = workspace::Workspace
-- continue does not refine type like return does
for _,v in ipairs(workspace:GetChildren()) do
if not v:IsA("BasePart") then continue end
print(v.Position) -- Key 'Position' not found in class 'Instance'
end
-- For comparison, return refining the type
local function fn(v:Instance)
if not v:IsA("BasePart") then return end
print(v.Position) -- OK, but without the type annotation, fn(v) below says the same as v.Position above - that is to say, the refinement does not propagate backward
end
for _,v in ipairs(workspace:GetChildren()) do
fn(v)
end
-- string.gsub (still?) does not accept `(string) -> string?`
print(string.gsub("testing", ".", function(x)
if math.random() < 0.5 then
return string.char(math.clamp(string.byte(x) + math.random(-2, 2), 0, 255))
end
-- Valid and convenient, but not recognized by the type checker
return nil
-- Alternative: return x
end))
The type of the workspace
global is different than type interface’s Workspace
type due to former has datamodel hierarchy been applied on it, on top of latter, which only includes the properties, methods, events and maybe callbacks (if there are any). You can see this for yourself by using typeof
:
local workspace: typeof(workspace) = workspace
print(workspace.Script) --Perfectly fine
local workspace: Workspace = workspace
print(workspace.Script) --Type Error: (5,7) Key 'Script' not found in class 'Workspace'
Oh, I should’ve brought more examples. I was referring to services coming from GetService having type any
because game
is any
. I swear I remember services having their correct types.
Maybe it never was that way:
local foo = game -- When hovered over: any, not DataModel or Instance
local Selection = game:GetService("Selection") -- any
-- Because game is any, GetService returns any and Get() returns any
local game = game::DataModel
local Selection = game:GetService("Selection") -- Instance
-- Cue large amounts of type warnings because I am doing Instance:Get()
-- This usually doesn't happen, therefore either game has been any all along
-- or GetService used to return the correct type, but no longer does so
local Selection = game:GetService("Selection")::Selection -- Selection
-- Fully expected behavior
-- Selection:Get() returns {Instance}
So that means I should be casting all of my services to the correct type, and should’ve been all along.
I also have to cast plugin
to Plugin
, but that’s mostly because there’s no (sanctioned?) Plugin script type.
I can’t think of any other globals that this could be applying to.
Thank you for pointing out my misunderstanding on this. Yeah I just realized that game
and workspace
being any
are the issue here
That’s a bit weird that those global have the type of any
because I’ve just checked it and they do have their types based on the datamodel. Maybe your studio is broken somehow?
Make it so that in
for i,v in pairs(table) do
end
the table at the end of the loop gets table.clear executed on it if there aren’t any outside references to it.
What would be your use case? You can easily just write table.clear
after the loop
Yeah i see. It’s just memory managing
I haven’t see autocomplete improvements where we able to do this
type Direction = "north" | "south" | "east" | "west"
local a: {[Direction]: boolean} = {[^] = true}
local b: {[Direction]: boolean} = {["^"]}
local b: {[Direction]: boolean} = {^}
Or did I not get something?