[ mona / prog / sol ]
Let's talk about Emacsen: GNU Emacs, Guile Emacs, edwim, mg, etc. Do you use them? Do you like them? Do you extend them? Any tips to share? Any questions to ask?
State of Emacs Lisp on Guile
The benchmark should only run the tests that have the same result in both implementations, otherwise you are measuring very different executions.
sbbs.el is pretty nifty but has anyone attempted to write a SchemeBBS mode for Edwin? I figure it could be modelled after imail mode.
Anyone have any idea how to make Emacs highlight unbound and shadowing Scheme variables? Locating errors involving these variables seems to take up a reasonable percentage of my debugging cycle, and it would be very helpful to discover them up front.
I don't know of anything like that, you'd probably have to integrate it into something like Geiser or have a collection of bound symbols (depending on the imports) of whatever Scheme implementation you use, so that these built-in variables aren't marked as unknown.
Let's keep the questions about installation and code reviews in one thread.
previous thread http://textboard.org/prog/39
Thanks a lot, I will probably add these worthwhile optimizations. I was thinking about changing the redirection to an absolute path too because, sadly, patching http-syntax.scm has been an exceedingly high barrier entry for many persons who have shown their interest. Updating that file (and the broken httpio.scm) to follow the new RFC might still be possible in future releases of MIT Scheme 10, but I have only recently tried porting SchemeBBS to the newer version. (The 10.1.10 dist you could download from the official site was broken for a year, I've just noticed it's been replaced by 10.1.11, 2020/06/04)
I have a cute idea for some really fun and unique feature that should be very easy to implement but
From "display the list of boards on top of pages" on Jun 11:
(define (make-board-list) `((p (@ (class "boardlist")) "[ " ,@(list-intersperse (map (lambda (board) (list 'a `(@ (href ,(string-append "/" board "/") )) board)) *board-list*) " | ") " ]")))
From "Allow to quote every single posts as comma separated values. Deduplicate regex code" on Jun 11:
(define *board-list* (map pathname-name (cddr (directory-read "data/sexp/*"))))
.. mona/ prog/ sandbox/ sol/
From top of the page:
[ mona / prog / sol ]
The same >>16 applies to message/epistula and headline/titulus in post-thread, of course.
Thank you for the code review and fixes. There are much needed security checks to be done on user inputs. The POST server went down with a forged request of thousands of query strings. Spam bots are also more and more aware of this place. I saw some familiar textboard spam ``Am..ox..i..cil.l.in O..n/line Wi&t32hout Pre@scr^ipt%ion'' slipping through. I need to decouple /sandbox/ from the other boards and automate the relaunching of the server asap (for that, a small script will do).
My apologies for not integrating your code yet, I'm mostly afk and offline these days (waiting for a provider to install broadband Internet at my place as a testament to nomadism. I've also dumpster-dived into a worn up but solid and comfortable gamer chair and a classy Directoire style wooden desk. The antique and modern styles don't exactly match but we'll call that a battlestation. With the sound-proof wall of books that I built against the wall behind which dwells another human, we're nearing perfection as far as working conditions are concerned.
I have a mock-up for a little proof of concept feature that I'd like to showcase but this one could be a security nightmare. Even if it's already sandboxed it needs at least to be a jailed process with limits on CPU, RAM and execution time.
-- yours truly
(define (parameters->alist p) (map parameter->pair (string-split p #\&)))
; Splits the input string 'str into a list of strings ; based on the delimiter character 'ch ; © (Doug Hoyte, hcsw.org) (define (string-split str ch) (let ((len (string-length str))) (letrec ((split (lambda (a b) (cond ((>= b len) (if (= a b) '() (cons (substring str a b) '()))) ((char=? ch (string-ref str b)) (if (= a b) (split (+ 1 a) (+ 1 b)) (cons (substring str a b) (split b b)))) (else (split a (+ 1 b))))))) (split 0 0))))
Because of the split-in-cons line this is recursive rather than iterative. This means that it can be stress tested on the stack depth. In the REPL of MIT/GNU Scheme 9.1.1:
$ mit-scheme --load lib/utils.scm --load lib/parameters.scm [...] Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 LIAR/x86-64 4.118 || Edwin 3.116 ;Loading "lib/utils.scm"... done ;Loading "lib/parameters.scm"... done 1 ]=> (define (test n) (parameters->alist (apply string-append (make-list n "&x=x"))) 'ok) ;Value: test 1 ]=> (test 42308) ;Value: ok 1 ]=> (test 42309) ;Aborting!: maximum recursion depth exceeded 1 ]=>
With an appropriately crafted wget post request textboard.org yields:
HTTP/1.1 502 Bad Gateway Server: nginx/1.18.0 Date: Thu, 02 Jul 2020 00:41:44 GMT Content-Type: text/html Content-Length: 496 Connection: keep-alive ETag: "5ecc391b-1f0"
The length of 'body' should be validated in post-message and post-thread, before computing 'params'. Something like (* 2 *max-post-size*) should be more than enough. And string-split should be made iterative, in the style of string-split*.
The POST server went down with a forged request of thousands of query strings.
That sounds cool but please try to stay safe from pandemic stuff.
Adding the checks recommended in >>16 >>18 >>20 is trivial but fixing string-split takes more than a line or two. Here is how string-split operates:
$ mit-scheme --load lib/utils.scm [...] Release 9.1.1 || Microcode 15.3 || Runtime 15.7 || SF 4.41 LIAR/x86-64 4.118 || Edwin 3.116 ;Loading "lib/utils.scm"... done 1 ]=> (string-split "" #\-) ;Value: () 1 ]=> (string-split "-a-b--c-d-" #\-) ;Value 14: ("a" "b" "c" "d")
Its sibling string-split* has the right idea for tco
;;; this version of string-split doesn't trim the leading separators ;;; (string-split "/usr/local/bin") => ("" "usr" "local" "bin") (define (string-split* sep str) (define (f cs xs) (cons (list->string (reverse cs)) xs)) (let loop ((ss (string->list str)) (cs '()) (xs '())) (cond ((null? ss) (reverse (if (null? cs) xs (f cs xs)))) ((char=? (car ss) sep) (loop (cdr ss) '() (f cs xs))) (else (loop (cdr ss) (cons (car ss) cs) xs)))))
but has an asymmetry bug whereby it keeps a leading empty piece but drops a trailing one:
1 ]=> (string-split* #\- "") ;Value: () 1 ]=> (string-split* #\- "-a-b--c-d-") ;Value 15: ("" "a" "b" "" "c" "d")
This is fine for its intended use in lib/markup.scm:block-scanner but makes it an incorrect split function. This in turn is because the split of a reversed input should be the split of the original input with the pieces and the order of the pieces reversed. String-split* violates this:
1 ]=> (string-split* #\- "-ab-cd-") ;Value 13: ("" "ab" "cd") 1 ]=> (string-split* #\- (reverse-string "-ab-cd-")) ;Value 14: ("" "dc" "ba")
In addition string-split* uses string->list to break the string up into individual characters, even within runs of non-separators, and it calls char=? on every character. Both of these are easily avoided by taking advantage of the built-in procedures for character based string search:
Here is the asymmetry and efficiency fix for string-split*:
(define (string-split-tco str char) (define (iter result now end) (if (= now end) (cons "" result) (let ((pos (substring-find-next-char str now end char))) (if pos (iter (cons (substring str now pos) result) (+ pos 1) end) (cons (substring str now end) result))))) (reverse (iter '() 0 (string-length str))))
1 ]=> (string-split-tco "" #\-) ;Value 15: ("") 1 ]=> (string-split-tco "-a-b--c-d-" #\-) ;Value 16: ("" "a" "b" "" "c" "d" "") 1 ]=> (string-split-tco "-ab-cd-" #\-) ;Value 17: ("" "ab" "cd" "") 1 ]=> (string-split-tco (reverse-string "-ab-cd-") #\-) ;Value 18: ("" "dc" "ba" "")
This can be easily used to get a fixed version of string-split that doesn't overflow the stack:
(define (string-split-tco-noempty str char) (define (iter result now end) (if (= now end) result (let ((pos (substring-find-next-char str now end char))) (if pos (iter (if (= now pos) result (cons (substring str now pos) result)) (+ pos 1) end) (cons (substring str now end) result))))) (reverse (iter '() 0 (string-length str))))
1 ]=> (string-split-tco-noempty "" #\-) ;Value: () 1 ]=> (string-split-tco-noempty "-a-b--c-d-" #\-) ;Value 19: ("a" "b" "c" "d")
The -tco and -tco-noempty versions can be unified via a filtering lambda, but the cost is a small drop in efficiency and for such a basic tool like splitting I didn't feel that the efficiency loss was justified.
1 ]=> (define (test n) (string-split-tco-noempty (apply string-append (make-list n "&x=x")) #\&) 'ok) ;Value: test 1 ]=> (test 50000) ;Value: ok 1 ]=> (test 100000) ;Value: ok
Even though string-split-tco-noempty gets rid of the stack overflow, I still recommend the 'body' length check from >>20 as well.
Do girls exist?
Would you exist if they didn't?
Yes; I descend from a lineage of men. The manliest of all men. My bloodline is proudly free of the blemish of femininity. My fathers raised me with the honour of masculinity and I'm not going to bring shame to my family by laying gaze upon women.
that's one of Oglaf's more hilarious subplots
(for unfamiliar reader, oglaf is a long running nsfw comic from before y'all cucked everything)
hps://www.oglaf.com/honor/ hs://www.oglaf.com/son-of-kronar/ h_s://www.oglaf.com/son-of-kronar/2/
Police forces across Europe celebrated their infiltration of EncroChat on Thursday, disrupting international organised crime networks which were using the company's encrypted phones.
This is the type of thread that you can write in every time you visit the site! You can do anything from use this as a personal log for your project, to sharing what you're hacking on at the moment, or to critique something some else did in the thread. I'm looking forward to hearing what you guys are up to!
Personally I've been working on a radix tree implementation in R7RS, it seems moderately efficient and not too bad to use, although I haven't finished many of the operations, and I'm not sure I will due to the awareness of a better way to do it if I only had the primitives (or even just a standardised FFI). Anyway thought I'd share it just because it's something to talk about. Due to the file limit I'm only posting the introduction, imports, exports, and type here, but a link to the full source can be found here: http://ix.io/1wB1.
; This is a implementation of a radix tree in the style of Clojure or ; Scala, meaning a not particularly good implementation. Ideally this ; would be a adaptive radix tree as described in the following paper: ; http://www-db.in.tum.de/~leis/papers/ART.pdf ; additionally it'd be nice to be able to have a variant for using SIMD ; functions on unboxed values if possible. Regardless scheme does not ; have the necessary primitives for implementing a adaptive radix tree ; to its full potential, namely access or abstractions of SIMD functions ; for the search function. ; much of this library may seem unidiomatic, this is simply because I'm ; trying quite hard to A) avoid allocations and B) factor out functions ; when they can be used in multiple situations, even if this means adding ; a bit of complexity. ; one of the goals of this library was to be exceedinly standard compliant, ; it's written entirely in R7RS small with SRFI 1 & 60. That being said ; this doesn't actually make this a particularly portable library due to ; the lack of upto date compliance with the standard and implementation ; of SRFI 60. To my knowledge the following implementations would likely ; be able to run this library: Foment, Gauche, Larceny, & Sagittarius. (define-library (data radix) (export radix-ref radix-set radix->list radix->vector vector->radix list->radix radix radix-append radix-data radix-length radix-depth)) (import (scheme base) (srfi 1) ; append! in radix->list (srfi 60)) ; bitwise operations (define-record-type radix #t #f data length depth)
Why are posting this here?
I didn't think the paster needed its own thread. Since it was announced in "Small programming projects ideas" https://textboard.org/prog/118#t118p46 the admin didn't either.
You butchered cooked-message in patch-acceptor.lisp, Bitdiddle.
If you go to a paste like
then delete 'raw' but forget the /, it doesn't match any hunchentoot:create-regex-dispatcher in controller.lisp and you get
The requested URL ~A was not found on this server./raw
instead of the intent of
The reason is that you removed the ~? recursive processing but kept its arguments.
For the same reason, if you get an (#.+http-internal-server-error+) and go to 'if *show-lisp-errors-p*', you will serve the format string itself: "~A~@[~%~%Backtrace:~%~%~A~]". To restore sanity add ~? back, move "/raw" to the :location line, and dump the now useless escape-for-html and mapcar.
(format nil "~?" format arguments) ))) [...] (cooked-message "~A/raw" (header-out :location)))
You can also use the format directly if you dislike ~?.
Thanks, I will look into that. I got that pastebot up and working in a matter of minutes and haven't paid much attention. Ad hoc modification of the Hunchentoot web server for the sake of spending the least amount of time possible on adding a link to raw pastes wasn't exactly something you'll found in the book of best practices anyway.
I will look into that.
OK. The fix is exactly those two lines. There is also >>115.
You're all faggots.
...you are incapable of the full mental effort required to pronounce 'aluminium'.
now I see how you got banned from that forum lol
Which forum banned whom?
...you care about the destruction of your ``historical'' artefacts when you virtually have no history. Unlike Mesopotamia which you destroyed and pillaged.
Where's the source for this one, I'm interested.
Grep the old Usenet groups and mailing lists for endless discussions about Scheme vs Common Lisp if you're interested in the debate. You'll find a lot of informed and relevant arguments.
These kind of questions ("what's the best programming language?") are kind of useless. They're lacking an adjective complement to make sense. Best for what use case?
Is there anyone here using it? What do you like and do you hate about it?
Thinking of distro hopping again?
I haven't tried it but along with Guix and Void Linux, it's one of the distribution I'd consider switching to.
On the paper, Guix is superior in many ways but it's not always the feedback I received from people having tried both.\ for a significant time.
Check them LISP papers.
They're not real threads but actors with message passing, I mean they're cheap.
Here's an aggregation of scheme related academic articles I stumbled across today: https://github.com/schemedoc/bibliography
BibTeX files would be nice.
That would be nice.
It is over today. Grab what you still can.
Thanks for sharing that.
2019 was ML, Deep learning, and a SaaS for freaking everything. What are the 2020, and 2021 startup memes?
I would say Rust and WASM but what else?
Oddly enough, postgres.
Black Lives Matter.
ML, Deep learning, and a SaaS
These were already start-up memes before 2019 (I think). Running stats on Hacker News posts in 2020 would probably answer the question. My only experience with memetic programming in a start-up was unironically the functional programming paradigm (Erlang OTP/Elixir) and it seems to have faded away.
Is the NoSQL fad gone?
I'm enrolled in a training program to learn godawful shiny (but bankable) technologies. It's true that most of the libraries websites bear the logo along with a Social Justice Initiative donation link. As far as non-tech-related advertisements are concerned, this and COVID messages were definitely the main trends of 2020. But it sounds like a truism and we can safely bet on variations on "work at home compliant" as one of the main selling feature for anything from now on.