Programming thread

But anything that requires it exclusively makes me really hate it. I also think you should try and avoid it unless you either have a lot of experience in doing a particular thing or you have made enough of what you are doing that you can make a good implementation of it.
Might be a matter of knowing the right design patterns etc.
In other news, I’m the pointers and arrays part of K&R and I’m starting to get lost. I get the basic premise of pointers and how they can be used with arrays (reminds me of a foreach loop which is useful). But I feel like I’m missing some stuff. Any good supplemental material on pointers?
I found Deep C Secrets quite helpful
If I was going to gamedev in a functional-ish language, I'd use Scheme with a CLOS-style OOP system.
Guile has GOOPS. Racket is probably better suited for game dev and has Swindle but it doesn't seem to be well-documented.
 
Last edited:
  • Like
Reactions: Marvin and y a t s
Dependency injection is the best anti-debugger technique you can get without resorting to tricks with inline assembler and IRQ hooks.
Dependency injection forces or at the very least encourages SOLID. It's hard to fuck up the rest of your program if you write tests while developing at that point.
 
  • Informative
Reactions: Belisarius Cawl
In other news, I’m the pointers and arrays part of K&R and I’m starting to get lost. I get the basic premise of pointers and how they can be used with arrays (reminds me of a foreach loop which is useful). But I feel like I’m missing some stuff. Any good supplemental material on pointers?

They're such a fundamentally primitive thing, that there isn't much to miss. A pointer is a memory address, pure and simple. These days, it's usually a 64-bit value. It "points" to a place in memory. The type of a pointer tells you what sort of data you expect to find there, and how the program should behave when it loads data from that location.

They make a lot more sense when you think about what the computer is physically doing. It goes to memory, it fetches data, it does shit with data. All a pointer does is pass around a memory address with a tag telling the program what it should fetch from there, how it should count things at that location, etc.
 
Yeah, I've messed with GOOPS before, it's nice.

Though the annoying thing about Guile, at least for gamedev, is that it's rigidly tied to Unix APIs. Like you can get it running but with stuff like MinGW.
Apparently Racket has a very decent cross-platform GUI library and, for something as sophisticated as a GUI library, I would imagine most other standard libraries are cross-platform, with obvious exceptions like Unix sockets. Perhaps you can learn Swindle with prior exposure to CLOS and GOOPS.
They're such a fundamentally primitive thing, that there isn't much to miss.
There are definitely subtleties like array decay.
 
Last edited:
  • Like
Reactions: y a t s and Marvin
Yeah, I've messed with GOOPS before, it's nice.

Though the annoying thing about Guile, at least for gamedev, is that it's rigidly tied to Unix APIs. Like you can get it running but with stuff like MinGW.
Guile can also cause some pretty nasty problems due to its design on the low level. For example if you embed Guile you'd better be sure your host application's runtime doesn't ever setjmp, because Guile sure does and relies on longjmp to handle things like continuations.
 
Apparently Racket has a very decent cross-platform GUI library and, for something as sophisticated as a GUI library, I would imagine most other standard libraries are cross-platform, with obvious exceptions like Unix sockets. Perhaps you can learn Swindle with prior exposure to CLOS and GOOPS.
Yeah, there are definitely options. It's mostly just a lack of time, what with work and whatnot.
Guile can also cause some pretty nasty problems due to its design on the low level. For example if you embed Guile you'd better be sure your host application's runtime doesn't ever setjmp, because Guile sure does and relies on longjmp to handle things like continuations.
Oh weird. I wouldn't have thought that necessary considering guile is a bytecode implementation.

I used to really like chicken. Chicken's a really interesting scheme-to-c compiler and it does that setjmp/longjmp stuff. Basically at the end of every function, it just calls the next function so the C stack grows indefinitely, and when it finally runs out of space, it zips down the spine of the stack, GC'ing everything and does the setjmp/longjmp stuff to reset the stack.
Appel's unpublished suggestion for achieving proper tail recursion in C uses a much larger fixed-size stack, continuation-passing style, and also does not put any arguments or data on the C stack. When the stack is about to overflow, the address of the next function to call is longjmp'ed (or return'ed) to a trampoline. Appel's method avoids making a large number of small trampoline bounces by occasionally jumping off the Empire State Building.
I'm just smart enough to vaguely understand this. Certainly not smart enough to implement it.

But chicken's ffi is very elegant and usable, including little macros that let you embed C code directly in scheme (assuming you're compiling the file).

I miss my scheme days. I'm just so busy doing dumb shit with Go, Python and Javascript for work nowadays, I just finish my workday and don't want to look at another line of code again. (Go's absolutely the least retarded mainstream language I work with)
 
Where do you learn stuff like this?
In short, from seeing Guile put in places it probably doesn't belong. Exceptions and Smart Pointers both usually rely on longjmp. Guile of course supplies scm_throw and garbage collection so freestanding programs have to go out of their way to run into any ugliness. Though, the moment you want to play around with Scheme in an engine or framework that provides its own memory management and error handling they will step on each other's toes and you absolutely will throw exceptions into a continuation, catch exceptions that were never thrown and dereference prematurely free'd resources.
 
Usually by running into the issue and tearing your hair out for five hours.
I more so meant more specifically what leads you to embed Guile or anything like it in a C application so that you reach that point. But other than that yeah I am ready to mald:
40k-evolution-of-horus.png
In short, from seeing Guile put in places it probably doesn't belong. Exceptions and Smart Pointers both usually rely on longjmp. Guile of course supplies scm_throw and garbage collection so freestanding programs have to go out of their way to run into any ugliness. Though, the moment you want to play around with Scheme in an engine or framework that provides its own memory management and error handling they will step on each other's toes and you absolutely will throw exceptions into a continuation, catch exceptions that were never thrown and dereference prematurely free'd resources.
Have you had any experience with embedding Lua? A lot of people seem to have a high opinion of it in that context.
 
  • Like
Reactions: y a t s
Where do you learn stuff like this?
Usually by running into the issue and tearing your hair out for five hours.
Aside from troubleshooting, a lot of my low-level knowledge comes from poking around in disassemblers and debuggers. Reverse engineering firmware for embedded devices and malware (if you're super careful about it) can teach you a lot of little esoteric tidbits and tricks used to implement certain features. You get to see a lot of that classic human ingenuity that has sadly been dying off and obscured with the rise of black box silicon chips that last a year or two at most.

I more so meant more specifically what leads you to embed Guile or anything like it in a C application so that you reach that point.
For me, this can usually be summed up quite nicely by a classic Portal 2 quote:
Cave Johnson said:
Science isn't about "Why?", it's about "Why not?".
 
Have you had any experience with embedding Lua? A lot of people seem to have a high opinion of it in that context.
Personally a little experience. The main reason why its spoken highly of is it was (successfully) designed with that specific purpose in mind,

Its not hugely different from any other scripting languages API, one difference is you can configure what the base 'number' type is in the language (by default it uses doubles). Otherwise you can get pointers to lua obejcts and manipulate them, there are facilities to create lua objects in non-script land and to hand them back into script land, you can create lua functions that execute compiled code (so you can wrap your real functions in lua functions), you can call lua scripts from the compiled code and get results back.

The main difference is that its pretty high performance in doing all of this compared to other languages. The interpreter runs quite fast, so you can somewhat more reasonably call a lua script from binary land and get the results back in a timely manner (and in particular in a relatively consistent amount of time)
 
  • Like
Reactions: Belisarius Cawl
Back