“Non profit” does not mean “Cannot make a profit.” It means the profit cannot be used for the benefit of individuals - such as owners or stockholders - and must instead go back into the non-profit purpose of the organization.
As I said many times to clients - a non-profit can make a profit. It just can’t use the profit for anything other than the charitable purpose (or in the case of a social club, for the benefit of the membership).
It is a “no-profit to the people who run it” organization. Not a “no profit period”
My internal lore:
(too generic, ugh it's gonna be boring...)
My paracosm:
(fancy name, what is this, ooooo shiny~)
So someone made this post on Mastodon:
https://infosec.exchange/@catsalad/116268399785747534
And that led another person to make this site: https://boat.horse/clock/index.html
This feels like some real old school internet stuff. For the younger folks out there, this is the kind of stuff that would pop up all the time on the internet in the late 90s and early 00s. No reason for it beyond it being cool and beautiful.
While the animated clock in the link sort of hurts my head, it still is beautiful.
I reported an insecure DKIM key to Deutsche Telekom / T-Systems. They first asked me to further explain things (not sure why 'Here's your DKIM private key' needs more explanation, but whatever...). Then they told me it's out of scope for their bugbounty.
I guess then there's really no reason not to tell you: They have a 384 bit RSA DKIM key configured at: dkim._domainkey.t-systems.nl
384 bit RSA is... how shall I put it? I think 512 bit is the lowest RSA key size that was ever really used. 384 bit RSA is crackable in a few hours on a modern PC (using cado-nfs). The private key is:
-----BEGIN RSA PRIVATE KEY-----
MIHxAgEAAjEAtTliQYV2Xvx1OGkDyOL799BTFEuobY2dn2AgtiKCQgrh78NVK1JK
j0yRXgNnPpGBAgMBAAECMF0t+TBZUCi8xATSMij7VLTxv5Xi5OIXesNiXOKtYIRP
LkpYfR5PggaMScfbmqSssQIZAMwOhm9d7Y7Qi7I2j1AlYbiqdtqO54T7FQIZAONa
9dJFkC6lM3EPXR+0SZ4dqwwpiM0nvQIYYgz8thi5JK264ohq9sTvnu9yKvUN9I09
AhgfgMYZKcxtujRjkSZtMzUUNLYzzDmJe90CGDKwqcBI0v9ChaR8WHht+/chMdxj
7ez94w==
-----END RSA PRIVATE KEY-----
the best medium to make art in is a medium that you have experienced as little of as possible, because that way you have no way of knowing if you’re doing a good job or not, so it’s much harder to hate yourself for making bad art
another great trick is to make art in a genre that you hate, copying it as closely as possible. that way your goal is already to make bad art so the only way you can fail is by accidentally making good art instead!
Finally finished the art of @JunkRaven , SEKHMET-class NHP, hanging out in her subaltern!
Here she is, chilling out at a bar/Horizon Collective clubhouse out somewhere in the Long Rim, with some of her buddies.
This one took a couple of months to finish. I don't think I've ever tried something this detailed, with so much going on in the background! (I'm bad at drawing environments.)
Layout primarily done in #Blender, poster designs done in #Inkscape, and everything else done in #Krita.
No generative AI was used to create this image.
@benjamingeer omg thank you! I’m so glad that you think so. and thanks for telling me about Fennel - if I didn’t already know about it it would’ve made my day lol
my priorities with a language like this would be:
(require) reuses the concept of (do), which would also be used in a lot of other places in the language)@benjamingeer I have and I absolutely love it - it might be my favorite Lisp ever. this idea was heavily inspired by Fennel, and by me missing a lot of its syntax and semantics when trying other Lisps
I’ve been thinking about how my ideal #Lisp would work, and I already know that I want it to have very similar semantics to #Lua. but I figured out some fun details. for example, ideally the only non-primitive data type would be Lua-style tables. which means that S-expressions would be converted by the reader into tables (not linked lists!)
so for example this S-expression:
(+ 1 2 (* 3 4))
would become the equivalent of this Lua code: (with 0-based indexes instead of Lua’s 1-based indexes because those are an affront to the machine spirits)
{
[0] = symbol("+"),
[1] = 1,
[2] = 2,
[3] = {
[0] = symbol("*"),
[1] = 3,
[2] = 4,
},
}
but of course a Lua table lets you have more keys than just numbers (it acts as a list and as a dictionary!), so I would have a syntax for that in the Lisp too:
(some-func [:some-arg some-value]
[:another-arg another-value])
{
[0] = symbol("some-func"),
[keyword("some-arg")] = symbol("some-value"),
[keyword("another-arg")] = symbol("another-value"),
}
which means that all functions get keyword arguments by default, with no hacks needed! it also provides a nice Racket-like syntax for certain forms:
(let ([foo some-value]
[bar another-value])
; code goes here
)
and IMO the biggest improvement from regular Lisp is that this language would have a special syntax for getting/setting a value from a table:
foo.bar.baz
; this ↑ gets turned into this ↓ by the reader
(. foo 'bar 'baz)
; ↑ which is the same as this ↓
(. (. foo 'bar) 'baz)
; you can also use it with functions like `set!`, `set`, `update!`, `update`, etc.
(define foo '())
(set! foo.bar '())
(set! foo.bar.baz 666)
foo ; -> '([bar ([baz 666])])
foo.bar.baz ; -> 666
(update! foo.bar.baz add1)
foo.bar.baz ; -> 667
of course I would also want to have metatables:
(define some-table '())
(set! (meta some-table)
'([foo bar]))
(meta some-table) ; -> '([foo bar])
and metamethods:
(define some-table '())
(set! (meta some-table)
'([:+
(λ (self other) "wait - this isn't doing addition!")]
[:+r
(λ (self other) "this isn't addition either!")]))
(+ some-table '()) ; -> "wait - this isn't doing addition!"
(+ '() some-table) ; -> "this isn't addition either!"
there would be a special case where the reader turns #this into a reference to the table that it’s currently inside of:
(define some-table '())
(set! (meta some-table)
'([:index #this]
[foo bar]))
(. some-table 'foo) ; -> 'bar
and it would also shamelessly steal “borrow” the absolutely incredible : syntax for calling methods in Lua:
(define some-table
(set (meta '([some-value 0]))
'([inc-some-value
(λ (self) (update! self.some-value add1))])))
(define inc-some-value
some-table:inc-some-value)
; this ↑ is equivalent to this ↓ (it automatically supplies `self`)
(define inc-some-value
(λ () (some-table.inc-some-value some-table)))
some-table.some-value ; -> 0
(some-table:inc-some-value)
some-table.some-value ; -> 1
(inc-some-value)
some-table.some-value ; -> 2
oh and importing would just execute the contents of the file you’re importing and then evaluate to the result of the last form! just like it’s inside of a (do) form:
; ./some-lib.kaslisp
(define lib '())
(set! lib.foo 12)
; this file now evaluates to the table called `lib`, because that's the last form (just like how a function works!
lib
; ./why-is-this-lib-a-number.kaslisp
; this one just evaluates to 666? that's a weird thing to do...
666
; ./main.kaslisp
(define some-lib (require "./some-lib.kaslisp"))
some-lib ; -> '([foo 12])
some-lib.foo ; -> 12
(require "./why-is-this-lib-a-number.kaslisp") ; -> 666
it just puts all the code inside of a function that takes no arguments, and then runs the function! so importing would have very simple easy-to-understand semantics
Be gay.
Do crimes.
Post about being gay.
DO NOT POST ABOUT DOING CRIMES.
It's quite simple.
short little update but I was intimidated by Racket’s macro system since it seems very magical and complex, so I hadn’t touched it at all until this point
but out of necessity I made some extremely basic macros in it using define-syntax-rule and you know what? it’s actually super easy. it’s definitely still magic (which I think is a bit of a travesty when Lisp makes macros so simple and intuitive compared to any other language) but it’s simple magic that’s easy to use
also, so far the struct -> OOP refactor is going really well! my code is much smaller, simpler, and easier to read already - though I haven’t completed the full refactor yet
@njion There have historically been seaweed used in Irish cuisine, but I don't think that's really a thing anymore. The only reason I know about it is cus there's a folk song about it. https://www.youtube.com/watch?v=3iRfI1ezYjA
Star Trek Resurgence is actively being delisted as the rights have expired. Snag it on PC or any of the consoles while you can. #StarTrek #Gaming #StopKillingGames
I’ve decided that I want to give #Racket another chance, and see if I can work out solutions to the problems that I ran into when trying to use it. it’s definitely the #Lisp that feels most practical to me out of everything that I’ve tried, and I still love the contract system and its specific take on threading macros
I remember that the error tracebacks were often missing important info, so I want to wait until that happens and see if I can figure out what the specific problem is/was
I was also trying to get some kind of static function signature checking, to make sure I was calling things right, but I’ve decided that I’m okay with relying on runtime errors (from contract violations) instead, as long as I can read the error tracebacks easily enough
another problem that I ran into while using it is that it feels clumsy and awkward to work with complex data structures
with Python I’m used to being able to nest objects pretty much arbitrarily deep, and have my LSP autocomplete all of the fields/methods at each step so I know exactly what type of data I have, and what I can do with it. with Racket that isn’t really the case - I need to flip through my source code in another split to remember what data I have at each step and how to transform it. I don’t think there’s a solution for this - I think I’ll just have to deal with this unfortunately
another aspect of Racket handling complex data structures clumsily is just that the syntax for drilling into a data structure is pretty noisy and long:
(~> some-data-structure
(get-field foo _)
(hash-ref "some-key")
(list-ref 0)
some-struct$-field)
compare that to most other languages, which would let you just write:
some_data_structure.foo["some-key"][0].field
this problem gets so much worse when you need to actually mutate the data, and even worse than that when it’s immutable. here’s a real function that I wrote in Racket: (it’s for a really basic clicker game)
(define/contract (game-state$-buy-autoclicker state ac-name)
(-> game-state$? string? game-state$?)
(define-struct-lenses game-state$)
(define-struct-lenses ac-slot$)
(define &ac
(lens-compose (&hash-ref ac-name) &game-state$-autoclickers))
(define ac-cost
(~> (&ac state)
ac-slot$-cost))
(printf "buying autoclicker ~a for cost ~a\n" (&ac state) ac-cost)
(define &ac-num-owned
(lens-compose &ac-slot$-num-owned &ac))
(define new-state
(~> state
(game-state$-clicks-update (-= ac-cost))
(lens-update &ac-num-owned _ (+= 1))))
(if (negative? (game-state$-clicks state))
(error "not enough clicks to buy this autoclicker")
new-state))
pretty much all it’s doing is this:
class GameState:
def buy_autoclicker(self, ac_name):
ac = self.autoclickers[ac_name]
cost = ac.get_cost()
print(f"buying autoclicker {ac} for cost {cost}")
if cost > self.clicks:
raise Exception("not enough clicks to buy this autoclicker")
ac.num_owned += 1
self.clicks -= cost
but the combination of nested data and immutability make it a huge mess in Racket
I’m definitely open to suggestions for how I can make this type of code shorter and easier to read, but for the moment here’s what I’m going to try:
I’m going to stop using structs completely in favor of classes, because classes are a great way to have mutability (which fixes the immutability problem) which is neatly contained in a way that can be easily unit-tested, and the syntax and semantics for dealing with classes are often shorter, simpler, and more consistent too
I’m also going to see if I can make a series of general-purpose “get/set/update the data in this nested data structure” forms:
(get-in some-data '(0 3 field-name "some-key"))
; returns some_data[0][3].field_name["some-key"]
(set-in some-data '(0 3 field-name "some-key") "new-value")
; returns a version of some_data with the specific data changed
; etc.:
(set!-in some-data '(0 3 field-name "some-key") "new-value")
(update-in some-data '(0 3 field-name "some-key") (+= 1))
(update!-in some-data '(0 3 field-name "some-key") (+= 1))
that way, my very first example would look like this instead:
(get-in some-data-structure '(foo "some-key" 0 field))
and I could refactor my function into a method that looks like this:
(define (buy-autoclicker ac-name)
(define ac (hash-ref autoclickers ac-name))
(define cost (send ac get-cost))
(printf "buying autoclicker ~a for cost ~a\n" ac cost)
(when (> cost clicks)
(error "not enough clicks to buy this autoclicker"))
(set! clicks (- clicks cost))
(update-field! num-owned ac add1))
that’s dramatically shorter and nicer