Programming thread

  • 🐕 I am attempting to get the site runnning as fast as possible. If you are experiencing slow page load times, please report it.
do you guys recommend the javascript version of sicp (i fw procedural languages more than functional) or should i man up and read the original?
wtf? both javascript and scheme are functional languages and scheme happens to be one of the easiest programming languages to learn out there
i have never in my life heard anything good about javascript sicp
so just get an editor that can match parentheses and any scheme interpreter and start working
new users aren't as mindraped by the complexities of metaprogramming
idk if that worked tbqh
 
How the fuck is JS a functional one? Sure it has some half baked functional collection functions, but its fundamentally not a functional one.
I mean, it's ultimately a quarrel about words.

In some perspectives, because Javascript has lambda (function in Javascript), that's enough to make it a functional language, albeit a shitty one. Other people would expect a richer collection of features to fit traditional functional programming better. Like maybe standard library features that make it easy to do your typical map/fold stuff with immutable collections.

Functional programming is probably best referred to as a style that you can program in in many languages. Some languages are better suited or specifically designed to make functional programming easy, but that's probably less useful to argue about.
 
How the fuck is JS a functional one? Sure it has some half baked functional collection functions, but its fundamentally not a functional one.
it has lambdas, higher-order functions, and lexical closure
it also has a bunch of other random shit but it has those 3 things
since scheme is 99% composed of higher-order lambdas with lexical scoping, i'd say javascript qualifies as a functional language
I mean, it's ultimately a quarrel about words.

In some perspectives, because Javascript has lambda (function in Javascript), that's enough to make it a functional language, albeit a shitty one. Other people would expect a richer collection of features to fit traditional functional programming better. Like maybe standard library features that make it easy to do your typical map/fold stuff with immutable collections.

Functional programming is probably best referred to as a style that you can program in in many languages. Some languages are better suited or specifically designed to make functional programming easy, but that's probably less useful to argue about.
the javascript dom has historically involved passing higher-order functions around like it's going out of style, but now they are using modern promise features and the syntax sugar that usually comes with that

also isn't js historically based on scheme?
 
https://jsdate.wtf/ -- If you want a glimpse into the insanity of Javascript, here's a quick 28 question quiz. (I got 9/28.)
Jesus Christ.

I've done professional work where I've had to work with the JS Date class. It's a real miserable piece of shit.

I got 14/28 on this quiz, but I was basically just clicking randomly for most of them.
 
now let's see paul allen's scheme's business card standard date library
scheme wizards in thread: how much does srfi 19 suck?
 
  • Feels
Reactions: Belisarius Cawl
https://jsdate.wtf/ -- If you want a glimpse into the insanity of Javascript, here's a quick 28 question quiz. (I got 9/28.)
1752444162048.webp

I feel ashamed to get that many right.

Also at question 9... What the actual fuck?
 
So recently I started playing with some Scheme+SDL+OpenGL. I think eventually I want to put together a little 2d game engine using a Lisp. I don't know if I'll make anything with it, but just messing around.

While I'm at it, I'm also wanting to get familiar with modern OpenGL. Years ago, I used to use the old fixed function pipeline, but I don't know anything about shaders, so I figure this would be a good exercise.

And I know SDL has an accelerated 2d API that uses OpenGL or whatever on the backend to draw sprites quickly, so it probably isn't strictly necessary for me to mess with OpenGL directly, but I think I want the flexibility as an option, even if in the end all I end up doing is drawing to rectangular sprites on a screen with some layering and transparency.

But of course, I'm starting small, so first of what I did was basically translate this tutorial literally to Scheme. I'm using Chicken Scheme because it's pretty portable, has a very good native compiler, lots of accompanying libraries, very nice FFI,

Wrote my own bindings to glew, SDL, and DevIL (for texture loading). There might be some existing Chicken bindings for some of these, but I often hate public bindings for big libraries like these. They often leave stuff out and it's a pain in the ass to put in a PR or possibly fork it and hamfistedly install an unofficial fork that isn't in the package repo of the language. A lot of the time I'll just say fuck it and keep my own handwritten bindings for these sorts of big libraries and keep them in the project itself, and set the import path to include ./.

Anyway, so I successfully did implement that tutorial (at least its simply little 2d hello world program in chapter 2).

