Skip to content

Instantly share code, notes, and snippets.

View technomancy's full-sized avatar

Phil Hagelberg technomancy

View GitHub Profile
@technomancy
technomancy / love-repl.fnl
Last active April 13, 2024 17:37
Fennel GUI REPL using love2d
;; since one of the strengths of Fennel is access to Lua frameworks, here's
;; a graphical REPL which runs inside LÖVE (https://love2d.org)
;; supports multiline input, showing errors in red, detecting incomplete input.
;; for a slightly more complex version which supports running inside a sandbox
;; see the wiki: https://github.com/bakpakin/Fennel/wiki/Repl
;; to run: fennel -c love-repl.fnl > main.lua && love .
(local fennel (require :fennel))
@technomancy
technomancy / style.md
Last active January 22, 2024 22:45
Clojure Style Guide: commentary

The Clojure Style Guide is pretty good overall. It's very detailed and most of its advice is solid. There are handful of places it makes bad recommendations or is missing some advice.

Many of these criticisms apply to the output of linters like clj-kondo as well.

threading macros vs let

@technomancy
technomancy / gist:cc0e7800878c39e4c245fc041c11df4b
Last active April 21, 2023 01:16
Clojure namespaces, spec, and why they're confusing

To me, "require-and-automatically-visible" is violating the beauty of namespace. But, maybe I felt this way because I don't understand Clojure's registry or how require works.

I thought about this more, and I think I have a better understanding of why this feels strange. Clojure has one thing called "namespaces" which are clojure.lang.Namespace objects created by the ns macro. Functionally speaking they are a storage location which mostly just contain vars and references to vars in other namespaces. They are used for code organization: specifically for organizing vars and occasionally Java classes and interfaces.

Clojure also has a completely different thing called "namespaces" which are prefixes that get attached to keywords and symbols. These can interact with ns namespaces thru the reader in a handful of ways (for instance, ::double-colon keywords and symbols inside backtick forms are resolved according to the current clojure.lang.Namespace) but for the most part should be considered a di

;; For this, please write a program which takes in a CLI arg for a string
;; expression such as “1 + 2 - 3” and have it interpret the expression
;; and print the result to stdout. Only support for + and - is needed, to
;; avoid precedence.
(fn evaluate [input]
;; first for regularity, we prepend a + to the input string; this way we end
;; up just looping thru a series of operator/number pairs instead of having
;; numbers with operators between them.
(let [input (.. "+ " input)]
;; This module is the read/eval/print loop; for coding Fennel interactively.
;; The most complex thing it does is locals-saving, which allows locals to be
;; preserved in between "chunks"; by default Lua throws away all locals after
;; evaluating each piece of input.
(local utils (require :fennel.utils))
(local parser (require :fennel.parser))
(local compiler (require :fennel.compiler))
(local specials (require :fennel.specials))
user=> (def s (map = (range 100) (concat (range 78) [:lol] (range 99))))
#'user/s
user=> (realized? s)
false
user=> (every? true? s)
false
user=> (realized? s)
true
user=>
@technomancy
technomancy / gist:e1a347f91abe11e440b7ba5c33f991c7
Created February 7, 2021 18:00
gcc segfault building tic80
[ 50%] Building C object CMakeFiles/tic80core.dir/src/core/sound.c.o
[ 50%] Building C object CMakeFiles/tic80core.dir/src/api/js.c.o
[ 50%] Building C object CMakeFiles/tic80core.dir/src/api/lua.c.o
[ 50%] Building C object CMakeFiles/tic80core.dir/src/api/wren.c.o
[ 50%] Building C object CMakeFiles/tic80core.dir/src/api/squirrel.c.o
[ 52%] Building C object CMakeFiles/tic80core.dir/src/ext/gif.c.o
[ 52%] Building C object CMakeFiles/tic80core.dir/src/tic.c.o
[ 52%] Building C object CMakeFiles/tic80core.dir/src/cart.c.o
[ 52%] Building C object CMakeFiles/tic80core.dir/src/tools.c.o
[ 52%] Building C object CMakeFiles/tic80core.dir/src/tilesheet.c.o
phil@localhost:~/lunatest$ ~/.luarocks/bin/luacheck lunatest.lua | grep -v unused | grep -v whitespace
Checking lunatest.lua 40 warnings
lunatest.lua:46:29: variable setmetatable was previously defined on line 42
lunatest.lua:64:7: variable debug was previously defined on line 38
lunatest.lua:489:1: setting non-standard global variable default_hooks
lunatest.lua:512:1: setting non-standard global variable verbose_hooks
lunatest.lua:540:14: accessing undefined variable verbose_hooks
lunatest.lua:540:40: accessing undefined variable default_hooks
lunatest.lua:656:10: variable arg was previously defined as an argument on line 655
;; works
(let [factory clojure.tools.logging/*logger-factory*]
(try
(alter-var-root #'clojure.tools.logging/*logger-factory*
(constantly clojure.tools.logging.impl/disabled-logger-factory))
(is (thrown-with-msg? Exception #"Message not processed"
(test-utils/process-message! msg 2)))
(finally
(alter-var-root #'clojure.tools.logging/*logger-factory* factory))))
@technomancy
technomancy / crash.log
Created December 26, 2017 23:36
urn crash in luaj
~/src/urn $ make test LUA=luaj
luaj bin/urn.lua tests/compiler/codegen/precedence --run -o /tmp/tmp.9mEtsMxCet -fstrict-structs --
org.luaj.vm2.LuaError: bin/urn.lua:2034 vm error: java.lang.ArrayIndexOutOfBoundsException: -1
stack traceback:
bin/urn.lua:2034: in function 'parseDocstring1'
bin/urn.lua:10481: in function 'validate'
bin/urn.lua:10501: in function 'run'
bin/urn.lua:2858: in function 'runPass1'
bin/urn.lua:10583: in function '?'
bin/urn.lua:11332: in main chunk