JavaScript for moddding

User avatar
duane
Member
Posts: 1686
Joined: Wed Aug 19, 2015 19:11
GitHub: duane-r
Location: Oklahoma City
Contact:

Re: JavaScript for moddding

by duane » Post

Oblomov wrote:
Mon Jan 04, 2021 08:16
Everybody here fighting about which is the best scripting language, and nobody mentions Ruby? What the heck is wrong with you people? ;-)
+1

And what about bash? Talk about a ubiquitous language. There's probably more shell scripts than js out there. ;)
Believe in people and you don't need to believe anything else.

User avatar
drkwv
Member
Posts: 99
Joined: Thu Jun 28, 2012 13:48
GitHub: aa6

Re: JavaScript for moddding

by drkwv » Post

sorcerykid wrote:
Mon Jan 04, 2021 22:18

Code: Select all

return this.#data = [{}]
    .concat(Object.keys(this.#data).sort((a,b) => {return this.#data[b][field]-this.#data[a][field]}))
    .reduce((acc,key) => { acc[key] = this.#data[key]; return acc })
Just from a cursory glance, that looks like spaghetti code with all kinds of obtuse JS-specific notations.
That's basic concepts of concatenating and reducing array that are used in JS every time. You don't need to go that deep in code unless something works wrong. These three simple "return" ".concat" ".reduce" tells you what's there. On the other hand your Lua code

Code: Select all

local sorted_list = { }
for k, v in pairs( data ) do
        table.insert( sorted_list, k )
end
table.sort( sorted_list, function ( a, b )
        return data[ a ][ field ] > data[ b ][ field ]
end )
looks so sparse and monotone that it is hard to catch an eye on something specific. When I look at a code like that I see that there's just going something. Especially when you leave it for a couple of months and then return to it and need to quickly understand it's structure.
sorcerykid wrote:
Mon Jan 04, 2021 22:18
It's not that big of a deal.
Still a deal though. It's sad when you start writing a program but instead find yourself engaged with implementing/managing libraries of basic table.sort() and math.round() algorithms every time like if there's 1980. And then dragging it from project to project because lang authors decided that you "will never need it".

Or some
avyukt wrote:
Fri Jan 01, 2021 11:28
International language support, while LUA has only European Language support
although I'm not quite sure what is meant here. But I'm sure it's something worth at least several days of that gentleman's life and something that could and should be implemented in Lua by default a long time ago.
sorcerykid wrote:
Mon Jan 04, 2021 22:18
so a cache isn't needed anyway. It sounds as if you are determined to find anything to complain about
That's quite the opposite: lacking of will to argue about that. When I wrote scoreboard.js I decided to write it in Lua also but the perspective of pain of dealing with it made me so depressive that I just decided to see what code will you come with. And you didn't see the purpose of using the hashtable throwing out the id: property. The cache is needed here to demonstrate the purpose of using a sortable hashtable in a first place. Because when you code something like this you always find later to be necessary to reuse the data object with some caching or things like that. And it's uncool also when you have to rewrite the code because it doesn't provide you with enough redundancy of options by default like JS hashtables do.
sorcerykid wrote:
Mon Jan 04, 2021 22:18
Here's a diff that shows the required changes to add caching as described.
Just to be accurate, I applied this diff with patch to your previous code and got this lua code

Code: Select all

------------------------------------------------------------
-- function table.sort_by( )
--
-- Sorts a table on the given numeric field and returns a
-- list of the sorted keys accordingly.
------------------------------------------------------------

function table.sort_by( data, field, is_reverse )
  local sorted_list = { }

  for k, v in pairs( data ) do
    table.insert( sorted_list, k )
  end
  table.sort( sorted_list, is_reverse and
    function ( a, b ) return data[ a ][ field ] > data[ b ][ field ] end or
    function ( a, b ) return data[ a ][ field ] < data[ b ][ field ] end
  )

  return sorted_list
end

function printf( str, ... )
  print( string.format( str, ... ) )
end

function Scoreboard( sort_field )
  local self = { }

  -- private properties

  local data = { }
  local sorted_list
  local sort_count = 0

  assert( ( { rating = true, hp = true, mana = true } )[ sort_field ], "Invalid field for sorting!" )

  -- public methods

  self.sort = function ( field )
    sort_count = sort_count + 1
    printf( "Sorting by %s... called %d time(s)", field or sort_field, sort_count )

    sorted_list = table.sort_by( data, field or sort_field, true )
  end

  self.print = function ( )
    print( "*****" )
    printf( "%-4s %-10s %6s %6s %6s", "RANK", "NAME", "RATING", "HP", "MANA" )
    for i, v in ipairs( sorted_list ) do
       printf( "#%-3d %-10s %6d %6d %6d", i, v,
        data[ v ].rating, data[ v ].hp, data[ v ].mana )
    end
    print( "*****" )
  end

  self.insert = function ( name, def )
    assert( not data[ name ], "Entry already exists!" )

    data[ name ] = {
      rating = def.rating or 0,
      hp = def.hp or 0,
      mana = def.mana or 0,
    }
    self.sort( )
    self.print( )
  end

  self.delete = function ( name, rating )
    assert( data[ name ], "Entry not found!" )

    data[ name ] = nil
    self.sort( )
    self.print( )
  end

  self.add_rating = function ( name, rating )
    assert( data[ name ], "Entry not found!" )

    data[ name ].rating = data[ name ].rating + rating
  end

  self.add_mana = function ( name, mana )
    assert( data[ name ], "Entry not found!" )

    data[ name ].mana = data[ name ].mana + mana
  end

  self.add_hp = function ( name, hp )
    assert( data[ name ], "Entry not found!" )

    data[ name ].hp = data[ name ].hp + hp
  end

  self.get_best_player = function ( field )
    return table.sort_by( data, field or sort_field, true )[ 1 ]
  end

  -- export object

  return self
end

local scoreboard = Scoreboard( "rating" )

scoreboard.insert( "tom", { hp = 1, mana = 100, rating = 100 } )
scoreboard.insert( "jerry", { hp = 2, mana = 100, rating = 200 } )
scoreboard.insert( "he-man", { hp = 10, mana = 300, rating = 1000 } )
scoreboard.add_rating( "jerry", 9000 )
scoreboard.add_mana( "tom", 600 )
scoreboard.add_hp( "he-man", 100 )
scoreboard.delete( "tom" )
scoreboard.insert( "somebody", { hp = 90, mana = 320, rating = 400 } )

print( "Best player by rating:", scoreboard.get_best_player( "rating" ) )
print( "Best player by hp:", scoreboard.get_best_player( "hp" ) )
print( "Best player by mana:", scoreboard.get_best_player( "mana" ) )

which still doesn't provide desired output

Code: Select all

me@me:~/Desktop$ lua5.3 score.patched.lua
Sorting by rating... called 1 time(s)
*****
RANK NAME       RATING     HP   MANA
#1   tom           100      1    100
*****
Sorting by rating... called 2 time(s)
*****
RANK NAME       RATING     HP   MANA
#1   jerry         200      2    100
#2   tom           100      1    100
*****
Sorting by rating... called 3 time(s)
*****
RANK NAME       RATING     HP   MANA
#1   he-man       1000     10    300
#2   jerry         200      2    100
#3   tom           100      1    100
*****
Sorting by rating... called 4 time(s)
*****
RANK NAME       RATING     HP   MANA
#1   jerry        9200      2    100
#2   he-man       1000    110    300
*****
Sorting by rating... called 5 time(s)
*****
RANK NAME       RATING     HP   MANA
#1   jerry        9200      2    100
#2   he-man       1000    110    300
#3   somebody      400     90    320
*****
Best player by rating:  jerry
Best player by hp:  he-man
Best player by mana:  somebody
as from the code I posted penult and last times

Code: Select all

me@me:~/tst/js$ node scoreboard4.js 
Sorting by rating... called 1 time(s)
*****
RANK NAME       RATING     HP   MANA
#0   tom           100      1    100
*****
Sorting by rating... called 2 time(s)
*****
RANK NAME       RATING     HP   MANA
#0   jerry         200      2    100
#1   tom           100      1    100
*****
Sorting by rating... called 3 time(s)
*****
RANK NAME       RATING     HP   MANA
#0   he-man       1000     10    300
#1   jerry         200      2    100
#2   tom           100      1    100
*****
Sorting by rating... called 4 time(s)
*****
RANK NAME       RATING     HP   MANA
#0   jerry        9200      2    100
#1   he-man       1000     10    300
#2   tom           100      1    100
*****
*****
RANK NAME       RATING     HP   MANA
#0   jerry        9200      2    100
#1   he-man       1000     10    300
#2   tom           100      1    700
*****
*****
RANK NAME       RATING     HP   MANA
#0   jerry        9200      2    100
#1   he-man       1000    110    300
#2   tom           100      1    700
*****
*****
RANK NAME       RATING     HP   MANA
#0   jerry        9200      2    100
#1   he-man       1000    110    300
*****
Sorting by rating... called 5 time(s)
*****
RANK NAME       RATING     HP   MANA
#0   jerry        9200      2    100
#1   he-man       1000    110    300
#2   somebody      400     90    320
*****
Sorting by rating... called 6 time(s)
Best player by rating: [ 'jerry', { hp: 2, mana: 100, rating: 9200 } ]
Sorting by hp... called 7 time(s)
Best player by hp: [ 'he-man', { hp: 110, mana: 300, rating: 1000 } ]
Sorting by mana... called 8 time(s)
Best player by mana: [ 'somebody', { hp: 90, mana: 320, rating: 400 } ]
sorcerykid wrote:
Mon Jan 04, 2021 22:18
As someone that's come from a background of many different programming languages
Never was going to challenge your experience. Might be that you're so smart and experienced that you don't feel discomfort working with Lua. But even if you are ok walking everyday up to the 15th floor by the stairs it doesn't mean that having a lift in a building means something bad.
Oblomov wrote:
Mon Jan 04, 2021 08:16
Everybody here fighting about which is the best scripting language, and nobody mentions Ruby? What the heck is wrong with you people? ;-)
Tried it about 10 years ago, got weird problems with parallelism. If they're adopted promises might be a good language to try it one more time. RoR spoiled the Ruby though. That would be better for Ruby is RoR never existed. Bash is good for code obfuscation. Significant space symbols is the "best" part about it.

User avatar
sorcerykid
Member
Posts: 1503
Joined: Fri Aug 26, 2016 15:36
GitHub: sorcerykid
In-game: Nemo
Location: Illinois, USA

Re: JavaScript for moddding

by sorcerykid » Post

That's basic concepts of concatenating and reducing array that are used in JS every time. You don't need to go that deep in code unless something works wrong.
If it's such "basic concepts" used every time, then it's strange that the JS language authors were so lazy that they didn't provide all of that redundant functionality as a single API. Instead JS requires a difficult-to-read copypasta whenever someone wants to implement a basic table sort in JS. That's ironic.
These three simple "return" ".concat" ".reduce" tells you what's there.
If you honestly think that code snippet is qualified as "simple", then you really shouldn't be criticizing Lua.
On the other hand your Lua code (snip)
looks so sparse and monotone that it is hard to catch an eye on something specific.
Ah, so you need overly-convoluted code so you can catch your eye on something specific. And that is why you want everyone to switch to Javascript to make it easier on your eyes, because you personally dislike "sparse and monotone" code.
When I look at a code like that I see that there's just going something. Especially when you leave it for a couple of months and then return to it and need to quickly understand it's structure.
Strange, I never have problems understanding simple Lua constructs like this. It's just a run-of-the-mill loop and sort function. I maintain tens of thousands of lines of code for my server, and I can honestly say that even when I'm dealing with poorly written mods, I can still generally ascertain out what the mod author was intending to do.
Still a deal though. It's sad when you start writing a program but instead find yourself engaged with implementing/managing libraries of basic table.sort() and math.round() algorithms every time like if there's 1980. And then dragging it from project to project because lang authors decided that you "will never need it".
As I already wrote above Lua is an embedded scripting language, and it began as a configuration language. So if you want a feature that is not builtin then you "require" it. The fact that you find libraries difficult to manage, and think a scripting language is supposed to provide training wheels for every possible use-case is wholly unrealistic.
That's quite the opposite: lacking of will to argue about that. When I wrote scoreboard.js I decided to write it in Lua also but the perspective of pain of dealing with it made me so depressive that I just decided to see what code will you come with. And you didn't see the purpose of using the hashtable throwing out the id: property.
I only left out of the ID field because you didn't use it in your original example at all. Also trying to comprehend that JS code was already giving me a headache since you were directly manipulating a private data structure within a class, which is an anti-pattern. The whole point of classes is abstraction. So it is no wonder you're having difficulty maintaining a code base if you are designing a custom API that way.
The cache is needed here to demonstrate the purpose of using a sortable hashtable in a first place.
Riight, so because Lua doesn't support sortable hashtables, the entire Minetest modding community is supposed to stop what they are doing and migrate to JS to make your life easier because you don't like writing a few extra lines of code to implement and maintain a cache, which is only needed as a thought experiment. That's hardly a reasonable expectation.
Because when you code something like this you always find later to be necessary to reuse the data object with some caching or things like that. And it's uncool also when you have to rewrite the code because it doesn't provide you with enough redundancy of options by default like JS hashtables do.
Fact of life: No scripting language is going to provide every single builtin feature that you want. At least Lua is easily extensible.

User avatar
drkwv
Member
Posts: 99
Joined: Thu Jun 28, 2012 13:48
GitHub: aa6

Re: JavaScript for moddding

by drkwv » Post

sorcerykid wrote:
Tue Jan 05, 2021 11:49
If you honestly think that code snippet is qualified as "simple", then you really shouldn't be criticizing Lua.
I actually said that there is no need to go behind these three keywords to understand the code unless something is broken and you really need to go deep into.
sorcerykid wrote:
Tue Jan 05, 2021 11:49
If it's such "basic concepts of concatenating" then it's strange that the JS language authors were so lazy that they didn't provide all of this redundant functionality as a single builtin function.
There is a place to improve JS. Unfortunately they don't consider it also. For example not having a sprintf() for such a long time is a shame. It's again the same mentality "nobody needs it" despite the fact that it was productively and heavily used long time before JS even existed. Having a standard function to multisort a hashtable by its properties' values would have been a blessing (if an implementation of it would be good enough which is unfortunately not always the case too).
sorcerykid wrote:
Tue Jan 05, 2021 11:49
Ah, so you need overly-convoluted code so you can catch your eye on something specific.
It's just somewhat a conveyor of one-liners where each line express a solid abstraction.
sorcerykid wrote:
Tue Jan 05, 2021 11:49
And that is why you want everyone to switch to Javascript to make it easier on your eyes, because you personally dislike "sparse and monotone" code.
As I said before I understand why everyone has no pleasure in switching to it. Probably when I created the thread I thought that it could be easily done (which turned out to be not true or this would have been done already) and just to express my frustration towards the everybody's general content with Lua. Now I don't think everyone should switch to JavaScript even more because JS started heading in a wrong direction.
sorcerykid wrote:
Tue Jan 05, 2021 11:49
and I can honestly say that even when I'm dealing with poorly written mods, I can still generally ascertain out what the mod author was intending to do.
I don't want to insult people who generously gifted to everyone their hard work for free, that would be unfair regards to them, but I can't share the delight of reading most mods code I've seen. Even not poorly written ones is still a monotone mess and I think Lua contributed to this significantly as a language to start with.
sorcerykid wrote:
Tue Jan 05, 2021 11:49
the entire Minetest modding community is supposed to stop what they are doing and migrate to JS to make your life easier
Please don't. But having at least a discussion about this is a good thing. Maybe just maybe in the distant bright future when/if the Minetest 2.0 will be born the choice of Lua would be reconsidered in favor of some better scripted language that hopefully will emerge. This thread should exist as a statement of the fact that Lua is not an ideal scripting language everyone is content with. It has issues.
sorcerykid wrote:
Tue Jan 05, 2021 11:49
Fact of life: No scripting language is going to provide every single builtin feature that you want. At least Lua is easily extensible.
JS is as extensible as a Lua. Both are merely equivalent to each other regards that feature.

MrUnderhill89
Member
Posts: 18
Joined: Fri Jun 03, 2016 13:55
GitHub: mrunderhill89

Re: JavaScript for moddding

by MrUnderhill89 » Post

drkwv wrote:
Tue Jan 05, 2021 12:32
I actually said that there is no need to go behind these three keywords to understand the code unless something is broken and you really need to go deep into.
That's a library issue, not an issue with the language. There's nothing stopping you from writing your own concat() and reduce() functions in Lua and using them to do functional programming. In fact, Lua can implement them slightly more elegantly than JS because Lua has tail-call optimization, which ES2016 was supposed to have, but neither Chrome nor Firefox have implemented it to date. Arrow syntax is nice, but it's syntactic sugar; function/end is just as readable. And (my pet peeve, I know) this/self in Lua isn't nearly as much black magic as it is in JS; in Lua, it's just another function parameter. Saves you so many calls to bind().

If you want to try functional programming in Lua, check out Moses and Luafun. They should feel pretty familiar to this style of programming. Haven't tried using Luafun in Minetest yet, but Moses works great if you load it as a global first.

User avatar
ywwv
Member
Posts: 24
Joined: Mon Jan 18, 2021 11:51

Re: JavaScript for moddding

by ywwv » Post

I hope minetest can get javascript so it can work in the web browsers at work. I cannot install programs on my work computer and minetest is more fun than the flash games that are unblocked

User avatar
rubenwardy
Moderator
Posts: 6379
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: United Kingdom
Contact:

Re: JavaScript for moddding

by rubenwardy » Post

Lua can run in browsers. Having JavaScript modding won't make it any easier to port to a web browser, we just don't want to support that. Perhaps you shouldn't be playing games at work or on work computers

User avatar
ywwv
Member
Posts: 24
Joined: Mon Jan 18, 2021 11:51

Re: JavaScript for moddding

by ywwv » Post

rubenwardy wrote:
Mon Jan 18, 2021 15:41
Lua can run in browsers. Having JavaScript modding won't make it any easier to port to a web browser, we just don't want to support that. Perhaps you shouldn't be playing games at work or on work computers
Perhaps you shouldn't judge me! you aren't my boss

if lua can run in browsers this is even better. I will look forwarsd to having it on the WWW

Post Reply

Who is online

Users browsing this forum: No registered users and 2 guests