Time Nick Message 20:14 sfan5 paradust: should never be the case 20:14 sfan5 can I summon some lua experts here 20:14 sfan5 https://0x0.st/oM6i.png what is wrong with this code 20:14 sfan5 I can't figure it out 20:15 sfan5 instead of a three high cobble column the nodes are all over the place, as if the indexes were wrong 20:18 sfan5 okay nevermind reading the docs helped 20:18 Krock_ wrong minp/maxp? 20:19 Krock_ local vm, emin, emax = minetest.get_mapgen_object("voxelmanip") 20:19 Krock_ local va = VoxelArea:new{MinEdge=emin, MaxEdge=emax} 20:19 sfan5 yes 20:19 sfan5 that begs the question why minp ~= emin or maxp ~= emax 20:20 Krock the mapgen may emerge more blocks around 20:20 Krock IIRC for structures that overlap the borders 20:21 Krock schematics placement with Vmanip for example 20:21 Krock the coordinates may go outside of minp/maxp but there's still vmanip data from the generator to place it 20:23 sfan5 hm 20:36 MTDiscord Breaking: Local core dev cant understand API 20:37 Krock even devs cannot remember what each part of the API is supposed to do 20:37 muurkha to be fair there are some aspects of the API that are a bit obscure 20:37 muurkha not to say rebarbative 20:37 Krock clearly 9000 lines of documentation is not enough :/ 20:40 muurkha it's over 9000! 21:00 MTDiscord sfan5: I believe everybody is bound to shoot themselves in the foot with this 21:01 MTDiscord Krock: A clean API would feed the VoxelArea with emin, emax on itself - modders couldn't possibly mess up 21:01 sfan5 https://0x0.st/oM6j.png is this too much gravel 21:01 muurkha documentation can tell you how to work around a bad interface but it doesn't make it a good one. most of the Minetest API is great but there are some boners 21:04 MTDiscord No, most of the MT API isn't great. 21:05 erle yeah most of it has grown, but not necessarily prospered 21:05 erle it works, for the most part 21:05 muurkha maybe your standards are higher than mine, but I've seen a lot of people with only minimal programming experience get interesting mods working, which in my mind is the mark of a great API 21:06 erle oh no, that's a basic requirement for something that wants mods 21:06 MTDiscord That's on Lua rather than the MT API 21:06 MTDiscord cue erle hating on the global environment 21:06 muurkha the global environment is definitely a design flaw in Lua 21:07 MTDiscord Elaborate 21:07 MTDiscord Would you prefer local by default? 21:07 erle lua is basically a bunch of design flaws that are easily embeddable :P 21:07 MTDiscord NOOOOOOOOOOOOOOOO 21:07 muurkha I'd prefer syntax-error-by-default and no variable scope larger than a file 21:07 muurkha well, compile-error-by-default 21:08 MTDiscord You can use Lua that way and it is in fact often done 21:08 erle lua is so cool it can do boolean operations on non-boolean arguments 21:08 MTDiscord Most script langs do that 21:08 erle > print(0 or 1) 21:08 erle 0 21:08 MTDiscord Lua isn't strictly typed, what a surprise 21:08 MTDiscord erle: Yes, that's immensely useful 21:09 erle yes, but many others would evaluate 0 to falsy 21:09 MTDiscord But Lua isn't C 21:09 muurkha I think the best design is something like `a = 5` declares a new variable named `a` and errors if it's already in scope, while `set a = 5` changes the value of the existing variable `a` to 5 and errors if it's not already in scope 21:09 erle or python 21:10 muurkha Perl with `use strict;` is the closest I've encountered on this, but it spells them `my $a = 5;` and `$a = 5;` respectively, which is backwards and also has line noise in it 21:10 MTDiscord The truthiness is just a detail 21:10 erle come on, lua sucks big time 21:10 muurkha lua is pretty gret 21:10 MTDiscord muurkha: Backwards? This is the next big disagreement 21:10 muurkha *great 21:10 MTDiscord Should mutable or immutable be the standard? 21:11 MTDiscord Syntax-wise I'd prefer a := x or a = x for declaration and a = x for assignment 21:11 muurkha luatic: declaring new variables should be the default, mutating them an exception. I don't think you necessarily need to make them immutable 21:11 muurkha yeah, Golang does it the way you prefer 21:11 MTDiscord I know :) I like go 21:11 MTDiscord erle: Lua doesn't "suck big time" 21:12 MTDiscord Only Lua written by C programmers sucks big time 21:12 muurkha Lua has some real flaws, but it's a brilliant language 21:12 MTDiscord ^ 21:12 MTDiscord I have compiled lists of actual flaws 21:12 MTDiscord https://cdn.discordapp.com/attachments/749727888659447960/984565751283327026/Why_Lua_sucks.md 21:12 muurkha mine is short: 1-based indices, global by default, no integers 21:13 erle what lol 21:13 muurkha (unless you compile it without floats, which is worse) 21:13 MTDiscord erle: It's in my "heresy" folder :) 21:13 MTDiscord muurkha: why'd you want integers? 21:13 MTDiscord doubles are literally a superset of 32-bit itns 21:13 MTDiscord ints* 21:14 muurkha floating-point is a powerful and dangerous facility that should be reserved for the cases where it's necessary 21:14 MTDiscord Using doubles as ints is not dangerous at all. 21:14 erle check out my doubles 21:14 MTDiscord This just stems from the common misconception that floating point means "random inaccuracies in calculations" 21:14 muurkha addition and multiplication on 32-bit integers are commutative, associative, and distributive. none of those is true of floating-point 21:15 muurkha no, I've taken basic numerical analysis :) 21:15 muurkha while I don't want to say I know what I'm talking about, my level of not knowing what I'm talking about is a little higher than *thta* 21:15 muurkha *that* 21:15 MTDiscord good 21:15 MTDiscord Still, I don't see any issues with floats 21:15 MTDiscord You don't get weird overflow behavior 21:16 muurkha you do, actually 21:16 MTDiscord (instead you get inaccuracies and eventually +inf) 21:16 muurkha you get cases where x ~= 0 but x + y == y 21:16 MTDiscord Yes 21:16 muurkha that's weird overflow behavior and sometimes it results in nonterminating computations 21:16 muurkha I don't think there's a perfect solution to overflow, just tradeoffs 21:17 MTDiscord When possible use fractions instead of floats ;) 21:17 MTDiscord https://github.com/TheAlgorithms/Lua/blob/main/src/math/fraction.lua 21:17 erle issues with floats: everybody gangsta until NaN 21:17 muurkha heh 21:17 erle issues with ints: everybody gangsta until integer overflow 21:17 muurkha my first program in Smalltalk rendered a Mandelbrot set, and I couldn't figure out why it became unusably slow after 15 iterations or so 21:17 MTDiscord seriously though muurkha, you can trivially emulate uint behavior just by doing % 2^32 after each op 21:18 muurkha yes, that is true 21:18 MTDiscord but normally you won't want this 21:18 MTDiscord because you know that all your integer numbers (including intermediate results) will fall in the 2^52 range which is represented accurately 21:18 muurkha well, it's a better tradeoff for some applications, but yes 21:19 muurkha so my Smalltalk would approximate a Mandelbrot just fine at 10 iterations 21:19 muurkha and 11, 12, 13 21:19 muurkha at 14 iterations it got slow 21:19 muurkha at 16 iterations it was four times as slow 21:19 muurkha at 17 iterations it was even slower, unusably so 21:20 muurkha finally I figured out what the problem was 21:20 muurkha I was calculating the pixel increment by dividing the view range (-2 to 2) by the number of pixels 21:20 muurkha as it happened my view range was integers. in Smalltalk dividing integers gives you a fraction 21:21 muurkha guess what happens when you repeatedly square a fraction? the numerator and denominator double in length on every iteration 21:21 MTDiscord bigint moment 21:21 MTDiscord Python programmers nowadays often run into similar issues 21:21 muurkha and Smalltalk, like most Lisps and recent versions of Python, handles overflow by transparently failing over to, yes, bigints. arbitrary precision 21:22 MTDiscord bigints just violate the assumption that arithmetic ops are constant time 21:22 muurkha from a semantic Lisp-programmer point of view this is the perfect solution to overflow 21:22 muurkha but I did not think it was perfect 21:22 muurkha inserting a ".0" in my program made it render the Mandelbrot instantly 21:22 MTDiscord much like all these spread operators etc. today or ops on string obstruct the hidden runtime cost 21:23 Pexin < muurkha> luatic: declaring new variables should be the default, mutating them an exception. 21:23 Pexin ^ u wot 21:23 MTDiscord garbage collection also hides complexity 21:23 muurkha yeah, but usually it's not an exponential factor as it was in this case 21:24 MTDiscord anyways erle: If you want more quirks, just try math.random(2^40) on PUC Lua ;) 21:25 muurkha Pexin: take a look at a piece of your code and look at how many places you'd have to insert `set ` if you were programming in a language designed the way I suggest. you'll be surprised how few it is 21:25 muurkha pre-Golang I would have suggested `a = 5` for the definition and Pascal-style `a := 5` for the mutation 21:25 Pexin as a C++ person, I'd use #defines or const in those cases 21:26 Pexin variables exist to be variable 21:26 muurkha in C++ you might be right, though I do see a pretty large number of const declarations in C++ 21:27 MTDiscord := for mutation? sorry but that's gross 21:27 muurkha that's what Pascal uses, luatic 21:27 MTDiscord := is mathematically always used for definitions 21:27 muurkha sorry, I didn't do it 21:27 MTDiscord "let x := the number of ..." 21:27 MTDiscord muurkha: then don't repeat it ;) 21:28 muurkha well, like I said, I think post-Golang it's not a reasonable solution 21:28 muurkha `set a = 5` or `now a = 5` is 21:28 MTDiscord pascal also brought the evil of code-data distinction upon programmers 21:28 muurkha or `a <- 5` if you don't have chans 21:28 muurkha luatic: how much memory does mushing together hashmaps and lists really cost? I have the sense that lists in Lua use a lot less memory than in Python or Perl 21:29 MTDiscord muurkha: considering that both parts start at size 0: not much 21:29 muurkha you mention it as one of the defects of Lua 21:30 muurkha program and data have been distinct since before stored-program computers; unifying them was Turing's great insight 21:30 MTDiscord not compared to Python though 21:30 MTDiscord muurkha: basically I was writing a character set 21:31 MTDiscord Something that could trivially fit into 32 bytes (256 characters) 21:31 muurkha as a bitvector you mean? 21:31 MTDiscord now the idiomatic Lua data structure for this would be a table, specifically the hash part 21:31 MTDiscord as a bitvector, yes 21:31 muurkha yeah 21:31 MTDiscord you can emulate it using a bitstring 21:31 muurkha I agree that Lua's implicit coercion is pretty problematic, and in particular `nil` 21:31 MTDiscord but it's not nearly as convenient 21:32 muurkha so maybe I should update my list to: 1-based indices, global by default, no integers, implicit coercion 21:32 sfan5 what about immutable strings 21:33 muurkha immutable strings can be argued either way, like most immutable things 21:33 MTDiscord the memory savings are neat 21:33 MTDiscord but a consequence is that string building is gross 21:33 MTDiscord you can use a rope, sure 21:33 muurkha it would be a lot less problematic if reading a nonexistent table entry returned you an error object containing the message "nonexistent table entry `choppy` at wurble/init.lua:47" instead of nil 21:34 MTDiscord 8x memory consumption when you write character-wise though 21:34 MTDiscord muurkha: You can set a metatable if you want that behavior ;) 21:34 muurkha you can amortize that by auto-compacting your rope leaves 21:34 muurkha you can, except that Lua doesn't have error objects 21:34 MTDiscord muurkha: Yes, but then you create lots of garbage strigns again 21:35 muurkha that's true, but doesn't the Lua GC deal pretty well with high allocation rates of small short-lived objects? 21:35 MTDiscord Fun fact: Lua actually even has a builtin string builder, but you don't get to use it ;) 21:35 muurkha haha 21:35 MTDiscord Except if you happen to be gsubing something 21:35 MTDiscord If you can use gsub, use gsub, don't roll your own ;) 21:36 MTDiscord Mhm, GC 21:36 muurkha I think LPeg answers the pattern-matching limitations pretty well 21:37 muurkha like, most languages don't have anything similar to LPeg 21:38 MTDiscord No, not the LPeg 21:38 MTDiscord not the LPeg 21:39 MTDiscord it scares us 21:39 muurkha regexps, guns, and floating-point are in the category of "powerful tools that should be reserved for uses where they are justified" 21:39 MTDiscord I'll take proper RegEx + CFG over LPeg any time 21:39 MTDiscord PEG is the kind of grammar with the least theory behind it 21:40 MTDiscord regular grammars are safe to use if you know how to use them 21:40 muurkha PEGs are both more powerful (usually) and safer than regular expressions 21:40 MTDiscord What? 21:40 muurkha most regexp engines have exponential-time blowup problems 21:40 MTDiscord Not at all 21:40 MTDiscord That's on the engines 21:40 muurkha sure 21:40 MTDiscord Actual regular expressions can be matched in linear time in the size of the input 21:40 MTDiscord And decent engines like those of Go or Rust do it that way 21:40 MTDiscord Or the PoC engine I'm writing in Lua :) 21:41 MTDiscord That's how I stumbled on the charset problem BTW 21:41 MTDiscord Naive charsets take up 2kB per full charset 21:41 muurkha it's true that PEGs are not all that analytically tractable. I was surprised to learn a few weeks ago that even the question of whether a PEG production can match the empty string is undecidable 21:41 muurkha but there's actually a fair bit of theory behind them 21:41 MTDiscord because 8 + 8 bytes for each k/v pair 21:41 muurkha that's a lot 21:43 muurkha here's a thought about csets: √256 = 16. what if you have a table with 16 entries, each of which is "none", "all", or a 16-bit bitvector? 21:43 muurkha this is obviously dumb for 256 characters I guess, and not adequate even for 65536 21:44 MTDiscord Lua uses UTF-8 so I don't care about 2^16 ^.^ 21:44 MTDiscord I did in fact consider just splitting at 4-bit nibbles 21:44 muurkha heh 21:44 MTDiscord But it'd make the implementation significantly more gross 21:44 MTDiscord Also TBF a couple kB for RegEx are fine xD 21:44 muurkha I've done a little work on Hammer, a PEG engine that supports matching arbitrarily aligned bitfields 21:45 muurkha well, I shouldn't say it's a PEG engine 21:45 muurkha since it also has other backends including LALR, if your grammar is LALR-compatible 21:47 muurkha nibblematching might be a good approach if you were going to run your matcher in hardware, with a ROM driving a state register like the Apple ][ disk drive 21:48 muurkha does LuaJIT do a reasonable job of compiling the obvious code for indexing into a 32-byte bitvector? 21:49 MTDiscord yes 21:49 MTDiscord in fact it's faster than indexing the hash table 21:49 muurkha good! 21:49 MTDiscord despite using numerous ops 21:49 muurkha in theory having a decent JIT backing your DSL could be a big win for DSL implementations: compile your regexp into Lua or JS or whatever, then hope the JIT compiler does a good job of compiling that into efficient binary code 21:50 muurkha but every time I've tried it, for example in http://canonical.org/~kragen/sw/dev3/sweetdreams.html, I've been disappointed 21:50 muurkha which probably is because I was hoping to not have to understand how the JIT compiler works at a deep level 21:52 muurkha compiling to naïve C and then feeding it to GCC and dlopen()ing the result sometimes works better 21:54 muurkha (I know that page is mostly about the C++ version of the softsynth; I'm talking about the part where I say, "I also wrote a JS version in Node.js which compiles the dataflow graph into a JS function in order to take advantage of runtime code generation. Instead of being faster than the C++ version, it’s about 10× slower. That’s still twice as fast as when it was just interpreting the dataflow graph 21:54 muurkha the way the C++ version does, and 20× as fast as my first JS draft, where I had totally messed up the buffering." 21:54 muurkha ) 21:55 muurkha LuaJIT is really great at dlopen()ing things!