/t/ - Technology

Discussion of Technology

Index Catalog Archive Bottom Refresh
+
-
Options
Subject
Message

Max message length: 0/12000

files

Max file size: 32.00 MB

Total max file size: 50.00 MB

Max files: 5

Supported file types: GIF, JPG, PNG, WebM, OGG, and more

CAPTCHA
E-mail
Password

(used to delete files and posts)

Misc

Remember to follow the Rules

The backup domains are located at 8chan.se and 8chan.cc. TOR access can be found here, or you can access the TOR portal from the clearnet at Redchannit 3.0.

.se is back up
.moe has intermittent downtime due to DDoS

Archival System Enabled
No More Thread Transfers


8chan.moe is a hobby project with no affiliation whatsoever to the administration of any other "8chan" site, past or present.

You may also be interested in: AI

(843.36 KB 1920x1080 1697678950319.jpg)

(λ) - Lisp General Anonymous 04/19/2025 (Sat) 11:17:31 No. 18163 >>18211>>18254
>Lisp is a family of programming languages with a long history and a distinctive parenthesized prefix notation. There are many dialects of Lisp, including Common Lisp, Scheme, Clojure and Elisp. >Emacs is an extensible, customizable, self-documenting free/libre text editor and computing environment, with a Lisp interpreter at its core. >Emacs Resources https://gnu.org/s/emacs https://github.com/emacs-tw/awesome-emacs https://github.com/systemcrafters/crafted-emacs >Learning Emacs C-h t (Interactive Tutorial) https://emacs.amodernist.com https://systemcrafters.net/emacs-from-scratch http://xahlee.info/emacs https://emacs.tv >Emacs Distros https://www.spacemacs.org https://doomemacs.org >Elisp Docs: C-h f [function] C-h v [variable] C-h k [keybinding] C-h m [mode] M-x ielm [REPL] https://gnu.org/s/emacs/manual/eintr.html https://gnu.org/s/emacs/manual/elisp.html https://github.com/emacs-tw/awesome-elisp >Common Lisp https://lispcookbook.github.io/cl-cookbook https://cs.cmu.edu/~dst/LispBook https://gigamonkeys.com/book https://lem-project.github.io https://stumpwm.github.io https://nyxt-browser.com https://awesome-cl.com >Scheme https://scheme.org https://try.scheme.org https://get.scheme.org https://books.scheme.org https://standards.scheme.org https://go.scheme.org/awesome https://research.scheme.org/lambda-papers >Clojure https://clojure.org https://tryclojure.org https://clojure-doc.org
[Expand Post]https://www.clojure-toolbox.com https://mooc.fi/courses/2014/clojure https://clojure.org/community/resources >Other https://github.com/dundalek/awesome-lisp-languages >Guix https://guix.gnu.org https://nonguix.org https://systemcrafters.net/craft-your-system-with-guix https://futurile.net/resources/guix https://github.com/franzos/awesome-guix >SICP/HtDP https://web.mit.edu/6.001/6.037/sicp.pdf https://htdp.org >More Lisp Resources https://rentry.org/lispresources
>>18163 (OP) Racket is great too
(38.10 KB 1024x1356 logo.webp)

