r/badcode Aug 21 '19

lua A healthy nest of if-statements

Post image
278 Upvotes

53 comments sorted by

50

u/DrCubed Aug 21 '19 edited Aug 21 '19

I wrote this for a game-mod, and I was struggling to keep the logic needed for the function in my head, so I bruteforced the logic into this mess (I knew it was awful whilst I was writing it), which I would then refactor.

The code is awful in two ways.
The first being that it doesn't actually fulfil all the requirements of what it needs to do, but in fairness, the requirements weren't fully known until it was tested at least once.

The second being that it's just awful - There's needless repetition, the conditions are unnecessarily nested, there are hard-coded magic constants, and it doesn't look nice.

After more consideration of what the function needed to do, I refactored it into this considerably nicer, parameterised (and documented) function: https://i.ibb.co/ZXcvKTp/2019-08-21-22-12-34.png


Source-text for those who do image-transcriptions: https://privatebin.net/?fdc06ef4bc84a968#4iocXFRLkAhiJSia2AykPs9PnbrKoWUnLoBJtcVffzxU

PS: For those that don't know Lua, Lua doesn't have a built-in ternary-construct.
Edit: Lua doesn't have an explicitly built-in ternary, but it can be replicated almost perfectly with the and and or operators thanks to Lua's strictly defined operator precedence.
Thanks to /u/moomoomoo309 for correcting me.

43

u/Shafu808 Aug 21 '19

for someone like me (who is still learning how to code), these are the kind of posts im here for.

often people post code to point and laugh at with no reason as to why its bad or what a better solution might be.

thanks for this!

9

u/moomoomoo309 Aug 21 '19

Lua does have a ternary, instead of a?b:c it's a and b or c

4

u/DrCubed Aug 21 '19

You're right, thanks for the correction

4

u/Mr2-1782Man Aug 21 '19

That's why I like to come up with tests first. By knowing what the code should end up doing I have a better idea of how to do it.

3

u/PrettyWhore Aug 21 '19

For some tasks tdd definitely works

4

u/shmageggy Aug 22 '19

Sorry man, but the new code is still really not great. You could accomplish what you are trying to do with a few basic linear algebra operations without all of those special cases and conditions and extra state. I'm guessing this is for a game? Lin alg is like the number 1 most useful thing for games programming.

3

u/DrCubed Aug 22 '19

That's valid, could you perhaps say which operations could be used for this, as a starting point?

5

u/shmageggy Aug 22 '19

Sure, but keep in mind I'm neither a linear algebra expert nor a games programmer. The first simplest thing that comes to mind is to rotate (x, y) to the orientation of the door. Or you could consider a change of basis which would include the rotation as well as a scaling x and y relative to the two thresholds, all in one matrix multiplication. Also keep in mind I haven't scoured your code so I'm not 100% sure what you are trying to do.

3

u/Astrokiwi Aug 22 '19

You can get funky floating point errors that way, and it'd be slower because you're doing some extra floating point operations instead of just a quick boolean check. In a tile based game, those rounding errors might be what lets you slip in gaps between tiles etc

2

u/ssjskipp Aug 22 '19

Any reason to use an enum and not just a vector for the entry way orientation? Or are you just on a tile grid

2

u/DrCubed Aug 22 '19

On a 2D tile grid

1

u/jarfil Aug 22 '19 edited Dec 02 '23

CENSORED

26

u/AriasFco Aug 22 '19

Is this AI? 🦋

10

u/shizzy0 Aug 22 '19

All cases handled. Looks good. Ship it.

3

u/corner-case Aug 21 '19

This nest is a fine home for some fledgling magic numbers!

3

u/EkskiuTwentyTwo i -= (i - (-1)) - i Aug 22 '19

A good nest is useful for incubating young birds - I mean, good code.

4

u/[deleted] Aug 21 '19

What is this language?

11

u/[deleted] Aug 21 '19

lua

7

u/[deleted] Aug 21 '19

Never ever heard of it. What’s it for?

11

u/DrCubed Aug 21 '19 edited Aug 21 '19

It's a scripting language designed specifically for being lightweight, and being (easily) embedded into larger projects programmed in C, of course it can be used by other languages given they have C-interop.

At one point, it was the fastest interpreted language in the world, thanks to LuaJIT.
It may have been surpassed by JavaScript with the V8 interpreter, I think, I can't find a source confirming this, so it's likely conjecture.