Next step: for actual game development, I want to implement a tile renderer. I want to be able to give it some sprite sheets, then divvy them up into tiles, and allocate tiles that I can move around the screen. Also I want to have a camera matrix (could get by with just a vec2 and just scroll the display that way, but a full matrix won't hurt) to scroll the screen.

Honestly, these will require very few changes to the tutorial code. At least the shader code from the tutorial.

Really, it'll largely be a organization of the tutorial code into a more digestible library API. So make-tile-renderer initializes the OpenGL shaders and buffers, then there will be functions to allocate the tiles and whatnot. It'll be a big code reorganization.

So I wrote all of this and the code looks pretty great. It's pretty efficient, like so if you change one tile (say the character jumps, so you move its tile upward), it should patch in only the subset of the OpenGL buffer that changed, and not replacing the whole buffer. Things like that.

Except on my first attempt to run it, I get the dreaded black screen. This is always the worst, most annoying thing to debug when dealing with 3d graphics. Like there could be a bajillion different causes. Like maybe the 3d camera is just pointed into the black void of computer graphics. Your geometry is rendering, just you might've got some camera parameter wrong.

I checked OpenGL itself for errors and I think I got all the obvious ones. Still black screen.

So since I have the tutorial code showing something, and this tile code isn't too different, I think what I'm going to do, is the ridiculous, manual task of tracing every single fucking OpenGL call that my code makes and making note of the args and return values and comparing them.

I'm doing that now.

If anyone's interested, here's a snippet of the matrix code I wrote for this project:
Btw, I'm a programmer, but not really natively the most mathematically inclined. I learn enough mathematical theory to navigate a particular problem, but that's about it. So this is an unmathematical person's approach to matrices.

Also even though Chicken's compiler is pretty boss, I generally don't intend to do much elaborate number crunching in Scheme itself. Most of that should be done in OpenGL. This matrix library is intended to be used to initialize the camera matrix when the program starts, and I'll just rig up something a lot simpler to manage the matrices for use during the actual main loop.

Code:
(import (srfi-4)
        (srfi-1)
        (defstruct))

(defstruct matrix
  dimensions
  data)

(define (matrix-flat-index mat idx)
  ;; ok, so
  ;; if we've got
  ;; X Y Z
  ;; D E F

  ;; so column major ref (a b)
  ;; (+ b (* a height))

  (+ (cadr idx) (* (car idx) (cadr (matrix-dimensions mat)))))

(define (->inexact x)
  (if (exact? x)
      (exact->inexact x)
      x))

(define (matrix-set! mat idx val)
  (set! (f32vector-ref (matrix-data mat) (matrix-flat-index mat idx)) (->inexact val)))

(define (%matrix-ref mat idx)
  (f32vector-ref (matrix-data mat) (matrix-flat-index mat idx)))

(define matrix-ref (getter-with-setter %matrix-ref matrix-set!))

(define (identity-matrix dim)
  (let* ((data (make-f32vector (apply * dim) 0.0))
         (res (make-matrix data: data dimensions: dim)))
    (for-each
     (lambda (idx)
       (set! (matrix-ref res (list idx idx)) 1.0))
     (iota (apply min dim)))
    res))
    
(define (zero-matrix dim)
  (make-matrix data: (make-f32vector (apply * dim) 0.0) dimensions: dim))

(define (matrix-multiply a b)
  (let* ((dim (list (car (matrix-dimensions b)) (cadr (matrix-dimensions a))))
         (res (zero-matrix dim)))
    (for-each
     (lambda (x)
       (for-each
        (lambda (y)
          (for-each
           (lambda (z)
             (set! (matrix-ref res (list x y))
               (+ (matrix-ref res (list x y))
                  (* (matrix-ref b (list x z))
                     (matrix-ref a (list z y))))))
           (iota (cadr (matrix-dimensions b)))))
        (iota (cadr dim))))
     (iota (car dim)))
    res))

(define (ortho-matrix #!key left right far near top bottom)
  (let ((res (zero-matrix '(4 4))))

    (set! (matrix-ref res '(0 0)) (/ 2 (- right left)))
    (set! (matrix-ref res '(1 1)) (/ 2 (- top bottom)))
    (set! (matrix-ref res '(2 2)) (/ -2 (- far near)))
    (set! (matrix-ref res '(3 3)) 1)

    (set! (matrix-ref res '(0 3)) (- (/ (+ right left) (- right left))))
    (set! (matrix-ref res '(1 3)) (- (/ (+ top bottom) (- top bottom))))
    (set! (matrix-ref res '(2 3)) (- (/ (+ far near) (- far near))))

    res))

When I get something interesting, I'll post the full project at some point.
 
today i fixed the problem i was struggling with for days
turns out i put uint8_t * instead of uint32_t *

in my defense ive been using a lot of uint8_t *'s recently...
As a piece of advice, use typedef aliases or #define, it's a lot easier to modify types when you give each context its own name. It can definitely be bloated, but having that flexibility is helpful, and having named types makes self-documentation more clear. It's also nice because you can hook it into autotools and just run something like ./configure -DMY_TYPE uint8_t without opening your code
 
Except on my first attempt to run it, I get the dreaded black screen. This is always the worst, most annoying thing to debug when dealing with 3d graphics. Like there could be a bajillion different causes. Like maybe the 3d camera is just pointed into the black void of computer graphics. Your geometry is rendering, just you might've got some camera parameter wrong.
Eyyy, I solved the black screen issue!

And I almost posted a blubbery post about how I solved it but the code was still broken in another way and it was driving me nuts, because this is what I was getting:
1752549445798.webp

Ok, so, with my first demonstration of my new tile renderer, I added a "tileset" containing a single tile that takes up the full size of the image, and that's the same image from the original tutorial I was basing things on. So that's what we're trying to test.

I eventually figured out that the black screen was indeed because the geometry was in the wrong place relative to the camera.

For some reason, putting the sprite at a -0.5 depth causes it to display, but at 0.5 it vanishes. This doesn't make sense because I have my ortho projection matrix set to have the near and far planes at 0 and 1. I have no clue why making it -0.5 causes it to suddenly pop into view. But I'll debug that more with that later. It's at least working for now.

More worrying was why that chunk is missing. That's fucking weird.

So I'm rendering this using GL_TRIANGLES. A rectangular tile would be two triangles. And I'm counting the vertices clockwise from the upper left. So to use some ascii art:
Code:
0 ----- 1
|       |
|       |
3 ----- 2

So I was rendering two triangles, 0,1,2 and 1,2,3.

I was pulling my hair out trying to figure out where I fucked up. And I was even reading my element index code over and over, looking straight at it. Somehow I can't count.

As should be obvious now, it should be 0,1,2 and 2,3,0 (or cycle it how you wish).

I actually just solved it a moment ago after I made that little ascii drawing for this post. Having the visual aid made me realize where I fucked up.
1752552808445.webp

This is what that working code looks like:
Code:
(define (tile-assign-indices! tile)
  (let* ((spec (tile-tile-spec tile))
         (set  (tile-spec-tileset spec))
         (coll (tileset-tile-collection set)))

    ;; element buffer
    (let ((buffer-data      (tile-collection-element-buffer-data coll))
          (elem-idx         (tile-element-buffer-index tile))
          (array-buffer-idx (tile-array-buffer-start-index tile))
          )
      (set! (u16vector-ref buffer-data (+ elem-idx 0)) (+ array-buffer-idx 0))
      (set! (u16vector-ref buffer-data (+ elem-idx 1)) (+ array-buffer-idx 1))
      (set! (u16vector-ref buffer-data (+ elem-idx 2)) (+ array-buffer-idx 2))

      (set! (u16vector-ref buffer-data (+ elem-idx 3)) (+ array-buffer-idx 3))
      (set! (u16vector-ref buffer-data (+ elem-idx 4)) (+ array-buffer-idx 0))
      (set! (u16vector-ref buffer-data (+ elem-idx 5)) (+ array-buffer-idx 2))
      )
     
      ;;; ... function continues filling in various other opengl buffers, like for the verts and texture coords
This is a function internal to the tile-collection library that first initializes the chunk of the OpenGL buffers when a new tile is allocated.

Well I'm pleased with this success. It's always very satisfying to solve a problem before bed. Or sometimes staying up later than usual to solve it.
 
Yes, the Brave dude wanted scheme as language for Netscape. However because of raising popularity of Java at that time C-Suite wanted something like Java, hence JavaScript was born. Abomination of language that wanted to be Scheme with Java syntax.
I've also noticed a lot of mostly bad features taken from Perl 5, including 'use strict'; to ensure that the interpreter does what it already ought to. There are a lot of influences actually:
Basically I can't help but think of something I posted over in the thread for bitching about niggers:
el-mestizaje-en-américa.webp
JavaScript is "El Ogro de las Américas"
 
Back