subtle differences between JavaScript and Lua [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I simply love JavaScript. It's so elegant.
So, recently I have played with Lua via the löve2d framework (nice!) - and I think Lua is also great. They way I see it, those two languages are very similar.
There are obvious differences, like
syntax
problem domain
libraries
types (a bit)
but which are the more subtle ones? Is there anything a JavaScript coder would take for granted that works in Lua just slightly different? Are there any pitfalls that may not be obvious to the experienced coder of one language trying the other one?
For example: in Lua, arrays and hashes are not separate (there are only tables) - in JavaScript, they are numerical Arrays and hashed Objects. Well, this is one of the more obvious differences.
But are there differences in variable scope, immutability or something like this?

Some more differences:
Lua has native support for coroutines.
UPDATE: JS now contains the yield keyword inside generators, giving it support for coroutines.
Lua doesn't convert between types for any comparison operators. In JS, only === and !== don't type juggle.
Lua has an exponentiation operator (^); JS doesn't. JS uses different operators, including the ternary conditional operator (?: vs and/or), and, as of 5.3, bitwise operators (&, |, etc. vs. metamethods ).
UPDATE: JS now has the exponentiation operator **.
JS has increment/decrement, type operators (typeof and instanceof), additional assignment operators and additional comparison operators.
In JS, the ==, ===, != and !== operators are of lower precedence than >, >=, <, <=. In Lua, all comparison operators are the same precedence.
Lua supports tail calls.
UPDATE: JS now supports tail calls.
Lua supports assignment to a list of variables. While it isn't yet standard in Javascript, Mozilla's JS engine (and Opera's, to an extent) has supported a similar feature since JS 1.7 (available as part of Firefox 2) under the name "destructuring assignment". Destructuring in JS is more general, as it can be used in contexts other than assignment, such as function definitions & calls and loop initializers. Destructuring assignment has been a proposed addition to ECMAScript (the language standard behind Javascript) for awhile.
UPDATE: Destructuring (and destructuring assignment) is now part of the spec for ECMAScript - already implemented in many engines.
In Lua, you can overload operators.
In Lua, you can manipulate environments with getfenv and setfenv in Lua 5.1 or _ENV in Lua 5.2 and 5.3.
In JS, all functions are variadic. In Lua, functions must be explicitly declared as variadic.
Foreach in JS loops over object properties. Foreach in Lua (which use the keyword for) loops over iterators and is more general.
UPDATE: JS has Iterables now too, many of which are built into the regular data structures you'd expect, such as Array. These can be looped over with the for...of syntax. For regular Objects, one can implement their own iterator functions. This brings it much closer to Lua.
JS has global and function scope. Lua has global and block scope. Control structures (e.g. if, for, while) introduce new blocks.
Due to differences in scoping rules, a closure's referencing of an outer variable (called "upvalues" in Lua parlance) may be handled differently in Lua and in Javascript. This is most commonly experienced with closures in for loops, and catches some people by surprise. In Javascript, the body of a for loop doesn't introduce a new scope, so any functions declared in the loop body all reference the same outer variables. In Lua, each iteration of the for loop creates new local variables for each loop variable.
local i='foo'
for i=1,10 do
-- "i" here is not the local "i" declared above
...
end
print(i) -- prints 'foo'
The above code is equivalent to:
local i='foo'
do
local _i=1
while _i<10 do
local i=_i
...
_i=_i+1
end
end
print(i)
As a consequence, functions defined in separate iterations have different upvalues for each referenced loop variable. See also Nicolas Bola's answers to Implementation of closures in Lua? and "What are the correct semantics of a closure over a loop variable?", and "The Semantics of the Generic for".
UPDATE: JS has block scope now. Variables defined with let or const respect block scope.
Integer literals in JS can be in octal.
JS has explicit Unicode support, and internally strings are encoded in UTF-16 (so they are sequences of pairs of bytes). Various built-in JavaScript functions use Unicode data, such as "pâté".toUpperCase() ("PÂTÉ"). Lua 5.3 and up have Unicode code point escape sequences in string literals (with the same syntax as JavaScript code point escape sequences) as well as the built-in utf8 library, which provides basic support for the UTF-8 encoding (such as encoding code points into UTF-8 and decoding UTF-8 into code points, getting the number of code points in a string, and iterating over code points). Strings in Lua are sequences of individual bytes and can contain text in any encoding or arbitrary binary data. Lua does not have any built-in functions that use Unicode data; the behavior of string.upper depends on the C locale.
In Lua, the not, or, and keywords are used in place of JS's !, ||, &&.
Lua uses ~= for "not equal", whereas JS uses !==. For example, if foo ~= 20 then ... end.
Lua 5.3 and up use ~ for binary bitwise XOR, whereas JS uses ^.
In Lua, any type of value (except nil and NaN) can be used to index a table. In JavaScript, all non-string types (except Symbol) are converted to strings before being used to index an object. For example, after evaluation of the following code, the value of obj[1] will be "string one" in JavaScript, but "number one" in Lua: obj = {}; obj[1] = "number one"; obj["1"] = "string one";.
In JS, assignments are treated as expressions, but in Lua they are not. Thus, JS allows assignments in conditions of if, while, and do while statements, but Lua does not in if, while, and repeat until statements. For example, if (x = 'a') {} is valid JS, but if x = 'a' do end is invalid Lua.
Lua has syntactic sugar for declaring block-scoped function variables, functions that are fields, and methods (local function() end, function t.fieldname() end, function t:methodname() end). JS declares these with an equals sign (let funcname = function optionalFuncname() {}, objectname.fieldname = function () {}).

A couple of subtle differences that will catch you out at least once:
Not equal is spelled ~= in Lua. In JS it is !=
Lua arrays are 1-based - their first index is 1 rather than 0.
Lua requires a colon rather than a period to call object methods. You write a:foo() instead of a.foo() †
† you can use a period if you want, but have to pass the self variable explicitly. a.foo(a) looks a bit cumbersome. See Programming in Lua for details.

To be honest it would be easier to list the things which are common to Javascript and Lua than to list the differences. They are both dynamically-typed scripting languages, but that's about as far as you can go really. They have totally different syntax, different original design goals, different modes of operation (Lua is always compiled to bytecode and run on the Lua VM, Javascript varies), the list goes on and on.

JavaScript arrays and objects are closer than you might think. You can use array notation to get at the elements of either of them, and you can add non-numeric indices to arrays. Individual array elements can hold anything, and the array can be sparse. They are nearly identical cousins.

I liked this question and the answers provided. Additional reasons the two languages seem more alike than not to me:
Both
assign functions to variables,
can build functions on the fly,
and define closures.

Off the top of my head
Lua ...
supports coroutines
has no restriction to just string/number as key for a table. Everything works.
the error handling is somewhat clumsy. Either you don't handle anything or use the pcall method
I think I read something about differences in the lexical scope and that Lua has the better one.
If I recall correctly regular expression support in lua is limited

Lua and JavaScript are both prototype base languages.

A test reveals that current Javascript also returns objects, or at least strings from logic expressions like lua does:
function nix(){
alert(arguments[0]||"0");
}
nix();

Related

Javascript used to be a lisp? [duplicate]

A friend of mine drew my attention the welcome message of 4th European Lisp Symposium:
... implementation and application of
any of the Lisp dialects, including
Common Lisp, Scheme, Emacs Lisp,
AutoLisp, ISLISP, Dylan, Clojure,
ACL2, ECMAScript, ...
and then asked if ECMAScript is really a dialect of Lisp. Can it really be considered so? Why?
Is there a well defined and clear-cut set of criteria to help us detect whether a language is a dialect of Lisp? Or is being a dialect taken in a very loose sense (and in that case can we add Python, Perl, Haskell, etc. to the list of Lisp dialects?)
Brendan Eich wanted to do a Scheme-like language for Netscape, but reality intervened and he ended up having to make do with something that looked vaguely like C and Java for "normal" people, but which worked like a functional language.
Personally I think it's an unnecessary stretch to call ECMAScript "Lisp", but to each his own. The key thing about a real Lisp seems like the characteristic that data structure notation and code notation are the same, and that's not true about ECMAScript (or Ruby or Python or any other dynamic functional language that's not Lisp).
Caveat: I have no Lisp credentials :-)
It's not. It's got a lot of functional roots, but so do plenty of other non-lisp languages nowadays, as you pointed out.
Lisps have one remaining characteristic that make them lisps, which is that lisp code is written in terms of lisp data structures (homoiconicity). This is what enables lisps powerful macro system, and why it looks so bizzare to non-lispers. A function call is just a list, where the first element in the list is the name of the function.
Since lisp code is just lisp data, it's possible to do some extremely powerful stuff with metaprogramming, that just can't be done in other languages. Many lisps, even modern ones like clojure, are largely implemented in themselves as a set of macros.
Even though I wouldn't call JavaScript a Lisp, it is, in my humble opinion, more akin to the Lisp way of doing things than most mainstream languages (even functional ones).
For one, just like Lisp, it's, in essence, a simple, imperative language based on the untyped lambda calculus that is fit to be driven by a REPL.
Second, it's easy to embed literal data (including code in the form of lambda expressions) in JavaScript, since a subset of it is equivalent to JSON. This is a common Lisp pattern.
Third, its model of values and types is very lispy. It's object-oriented in a broad sense of the word in that all values have a concept of identity, but it's not particularly object-oriented in most narrower senses of the word. Just as in Lisp, objects are typed and very dynamic. Code is usually split into units of functions, not classes.
In fact, there are a couple of (more or less) recent developments in the JavaScript world that make the language feel pretty lispy at times. Take jQuery, for example. Embedding CSS selectors as a sublanguage is a pretty Lisp-like approach, in my opinion. Or consider ECMAScript Harmony's metaobject protocol: It really looks like a direct port of Common Lisp's (much more so than either Python's or Ruby's metaobject systems!). The list goes on.
JavaScript does lack macros and a sensible implementation of a REPL with editor integration, which is unfortunate. Certainly, influences from other languages are very much visible as well (and not necessarily in a bad way). Still, there is a significant amount of cultural compatibility between the Lisp and JavaScript camps. Some of it may be coincidental (like the recent rise of JavaScript JIT compilation), some systematic, but it's definitely there.
If you call ECMAScript Lisp, you're basically asserting that any dynamic language is Lisp. Since we already have "dynamic language", you're reducing "Lisp" to a useless synonym for it instead of allowing it to have a more specific meaning.
Lisp should properly refer to a language with certain attributes.
A language is Lisp if:
Its source code is tree-structured data, which has a straightforward printed notation as nested lists. Every possible tree structure has a rendering in the corresponding notation and is susceptible to being given a meaning as a construct; the notation itself doesn't have to be extended to extend the language.
The tree-structured data is a principal data structure in the language itself, which makes programs susceptible to manipulation by programs.
The language has symbol data type. Symbols have a printed representation which is interned: when two or more instances of the same printed notation for a symbol appear in the notation, they all denote the same object.
A symbol object's principal virtue is that it is different from all other symbols. Symbols are paired with various other entities in various ways in the semantics of Lisp programs, and thereby serve as names for those entities.
For instance, dialect of Lisp typically have variables, just like other languages. In Lisp, variables are denoted by symbols (the objects in memory) rather than textual names. When part of a Lisp program defines some variable a, the syntax for that a is a symbol object and not the character string "a", which is just that symbol's name for the purposes of printing. A reference to the variable, the expression written as a elsewhere in the program, is also an on object. Because of the way symbols work, it is the same object; this object sameness then connects the reference to the definition. Object sameness might be implemented as pointer equality at the machine level. We know that two symbol values are the same because they are pointers to the same memory location in the heap (an object of symbol type).
Case in point: the NewLisp dialect which has a non-traditional memory management for most data types, including nested lists, makes an exception for symbols by making them behave in the above way. Without this, it wouldn't be Lisp. Quote: "Objects in newLISP (excluding symbols and contexts) are passed by value copy to other user-defined functions. As a result, each newLISP object only requires one reference." [emphasis mine]. Passing symbols too, as by value copy, would destroy their identity: a function receiving a symbol wouldn't be getting the original one, and therefore not correctly receiving its identity.
Compound expressions in a Lisp language—those which are not simple primaries like numbers or strings—consist of a simple list, whose first element is a symbol indicating the operation. The remaining elements, if any, are argument expressions. The Lisp dialect applies some sort of evaluation strategy to reduce the expression to a value, and evoke any side effects it may have.
I would tentatively argue that lists being made of binary cells that hold pairs of values, terminated by a special empty list object, probably should be considered part of the definition of Lisp: the whole business of being able to make a new list out of an existing one by "consing" a new item to the front, and the easy recursion on the "first" and "rest" of a list, and so on.
And then I would stop right there. Some people believe that Lisp systems have to be interactive: provide an environment with a listener, in which everything is mutable, and can be redefined at any time and so on. Some believe that Lisps have to have first-class functions: that there has to be a lambda operator and so on. Staunch traditionalists might even insists that there have to be car and cdr functions, the dotted pair notation supporting improper lists, and that lists have to be made up of cells, and terminated by specifically the symbol nil denoting the empty list, and also a Boolean false. Insisting on car and cdr allows Scheme to be a Lisp, but nil being the list terminator and false rules
The more we shovel into the definition of "Lisp dialect", though, the more it becomes political; people get upset that their favorite dialect (perhaps which they created themselves) is being excluded on some technicality. Insisting on car and cdr allows Scheme to be a Lisp, but nil being the list terminator and false rules it out. What, Scheme not a Lisp?
So, based on the above, ECMAScript isn't a dialect of Lisp. However, an ECMAScript implementation contains functionality which can be exposed as a Lisp dialect and numerous such dialects have been developed. Someone who needs wants ECMAScript to be considered a Lisp for some emotional reasons should perhaps be content with that: that the semantics to support Lisp is there, and just needs a suitable interface to that semantics, which can be developed in ECMAScript and which can interoperate with ECMAScript code.
No it's not.
In order to be considered a Lisp, one has to be homoiconic, which ECMAscript is not.
Not a 'dialect'. I learned LISP in the 70's and haven't used it since, but when I learned JavaScript recently I found myself thinking it was LISP-like. I think that's due to 2 factors: (1) JSON is a list-like associative structures and (2) it's seems as though JS 'objects' are essentially JSON. So even though you don't write JS programs in JSON as you would write LISP in lists, you kind of almost do.
So my answer is that there are enough similarities that programmers familiar with LISP will be reminded of it when they use JavaScript. Statements like JS = LISP in a Java suit are only expressing that feeling. I believe that's all there is to it.
Yes, it is. Quoting Crockford:
"JavaScript has much in common with Scheme. It is a dynamic language. It has a flexible datatype (arrays) that can easily simulate s-expressions. And most importantly, functions are lambdas.
Because of this deep similarity, all of the functions in [recursive programming primer] 'The Little Schemer' can be written in JavaScript."
http://www.crockford.com/javascript/little.html
On the subject of homoiconicity, I would recommend searching that word along with JavaScript. Saying that it is "not homoiconic" is true but not the end of the story.
I think that ECMAScript is a dialect of LISP in the same sense that English is a dialect of French. There are commonalities, but you'll have trouble with assignments in one armed only with knowledge of the other :)
I find it interesting that only one of the three keynote presentations highlighted for the 4th European Lisp Symposium directly concerns Lisp (the other two being about x86/JVM/Python and Scala).
"dialect" is definitely stretching it too far. Still, as someone who has learned and used Python, Javascript, and Scheme, Javascript clearly has a far Lisp-ier feel to it (and Coffeescript probably even more so) than Python.
As for why the European Lisp Symposium would want to portray Javascript as a Lisp, obviously they want to piggyback on the popularity of the Javascript for which the programmer population is many, many times larger than all the rest of the Lisp dialects in their list combined.

Why is toString of JavaScript function implementation-dependent?

From the EcmaScript 5 specification
15.3.4.2 Function.prototype.toString( )
An implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration. Note in particular that the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.
Why is it implementation-dependent? It shouldn't be too hard to make it output standardized string consisting of the original code of the function. Also the reasons that I can come up with such as optimization, doesn't seem to be too heavily used as pretty much all the browsers give the original code as result of toString.
If the toString wouldn't be implementation-dependent and thus would be standardized to be the original code for function (with the new lines etc. handled on standard way), wouldn't it make it possible to include the functions on JSON?
I do realize that the JSON, despite its name, is independent of JavaScript and thus the functions shouldn't be part of it. But this way the functions could in theory be passed with it as strings, without losing the cross-browser support.
Internally, Function.prototype.toString() has to get the function declaration code for the function, which it may or may not have. According to the MDN page, FF used to decompile the function, and now it stores the declaration with the function, so it doesn't have to decompile it.
Since Gecko 17.0 (Firefox 17 / Thunderbird 17 / SeaMonkey 2.14),
Function.prototype.toString() has been implemented by saving the
function's source. The decompiler was removed
*https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/toString
Decompiling it requires extra work. Storing it requires extra memory. A given ECMAscript implementation may have different resource requirements.
Further, if it is decompiled, that is dependent on how it was stored in the first place. An engine may be unable to return comments in the original, because it didn't store them when the function was evaluated. Or whitespace/newlines might be different if the engine collapsed them. Or the engine may have optimized the code, such as by ignoring unreachable code, making it not possible to return that code back in the toString() call.
...some engines omit newlines. And others omit comments. And others
omit "dead code". And others include comments around (!) function. And
others hide source completely...
*http://perfectionkills.com/state-of-function-decompilation-in-javascript/
These are just a few reasons why Function.prototype.toString() is implementation dependent.

RegExp for parsing a Math Expression?

Hey I've written a fractal-generating program in JavaScript and HTML5 (here's the link), which was about a 2 year process including all the research I did on Complex math and fractal equations, and I was looking to update the interface, since it is quite intimidating for people to look at. While looking through the code I noticed that some of my old techniques for going about doing things were very inefficient, such as my Complex.parseFunction.
I'm looking for a way to use RegExp to parse components of the expression such as functions, operators, and variables, as well as implementing the proper order of operations for the expression. An example below might demonstrate what I mean:
//the first example parses an expression with two variables and outputs to string
console.log(Complex.parseFunction("i*-sinh(C-Z^2)", ["Z","C"], false))
"Complex.I.mult(Complex.neg(Complex.sinh(C.sub(Z.cPow(new Complex(2,0,2,0))))))"
//the second example parses the same expression but outputs to function
console.log(Complex.parseFunction("i*-sinh(C-Z^2)", ["Z","C"], true))
function(Z,C){
return Complex.I.mult(Complex.neg(Complex.sinh(C.sub(Z.cPow(new Complex(2,0,2,0))))));
}
I know how to handle RegExp using String.prototype.replace and all that, all I need is the RegExp itself. Please note that it should be able to tell the difference between the subtraction operator (e.g. "C-Z^2") and the negative function (e.g. "i*-(Z^2+C)") by noting whether it is directly after a variable or an operator respectively.
While you can use regular expressions as part of an expression parser, for example to break out tokens, regular expressions do not have the computational power to parse properly nested mathematical expressions. That is essentially one of the core results of computing theory (finite state automata vs. push down automata). You probably want to look at something like recursive-descent or LR parsing.
I also wouldn't worry too much about the efficiency of parsing an expression provided you only do it once. Given all of the other math you are doing, I doubt it is material.

Static Parsing: Tell if Two Javascript Functions are the Same

I am looking for a way, using static analysis of two JavaScript functions, to tell if they are the same. Let me define multiple definitions of "the same".
Level 1: The functions are the same except for possible different whitespace, e.g. TABS, CR, LF and SPACES.
Level 2 The functions may have different whitespace like Level 1, but also may have different variable names.
Level 3 ???
For level one, I think I could just remove all (non-literal, which may be tough) whitespace from each string containing the two JS function definitions, and then compare the strings.
For level two, I think I would need to use something like SpiderMonkey's parser to generate a two parse trees, and then write a comparer which walks the trees and allows variables to have different names.
[Edit] Williham, makes a good point below. I do mean identical. Now, I'm looking for some practical strategies, particularly with regards to using parse trees.
Reedit:
To expound on my suggestion for determining identical functions, the following flow can be suggested:
Level 1: Remove any whitespace that is not part of a string literal; insert newlines after each {, ; and } and compare. If equal; the functions are identical, if not:
Level 2: Move all variable declarations and assignments that don't depend on the state of other variables defined in the same scope to the start of the scope they are declared in (or if not wanting to actually parse the JS; the start of the braces); and order them by line length; treating all variable names as being 4 characters long, and falling back to alphabetical ordering ignoring variable names in case of tied lengths. Reorder all collections in alphabetical order, and rename all variables vSNN, where v is literal, S is the number of nested braces and NN is the order in which the variable was encountered.
Compare; if equal, the functions are identical, if not:
Level 3: Replace all string literals with "sNN", where " and s are literal, and NN is the order in which the string was encountered. Compare; if equal, the functions are identical, if not:
Level 4: Normalize the names of any functions known to be the same by using the name of the function with the highest priority according to alphabetical order (in the example below, any calls to p_strlen() would be replaced with c_strlen(). Repeat re-orderings as per level 1 if necessary. Compare; if equal, the functions are identical, if not; the functions are almost certainly not identical.
Original answer:
I think you'll find that you mean "identical", not "the same".
The difference, as you'll find, is critical:
Two functions are identical if, following some manner of normalization, (removing non-literal whitespace, renaming and reordering variables to a normalized order, replacing string literals with placeholders, …) they compare to literally equal.
Two functions are the same if, when called for any given input value they give the same return value. Consider, in the general case, a programming language which has counted, zero-terminated strings (hybrid Pascal/C strings, if you will). A function p_strlen(str) might look at the character count of the string and return that. A function c_strlen(str) might count the number of characters in the string and return that.
While these functions certainly won't be identical, they will be the same: For any given (valid) input value they will give the same value.
My point is:
Determining wether two functions are identical (what you seem to want to achieve) is a (moderately) trivial problem, done as you describe.
Determining wether two functions are truly the same (what you might actually want to achieve) is non-trivial; in fact, it's downright Hard, probably related to the Halting Problem, and not something that can be done with static analysis.
Edit: Of course, functions that are identical are also the same; but in a highly specific and rarely useful way for complete analysis.
Your approach for level 1 seems reasonable.
For level 2, how about do some rudimentary variable substitution on each function and then do approch for level 1? Start at the beginning and for each variable declaration you encounter rename them to var1, var2, ... varX.
This does not help if the functions declare variables in different orders... var i and var j may be used the same way in both functions but are declared in different orders. Then you are probably left doing a comparison of parse trees like you mention.
See my company's (Semantic Designs) Smart Differencer tool. This family of tools parses source code according to compiler-level-detail grammar for the language of interest (in your case, JavaScript), builds ASTs, and then compares the ASTs (which effectively ignores whitespace and comments). Literal values are normalized, so it doesn't matter how they are "spelled"; 10E17 has the same normalized value as 1E18.
If the two trees are the same, it will tell you "no differences". If they differ by a consistent renaming of an identifier, the tool will tell you the consisten renaming and the block in which it occurs. Other differences are reported as language-element (identifier, statement, block, class,...) insertions, deletions, copies, or moves. The goal is to report the small set of deltas that plausibly explain the differences. You can see examples for a number of languages at the web site.
You can't in practice go much beyond this; to determine if two functions compute the same answer, in principle you have to solve the halting problem. You might be able to detect where two language elements that are elements of a commutative list, can be commuted without effect; we're working on this. You might be able to apply normalization rewrites to canonicalize certain forms (e.g., map all multiple declarations into a sequence of lexically sorted single declarations). You might be able to convert the source code into its equivalent set of dataflows, and do a graph isomorphism match (the Programmer's Apprentice from MIT back in the 1980's proposed to do this, but I don't think they ever got there).
All of there are more work to do than you might expect.

JS Object navigation-- when to use object.sub and object["sub"]?

Looking at this from a point of semantics, there's two ways to navigate objects in JS, you can either use the dot operator or work through them like it's a nested array.
When is it appropriate to use one operator over the other? Why shouldn't I just use the method with square brackets all the time (it seems more powerful)? They both seems easy to read, but the dot operator looks like it's limited in that it cannot be provided with variable names of nested objects, or work through arrays.
The main reasons for using []
You can't access properties with the names of keywords via the dot notation (at least not in < ES5)
You can use it to access properties given by a string
The reasons for using .
Always using [] makes syntax highlighting, code completion etc. pretty much useless
Even with automatic insertion of the closing counter parts [' is a hell lot slower to type (especially on non US Keyboard layouts)
I mean, just imagine writing Chat['users']['getList']()['sort']()['each'].
Rule of thumb: Use . where ever possible, and fall back to [] when there's no other way.

Categories

Resources