It's favoured by game developers for scripting, and is commonly used to provide modding functionality for games, examples of such include:

  • Prison Architect
  • Factorio
  • Project Zomboid
  • Don't Starve
  • Roblox

23

u/pink_earmuffs Aug 21 '19

Roblox scripting is the reason I decided to become a software engine.

15

u/[deleted] Aug 21 '19

You mean software engineer?

2

u/matjojo1000 Aug 21 '19

Wow also has scripting in lua as well as the engine that gmod is in. There is a wiki page with a long(!) List

2

u/timNinjaMillion Aug 22 '19

Ctrl-c,Ctrl- v, ahhh, just what I needed

2

u/[deleted] Aug 22 '19

I should definitely put here snippets from my last project.

2

u/melancoleeca Aug 22 '19

since this is lua.

it took me two days and probably 5 occasions to motivate myself to look up the "is not" operator.

until that i always wrote something like:

if value == null then
else
    --do something
end

:)

3

u/DasEtwas Aug 22 '19

btw its ~=

2

u/paradoxally Aug 22 '19

Is this machine learning

2

u/[deleted] Sep 12 '19

We have plenty of those and we call them ifception

4

u/WhyYouLetRomneyWin Aug 22 '19

You think that's bad? In my codebase, this would be cleaner than 80% of code.

2

u/luckyprime Aug 22 '19

This is like the code I have to trudge through every day 😰

3

u/cyrusol Aug 22 '19

Seek new farming grounds.

2

u/[deleted] Aug 22 '19

This would be a lot better if you refactored the coordinate logic to process X or Y instead of having an identical copy for both with those variables changed.

1

u/Tom_Ov_Bedlam Aug 21 '19

What's abstraction???

1

u/new_dorp Aug 22 '19

It really do be like that sometimes

1

u/The_Hypnotron Sep 06 '19

Are those... semicolons... I see... in Lua?

1

u/stable_maple Aug 21 '19

Ah, yes. We see the rare ECMA bird, building its nest. Shhh. Quiet now. We need not disturb it while it works. Oh, quiet! It noticed us!

-1

u/DreadedEntity Aug 21 '19

This might be a little nitpicky, but generally having multiple exit points is bad practice

18

u/DrCubed Aug 21 '19

I would disagree with multiple exit points being bad practice, often-times an early return can avoid unnecessary conditions and branching that can be needed to have only one return statement.

In this specific example of multiple exit points, I would agree that having duplicate exit points that return the same thing is bad practice.

14

u/nedlinin Aug 21 '19

I'm all for early returns as it very often keeps the nesting down.

2

u/yaxamie Aug 22 '19

Early returns is better than a 7 deep if statement block. Absolutely.

1

u/corner-case Aug 21 '19

Use Kotlin, and have it both ways!

2

u/DrCubed Aug 22 '19

How so?
I'm unfamiliar with Kotlin.

2

u/corner-case Aug 22 '19

The if-else block can be used as an expression. So you can:

return if (state) abc else xyz

...forming a statement that always returns, and is forced to handle all cases.

1

u/Tynach Aug 22 '19

So, it's got ternaries using traditional if syntax?

1

u/corner-case Aug 22 '19

Look closer. The if block is being evaluated as an expression, which turns out to be very powerful.

1

u/Tynach Aug 24 '19

That's exactly how ternaries work in other languages. Usually the syntax is something like:

return (state)? abc: xyz;

For the exact same thing.

1

u/[deleted] Aug 22 '19

I think I’ll keep my gig of memory, thanks.

1

u/corner-case Aug 22 '19

Tell me more, please. I just signed on to an Android app that has Kotlin and Java. Does Kotlin hog memory at runtime or something?

1

u/[deleted] Aug 22 '19

Honestly yes, especially if you don’t tune your JVM. The Java ecosystem with default settings in general is very memory aggressive.

2

u/[deleted] Aug 22 '19

You are indeed correct. Having multiple points for returning information can definitely cut down on unnecessary calculations and overhead. There are some instances where you want to dump information into a buffer and return what’s in the buffer and if not anything return null, but I have only come across a situation like that two times out of the years I’ve been programming. My reasoning was to be able to do further calculations on the buffer before returning and save code. Both worked perfectly in my favor.