fennel!
I'm trying to do something way above my head but here's the gist. - When you press F5 in C or Python some compiling options show up on the minibuffer, those change depending on the major mode you're in - After selecting one, another function is called that opens eshell, executes the command and switches back to the original window once it detects the process is done The following works on both C and Python, I'm not good with elisp at all so I kept iterating versions using deepseek, I'd like to know if there's no better way of implementing something like that. (defvar my/compile-options '((c-mode ("C with user input" . "make run") ) (python-mode ("Python with user input" . "python3 -u REPLACE") ))) (defun my/compile-choice () "Prompt for a compilation command and execute it in eshell." (interactive) (let (applicable-options) (dolist (entry my/compile-options) (when (derived-mode-p (car entry)) (setq applicable-options (append applicable-options (cdr entry))))) (if (not applicable-options) (message "No compilation options for current mode") (let* ((choice (completing-read "Compile option: " applicable-options nil t)) (command (cdr (assoc choice applicable-options)))) (my/run-in-eshell command))))) (defun my/run-in-eshell (command-str) "Run COMMAND-STR in eshell, replacing REPLACE with the current filename." (interactive) ;;delete existing eshell buffer (let ((buf (get-buffer "*eshell*"))) (when buf (when-let ((win (get-buffer-window buf))) (delete-window win)) (kill-buffer buf))) ;;replace REPLACE with the current filename and insert command (let ((filename (buffer-file-name))) (unless filename (error "Buffer is not visiting a file")) ;;new eshell (eshell) (switch-to-buffer eshell-buffer-name) (goto-char (point-max)) (insert (replace-regexp-in-string
[Expand Post] "REPLACE" (shell-quote-argument filename) command-str)) (eshell-send-input)) ;;switch back window when done (set-process-sentinel (get-buffer-process (current-buffer)) (lambda (process _event) (when (memq (process-status process) '(exit signal)) (previous-window-any-frame))))) (global-set-key (kbd "<f5>") 'my/compile-choice) A few notes: - I need eshell because it needs to work on both linux and windows - I could only manage to detect when a program terminates inside eshell using process-sentinel - i delete the existing eshell buffer before initiating because i was having issues sending new commands to the existing shell - My C program has a simple makefile that runs it (./main) - In my init.el I have a section to limit the height of the eshell and forces it to be displayed always at the bottom of the current frame - The way I'm sending the file name (like on python) is really stupid, but it works
>>18228 Any reason you don't use M-x compile?
>>18248 Whether it's compile or eshell doesn't change anything I've said. They have the same problems when trying to implement the behavior I want it to have. I picked eshell because I could expand these functions later on.
(145.40 KB 400x400 1739089728314468.png)

>>18163 (OP) My first thought was eshell is a lisp interpreter, so you could append switch-to-buffer after your compile command, and using pcase to select the command from the mode (defun mode-compile-command (file) (completing-read "> " nil nil nil (pcase major-mode ('c-mode "make run") ('python-mode (concat "python -u " file)) ('lisp-mode (concat "sbcl --load " file)) (_ "echo none")))) (defun mode-compile () (interactive) (let* ((buffer (buffer-name)) (file (buffer-file-name)) (command (mode-compile-command file))) (switch-to-buffer eshell-buffer-name) (insert (concat command "; (switch-to-buffer \"" buffer "\")")) (eshell-send-input)))
>>18254 Sorry misquote >>18228
>>18252 Well what *is* your problem? It seems to me you want a code review? Your code is pretty terrible ngl. I'd just wrap compile in your shoes.
>>18262 >>18254 I might have badly expressed myself. Look at the webm (i think its dark because HDR is turned on, sorry), it shows the function displayed in my question at work. 1. I press F5 2. The function checks the major mode I'm in 3. It displays compiling options that fit the major mode in the minibuffer, which I've set up beforehand in the function 4. After I select one compiling option it: - Spawns an eshell window (ideally i'd reuse one if it already exists but i was having issues with it) - Executes the command inside the eshell (for example: in the case of a C program and the option I've selected in the minibuffer, make run) - Switches back to the previous window once the program exits NOTE: I'd like to expand the "compiling options" later with more things to pick, so ideally I wouldn't attach the command I want to run directly to which major mode I'm currently in at the time. Is there a better way to make a function that does that in a simpler way? >code is pretty terrible Yes, I know. It does work like I wanted it to, but like I said, I needed to tard wrang deepseek to get there because I'm not experienced enough to do it alone. >code review If that's the only way I have to achieve what I want, sure, ideally I'd get some guidance (keep in mind that I'm new, most stuff go over my head) on what I should be doing instead. Or if the problem is interesting for you, your own implementation of it.
>>18267 >NOTE: I'd like to expand the "compiling options" later with more things to pick, so ideally I wouldn't attach the command I want to run directly to which major mode I'm currently in at the time. Let's say you wish to combine the major mode with the current day using this function: (defun day-string () (format-time-string "%a" (current-time))) For C maybe you have 'make run' on weekends and two 'test and debug' options on weekdays, while for Python test.py is added on any day that isn't Monday. The following list structure encodes that info (basically a more fancy alist): (compile-options (major-mode (day-string)) ((c-mode "Sat") "make run") ((c-mode "Sun") "make run") ((c-mode _) (("cc" file "-o /tmp/test") ("cc" file "-Drelease -o build"))) ((python-mode "Mon") ("python -u" file)) ((python-mode _) ("python -u" file "test.py"))) Where (major-mode (day-string)) could expand to (c-mode "Mon"), and matches ((c-mode _) ...) compile-options is just be a macro that expands to a pcase function: (defmacro compile-options (pattern &rest cases) `(defun compile-options-select () (pcase ,pattern ,@cases))) Which would be used like this: (completing-read "> " (compile-options-select)) How does that sound so far?
>>18277 The main issue with a date example is that it still wouldn't give me a list with options, but I tried remaking it as a simpler list, I couldn't for the life of me figure out how to switch back to the previous buffer with a simple hook, I don't understand why I couldn't do something simple like (add-hook 'after-make-frame-functions 'previous-window-any-frame). (defun my/compile-with-preset () "Prompt for a compilation preset then execute it." (interactive) (let* ((preset (completing-read "Select preset: " '("Run" "Release" "Test") nil t)) (cmd (pcase (list major-mode preset) (`(c-mode "Run") "make run") (`(c-mode "Release") "make release") (`(c-mode "Test") "make test") (`(python-mode "Run") (format "python -u %s" (buffer-file-name))) (`(python-mode "Release") (format "python -u %s" (buffer-file-name))) (_ (user-error "No compile option for %S" (list major-mode preset))))) (compilation-buffer (compile cmd t))) (pop-to-buffer compilation-buffer) (with-current-buffer compilation-buffer (add-hook 'compilation-finish-functions (lambda (_buffer _status) (previous-window-any-frame)) nil t)) (goto-char (point-max)))) (global-set-key (kbd "<f5>") 'my/compile-with-preset) One problem with this function that I'd like to solve is that, well, the list itself doesn't really change according to the major mode, all options are still displayed whether they exist or not. And if I'm being honest I really don't understand how else I'd do that other than making a list based on the major mode like I did before then calling it on the main function. I sent the function above on deepseek and after some trial and error I reached this: (defvar my/compile-presets '((c-mode ("Run" . (lambda () "make run")) ("Release" . (lambda () "make release")) ("Test" . (lambda () "make test"))) (python-mode ("Run" . (lambda () (format "python -u %s" (buffer-file-name)))) ("Module" . (lambda () (format "python -m %s" (read-string "Module name: "))))) "Alist mapping major modes to presets and their commands.")) (defun my/compile-with-preset () "Prompt for a compilation preset based on major mode, then execute it." (interactive) (let* ((mode-presets (alist-get major-mode my/compile-presets nil nil #'eq))) (unless mode-presets (user-error "No compile presets for %s" major-mode)) (let* ((preset (completing-read "Select preset: " (mapcar #'car mode-presets) nil t))
[Expand Post] (cmd-fn (cdr (assoc preset mode-presets))) (cmd (funcall cmd-fn)) (compilation-buffer (compile cmd t))) (pop-to-buffer compilation-buffer) (with-current-buffer compilation-buffer (add-hook 'compilation-finish-functions (lambda (_buffer _status) (previous-window-any-frame)) nil t)) (goto-char (point-max))))) (global-set-key (kbd "<f5>") 'my/compile-with-preset) But I really don't understand how that works, I wouldn't ever come up with that by myself and I don't know if that's a good way of achieving it or not. From reading I guess it works like - Listing the compatible modes listed in compile-presets and putting them in mode-presets - Using completing-read I list the available CAR - I pick the CDR of the selected car then... execute it? I think it has to work like that so I can evaluate buffer-file-name at runtime? - I send the result to compile, the rest works like the other one. Overall I quite like how the function works even though I didn't make it (I did add the "Module" option on python so you can see one of the potential uses of making it as a list) but my opinion doesn't matter much. What do you guys think? >why do you want it as a list?????? Because I want one...
>>18434 >The main issue with a date example is that it still wouldn't give me a list with options The idea was ((c-mode _) (("cc" file "-o /tmp/test") ("cc" file "-Drelease -o build"))) represented a case with two options (which would be expanded by the compile-options macro if you wanted me to continue writing it) >But I really don't understand how that works, I wouldn't ever come up with that by myself It's unusually written by deepseek for sure, I would rewrite the command selection part like: (defvar compile-presets '((c-mode ("Release" . "make release") ("Debug" . "make debug")) (python-mode ("Release" . (format "python -u %s" (buffer-file-name))) ("Debug" . (format "python -m %s" (read-string "Module: ")))))) (pcase (alist-get major-mode compile-presets) ((and (pred consp) list) (let ((command (eval (alist-get (completing-read "> " (mapcar #'car list) nil t) list nil nil #'equal)))) command)) (_ (user-error "No compile presets for %s" major-mode))) 'command' is then handed off to eshell or compile/compilation-buffer as you like
>>18443 Small revision: if you don't mind adding another function (of binding it locally with flet) this seems clearer: (defun assoc-read (list) (assoc (completing-read "> " (mapcar #'car list) nil t) list)) (pcase (alist-get major-mode compile-presets) ((and (pred consp) (app assoc-read `(,select . ,command))) command) (_ (user-error "No compile presets for %s" major-mode))) 'select' and 'command' are bound to the results of choosing from the alist, there's possibly a nicer way of writing assoc-read tho
If you were making a Lisp for serious use, what would you include? How would the base language be styled? Would you follow along with existing Lisps? Are there any nit-picks you have with the style of existing Lisps? Scheme uses a minimal but sufficient language as its base. Common Lisp does the opposite, and includes a fairly complete standard library. Clojure has a very particular standard library, advertises its sophisticated implementations of immutable data structures as its primary draw, but also includes many macros to yield its particular style. While I've always liked the Scheme approach, I often see Clojure devs boasting about how beautiful their language is. I feel I'm missing something there, since it's never looked as appealing to me. I'm looking to bike-shed a language I've been working on and particularly its macros sometime in the near future, and I wanted some general thoughts.
>>18804 I think it's vital to implement parallelism from the ground up, that shit is impossible to get right if you have to tack it on later. Also include common useful data structures in the standard library, no one is happy when they have to implement their own graph search, B-trees, multivectors, or doubly linked lists. I personally really like the idea of interpreted lisps more than compiled ones for reasons of much better self reflection and not having to deal with implementation issues so much, but compilers are also pretty great. A fully compiled initial standard library in an immutable namespace and first class macros support can I think get the best of both worlds in most cases. Some people like types, but imo they only seem to exist to promote verbosity, boiler plate injection, and endless bikeshedding about exactly what types everything should be.
(146.00 KB 423x600 17030169733983.jpg)

>>18804 >If you were making a Lisp for serious use, what would you include? >good ffi, ideally can generate bindings given a shared object/archive and header >library, package, and build system (if applicable) is standardized >single step debugger, perhaps even for static binaries (if build includes dwarf debugging information) >ability to add new intrinsics (e.g. https://pvk.ca/Blog/2014/08/16/how-to-define-new-intrinsics-in-sbcl/ for stuff like simd or cuda) All very serious business
>>18926 >I think it's vital to implement parallelism from the ground up, that shit is impossible to get right if you have to tack it on later. Sounds about right, I've been thinking about it and while I don't think I've outright excluded concurrency I still don't know which concurrency model I should use. Designing for parallelism is shockingly hard in comparison to how seamless most languages make it seem. >Also include common useful data structures in the standard library, no one is happy when they have to implement their own graph search, B-trees, multivectors, or doubly linked lists. Something that I think I'll have to bike-shed one way or the other. I'll have to keep that list in mind. >I personally really like the idea of interpreted lisps more than compiled ones for reasons of much better self reflection and not having to deal with implementation issues so much, but compilers are also pretty great. This might be less of a choice with my language. >A fully compiled initial standard library in an immutable namespace and first class macros support can I think get the best of both worlds in most cases. This is a Lisp thread, first-class macro systems should be a given. Compiled initial standard library seems all but necessary for performance unless you start with a JIT. >Some people like types, but imo they only seem to exist to promote verbosity, boiler plate injection, and endless bikeshedding about exactly what types everything should be. Types are a double-edged sword. They tend to lead to better performance and can be useful to communicate the structure of your data. That said, I remember the proliferation of Haskell papers in the 2010s which amounted to user papers on feng shui with types, as well as the continued teaching of OOP design patterns as dogma. It's very easy to get lost in the type theory weeds and make things harder for yourself and others, especially after you start adding things like phantom types. >>18994 >>good ffi, ideally can generate bindings given a shared object/archive and header I don't know about auto-generation of bindings, but I have a few experimental ideas about how to have a good FFI. >>library, package, and build system (if applicable) is standardized Noted, that's another thing I might need to bike-shed. >>single step debugger, perhaps even for static binaries (if build includes dwarf debugging information) I've been thinking about optional reflection support for issues like this. If you don't set things up for hardware debugging support, there are inherent difficulties in supporting this style of debugging while also remaining performant. >>ability to add new intrinsics (e.g. https://pvk.ca/Blog/2014/08/16/how-to-define-new-intrinsics-in-sbcl/ for stuff like simd or cuda) That would have to be a platform-dependent thing.
(141.03 KB 400x581 evlis-jank.jpg)

>>19042 >Designing for parallelism is shockingly hard in comparison to how seamless most languages make it seem. You might be interested in this machine https://museum.ipsj.or.jp/en/heritage/EVLIS.html >EVLIS was named after the function evlis, which evaluated parameters in parallel in evaluation function eval. For an application like (apply f ((+ 1 2) (+ 3 4))) it's specifically (map eval params) in the body of apply that can be parallelized (where the parameters have no side effects)
>>19042 networking and IPC are also vitally important for a modern language and should be part of the standard along with package management, likewise verification and encryption. I should, from the repl of a fresh install, be able to search for and download a versioned, dated, signed package either from a central repo or directly from a github page. I really think more languages should embrace the emacs style declarative package management, where you just put a list of packages you want and their settings in your init file and everything is automatically downloaded and installed.
>>20246 Right, and there's an inherent parallelism in functional programming. If you go for green threads it's not out of the question to evaluate list elements or cons pairs in parallel if you expect each operation to be non-trivial. The hard question is getting something that's complete enough in terms of IPC, and making a runtime for it that doesn't compromise performance. Asynchronous I/O is one thing, concurrent garbage collection/reference counting is a different beast altogether, especially if you want things like atomic operations. >>20368 >networking Yes, at least TCP/IP and UDP/IP seem mandatory. >IPC Assuming you mean OS-level IPC. This is probably something to look more closely into. >verification and encryption Yes, it's unfortunate that besides libsodium there aren't many projects out there seeking to be a "many-in-one" solution for cryptography. >I should, from the repl of a fresh install, be able to search for and download a versioned, dated, signed package either from a central repo or directly from a github page. >I really think more languages should embrace the emacs style declarative package management, where you just put a list of packages you want and their settings in your init file and everything is automatically downloaded and installed. Noted, should think about this sooner rather than later too. Lots of good answers
I was thinking about some alternate forms for pattern-matching "let" macros. At the time I had a few things in mind: >several beginning parentheses when doing the first pattern match, with a minimum of two >several closing parentheses on the last expression, also with a minimum of two >Haskell's do syntax, let in various FP languages, Koka's deliberate imitation of imperative syntax >Clojure's arrow macros, especially as-> The typical forms of let that I see are: >s-let The usual Common Lisp/Scheme let, putting one pair of parentheses around the whole sequence of pattern-expression pairs and one pair of parentheses around each pattern-expression pair. >c-let The Clojure let, putting one pair of parentheses around the whole sequence of pattern-expression pairs. I ended up with two others: >b-let No parentheses around the sequence of pattern-expression pairs. Putting one pair of parentheses around each pattern-expression pair, then terminating with a single expression at the end. It has a problem that the last expression doesn't fit the regular form of the rest, and this means adding a step before or after. >d-let No parentheses around the sequence of pattern-expression pairs. Putting one pair of parentheses around each pattern-expression pair and terminating with the value of the expression of the final pattern-expression pair at the end (and ignoring the final pattern). This is more regular than b-let, and allows a convention of finishing with a "return pattern". Here they are side-by-side. ;; s-let (let (((p1 p2) (x1)) (p3 x2) ((() p4) (x3))) (x4)) ;; c-let (let ((p1 p2) (x1) p3 x2 (() p4) (x3)) (x4)) ;; b-let (let ((p1 p2) (x1)) (p3 x2) ((() p4) (x3)) (x4)) ;; d-let (let ((p1 p2) (x1)) (p3 x2) ((() p4) (x3)) (<ret> (x4))) I've been using the b-let form for some of my code and I like it, but I was curious about what others think.
Clojure is not a lisp.
(274.44 KB 2000x1208 etruscan-lofi.jpg)

>>20822 (import (ice-9 match)) (define-syntax let (syntax-rules (=) [(_ pat = exp . rest) (match-let ([pat exp]) (let . rest))] [(_ body) body])) (let (y m d) = (list 2025 04 21) roman = (lambda (a) (format #f "~@r" a)) date = (map roman (list d m y)) (show date)) (XXI IV MMXXV) There's always heresy (h-let)
This one was hard to find. I posted a link to it here. https://desuarchive.org/g/thread/104995871/
(132.86 KB 400x400 1711668374435133.png)

>>21211 I think we mostly got split between 8/t/ here and lainchan/lambda/
(1.37 MB 640x360 aharen.gif)

(require 'dom) (defun playlist-items (id) (mapcar (lambda (e) (cons (dom-text (dom-by-tag e 'title)) (dom-attr (dom-by-tag e 'link) 'href))) (dom-by-tag (with-current-buffer (url-retrieve-synchronously (concat "https://www.youtube.com/feeds/videos.xml?playlist_id=" id)) (set-buffer-multibyte t) (goto-char (point-min)) (search-forward "\n\n") (xml-parse-region (point) (point-max))) 'entry))) (defun playlist-play (id) (cl-loop for (title . url) in (playlist-items id) do (message "playing %s" title) (call-process-shell-command (concat "mpv " url)))) (playlist-play "PLODmH4ThctzbcB3KMtDcQ30eCep78mG05")


Forms
Delete
Report
Quick Reply
Drag files here to upload or
click here to select them
No Cookies?
0