beneroth changed the topic of #picolisp to: PicoLisp language | The scalpel of software development | Channel Log: https://libera.irclog.whitequark.org/picolisp | Check www.picolisp.com for more information
alexshendi has quit [Read error: Connection reset by peer]
alexshendi has joined #picolisp
bjorkintosh has quit [Ping timeout: 276 seconds]
<geri> abu[7]: hey, can you walk me through how binding works in (quote (A B) (+ A B))?
<geri> well, ('((A B) (+ A B)) 1 2) probably
<abu[7]> Hi geri, the syms A and B are pushed, set to new values, '+' is called, and the values restored
<geri> a single bind frame is (very simplified) an alist mapping symbols to their previous values right?
<abu[7]> No
<abu[7]> a stach struct
<abu[7]> doc/structures
<geri> im still not very good at reading those structures 😭
<abu[7]> "Bind frame:"
<abu[7]> symN + valN
<abu[7]> Physically just 2 push instructions
<abu[7]> 'Bind' is a pointer to a linked list
<abu[7]> line 140
<abu[7]> valN <-- Bind
<geri> so a more efficient alist with gc workarounds but thats mostly it? :D
<abu[7]> I would not call it "alist" as it is not cells
<geri> association something!
<abu[7]> and yes, gc traverses it
<abu[7]> yes :)
<abu[7]> but never searched like an alist
<abu[7]> just to keep the values
<geri> well, if i has to implement it in picolisp itself id say it's be a list of alists
<geri> list for the stack, alist for bind frame
<abu[7]> ok, but not a list of lists
<abu[7]> just a list
<geri> huh
<abu[7]> A single bind frame is symN + valN + LINK
<abu[7]> Expr is there only in case of function calls
<geri> like ('A NIL)?
<abu[7]> 'let' etc. don't have it
<geri> link idk how to show
<abu[7]> Your A B case
<abu[7]> '((A
<abu[7]> ...
<abu[7]> (let A .. does not have Expr
<geri> what's Expr for?
<abu[7]> The function call
<abu[7]> an 'exe'
<abu[7]> ('((A B) (+ A B)) 1 2)
<geri> is it saced so it doesnt get gc'd if you idk, alter the function recursively? :D
<geri> saved*
<abu[7]> Mainly for tools like 'trail'
<abu[7]> gc save is not necestary
<abu[7]> code is safe anyway
<geri> okay
<geri> is the bind stack saved into the heap for stuff like upvar?
<geri> (or however its called)
<geri> just up?
<abu[7]> not the heap. The stack is a separate hardware controlled memory
<abu[7]> It is saved mainly for unbinding
<abu[7]> the bind stack entries
<geri> okay, i guess stack is checked during gc to check availability too theb?
<abu[7]> Otherwise you could just 'set' the values
<abu[7]> no for availability
<abu[7]> it is hardware-maintiained
<abu[7]> swapped etc.
<geri> i mean something something gc roots
<abu[7]> so potentionally infinite
<abu[7]> ah, yes
<abu[7]> all in such frames is 'gc'ed
<abu[7]> all those "frames"
<abu[7]> following 'Link'
<geri> okay, getting closer to comprehanding the truth :D
<abu[7]> the simplest one is "Saved values:"
<abu[7]> just a single value
<geri> is it about (save)?
<geri> in llvm
<abu[7]> correct
<geri> okay
<geri> you said the binding stack resolves an issue with unbinding, what is it about?
<abu[7]> the syms are restored to their previous values
<geri> i mean, you wouldnt have explicit access to the bindings stack if you did something like `any frame = your_structure`... (in C terms)
<abu[7]> Why no access?
<geri> cause its on the stack and not readily available as a variable you can mess with
<abu[7]> The old C pil did something like that
<geri> ah
<abu[7]> following the links on the stack
<geri> okay
<abu[7]> quite the same way I think
<geri> are A and B 2 different bind frames or a part of one?
<abu[7]> Two bind frames
<abu[7]> Like created by (let A 7 (inc A))
<geri> so if i call up, it'll walk the whole bind stack until it finds Nth reference to the symbol im asking about?
<abu[7]> T
<geri> okay, that makes a lot of sense now
<geri> thank you!
<abu[7]> Welcome! :)
<geri> im having a ton of fun experimenting how much you can implement without making the thing a primitive
<abu[7]> T, almost all
<geri> for example, (de Quote Arg (car Arg)) or (de List @ (rest))
<geri> eval is insanelt powerful
<abu[7]> (de Quote Args (cdr Args))
<geri> in particular, eval, quote, cons, car & cdr
<abu[7]> (de Quote Exe (cdr Exe)) to be exact
<geri> isnt it just (de Quote Any Any) actually? :D
<abu[7]> no
<abu[7]> ah, on the Lisp level yes
<geri> : (de Quote Args Args)
<geri> -> Quote
<geri> : (Quote 1 2 3)
<geri> -> (1 2 3)
<geri> : (quote 1 2 3)
<abu[7]> in PilSrc it is cdr
<geri> -> (1 2 3)
<geri> yeah, a little different in src
<geri> with a single while loop & cond/if you can implement most looping constructs i think
<abu[7]> Just 'loop' is best
<geri> while is simpler
<geri> but yeah
<geri> you can do a simple let by rewriting a lambda with instant application
<abu[7]> less general though
<geri> (let (A 5) A) => ((quote (A) A) 5)
<geri> obviously, machine code is more efficient, but its so fun
<abu[7]> :)
<geri> yeah its very fun honestly
<geri> :D
<geri> what can you do if you wanna write a non-eval function that takes arguments in a pretty destructured way?
<geri> like (de test (A B . @) ...) but non-eval
<geri> guessing use let or match destructuring
<abu[7]> Yes, no other way I think
<abu[7]> or simple car / cdr
<geri> manual destructuring :D
<abu[7]> T
<geri> i should look into how destructuring works overall
<geri> honestly i really like the idea of with-symbols, although the resulting function looks pretty horrifying when printing in picolisp
<geri> if you could have uninterned symbols with proper names you wouldnt even know it was uninterned symbols
<abu[7]> What does with-symbols do?
<geri> the magic with (box) i showed yestersay
<geri> gensym approach to mininizing synbol collisions
<geri> honestly (private) is about as ugly, but its built into the language so its faster
<geri> wait, how does (private) re-intern stuff if you call it twice?
<geri> iirc you said it interns into priv namespace
<abu[7]> (symbols '(priv) (read))
<geri> (private) (A B) ... (private) A
<geri> shouldn't second private return A in the priv namespace?
<abu[7]> s/return/intern
<abu[7]> (vi 'llvm~rdAtom)
<abu[7]> (intern (consSym Nm $Nil) 0 Nm $PrivT $Nil YES)
<abu[7]> Forces a new symbol
<geri> ah
<geri> how do i see address of the symbol pointer?
<geri> what's compared with ==
<abu[7]> You mean (== (car L) $priv) ?
<geri> i thin its jsut (adr 'thing)
geri has quit [Quit: ERC 5.5.0.29.1 (IRC client for GNU Emacs 29.4)]
geri has joined #picolisp
<geri> i messed something up
<geri> i think (adr 'thing) works
<abu[7]> yes, 'adr' gives the pointer
<geri> nice
<abu[7]> Eg. get the TAIL with (struct (- (adr Sym) 8) T)
<geri> oh huh
alexshendi has quit [Ping timeout: 248 seconds]
<geri> (struct (- sym 8) T)
<abu[7]> : (struct (- (adr 'car) 8) '(T T))
<geri> instant segmentation fault :D
<abu[7]> -> ((("@doc/refC.html" . doc) (((17 "@src/subr.l" llvm pico)) . *Dbg) . 7496035) 5927590773872)
<abu[7]> Bad sym?
<geri> sym & (adr 'sym) are not the same, even though both are pointers, huh
<abu[7]> '(T T) gives TAIL + VAL
<geri> cant do (adr 12) :(
<geri> i was wondeirng how much you can inspect using this trick
<abu[7]> 12 has no addsess
<geri> arent shorts cons cells though?
<abu[7]> no
<abu[7]> just a value
<geri> so shorts only take 64 bits?
<abu[7]> not pysically in memory
<abu[7]> 60 bits plus sign
<geri> + 3 bits for tag
<abu[7]> T
<abu[7]> So the pointer *is* the number
<geri> numbers can be in the heap as a part of a cons cell though, so technically it does get GC'd?
<abu[7]> Yes, gc must know about them
<abu[7]> cnt is skipped
<gahr> tankf33der: her
<abu[7]> big is marked
<geri> ah
<geri> personally gc is still far from clicking, but its progressing!
<abu[7]> 👍
<geri> how old were you when you started writing your interpreters?
<geri> like picolisp's older siblings
<abu[7]> It was first Forth
<abu[7]> about 28 perhaps
<abu[7]> Before that I wrote only assemblers
<geri> was it fun?
<abu[7]> Sure :)
<abu[7]> My first one was called SHIT (semi-hexadecimal instruction translato )
<geri> very nice name :DD
<abu[7]> It was hex code with jump offset calculations
alexshendi has joined #picolisp
<geri> wait, assemblers basically like syntax at&t & intel have for x86?
<geri> havent done them before :D
<abu[7]> It was another CPU though
<abu[7]> National Semiconductor's SC/MP
<gahr> tankf33der: don't we perhaps want to fixup the MAIN defintion to contain the pkg-config invocation?
alexshe81 has joined #picolisp
alexshendi has quit [Read error: Connection reset by peer]
taleon has quit [Remote host closed the connection]
<tankf33der> Morning
<tankf33der> did you received my email?
<tankf33der> gahr: i am ready to discuss
<gahr> hi, yes i have
<tankf33der> You should remove MAIN line from Makefile of ports on next release.
<tankf33der> Also i have additional questions about port
<gahr> so the MAIN line is not there anymore?
<gahr> I see it's still there in the latest snapshot
<gahr> but link flags are spread between MAIN and the CC call in the picolisp target
<tankf33der> -leeadline and libffi switched to pkg-config call!!!
<tankf33der> they are moved from MAIN
<tankf33der> This was patch
<gahr> yes, I understand
<gahr> I was wondering why don't you put the pkg-config flags in MAIN
<gahr> so all link options are there
<gahr> MAIN = -rdynamic -lc -lutil -lm -ldl `pkg-config --libs readline libffi`
<gahr> something like this
<tankf33der> Also ok, but i put pkg-config here to keep both calls together :)
<gahr> which calls?
<tankf33der> there are two calls of pkg-config
<gahr> the one in lib.bc target?
<gahr> ok anyway, I don't have a strong opinion, you are free to adjust the Makefile like you want :)
<gahr> what's the other topic you wanted to discuss?
<geri> abu[7]: so basically "yes" :D
<geri> i heard you can do assembly in any language, long as you know the opcodes
<geri> write a sequence of bytes that means "return 1" and you're golden
<geri> heard it in forth context
<geri> also, how do you know how many entries to pop out of binding stack once the function call is finished? :D
alexshendi has joined #picolisp
<tankf33der> gahr: why LLVM17 ?
<tankf33der> i meant min LLVM17
<gahr> min=17
<abu[7]> Shouldn't we better remove the MAIN var completely and put all into the CC line (as MAIN is needed only once anyway)
<gahr> abu[7]: that's also a possibility.. it depends how declarative you want your Makefile
<gahr> tankf33der: I think most people are running higher versions anyway, but I'm willing to change that: what minimum version would you prefer?
<tankf33der> gahr: picolisp works in range 11-20 out of box, i think i tested on llvm8 too
<gahr> ok I can put 11
alexshe81 has quit [Ping timeout: 252 seconds]
<abu[7]> I prefer to keep things in the place where they are needed
<abu[7]> OK, I remove MAIN
alexshendi has quit [Ping timeout: 248 seconds]
<tankf33der> gahr: next, why LIB_DEPENDS=libffi.so:devel/libffi ?
<tankf33der> where are openssl and readline depends?
<gahr> USES readline ssl
<gahr> this brings in dependencies on readline and ssl, + sets up stuff
<tankf33der> why you have a special line for ffi depend?
<abu[7]> Done and released
<gahr> tankf33der: because there's no USES ffi
<tankf33der> ok
<gahr> the lib dependency is enough
<tankf33der> gahr: so now MAIN is gone and you should remove MAIN on post-patch on next release too.
<gahr> cool, thanks
<tankf33der> see you.
<gahr> when is the new release due? I won't be around a computer much in the next days
<abu[7]> I think tankf33der pulls every hour or so
<tankf33der> every 3 monthes
<abu[7]> That's the Debian release
<abu[7]> I plan on 29th this month
<tankf33der> abu[7]: freebsd also uses this numbers
<tankf33der> PORTNAME=picolisp
<tankf33der> PORTVERSION=24.9
<abu[7]> ok
<gahr> yes, I know about the cadence, I wanted to know about the day, given the particular time of the year.. ok I guess I can update the port on 29th or 30th
<tankf33der> yeap, thanks
<abu[7]> 👍
<gahr> cool, thanks both :)
<tankf33der> afk
<geri> unafk
<geri> :D
<geri> abu[7]: i had a question above about how do you know how many frames to pop off of bind stack when function has been run
<geri> maybe theres some sort of counter im not seeing
<abu[7]> Depends on the use case
<abu[7]> In case of 'llvm~evExpr' it is until hitting '@'
<geri> ah, basically a magic value for a stop marker
<geri> that's neater that what i was thinking
taleon has joined #picolisp
<abu[7]> For 'let' it is either just one
<abu[7]> or remembered in 'Q'
<geri> what's Q?
<abu[7]> A local variable
<abu[7]> (vi 'let)
<abu[7]> at the end
<geri> im honestly not a fan of every argument being named as a single letter where you have no idea what's it supposed to be doing
<geri> xd
<abu[7]> P and Q are usually pointers in PilSrc
<geri> hmm
<abu[7]> (let (P (val $Bind) Q P)
<abu[7]> (? (== Q (setq P ...
<geri> (== Anything (setq ...)) is such a C pattern :D
<geri> ive seen you use it a lot in gc.c in original picolisp for example
<abu[7]> Yeah, same
<geri> what's going on in mapcar?
<geri> im guessing workarounds for f expressions in some way, shape or form
<abu[7]> "going on" in which sense?
<geri> its huge and im confused what's actually happening inside
<geri> :D
<geri> cause typical map function will be like half of that side
<geri> size
<abu[7]> It is basisally an "apply"
<geri> basically fexps make first class functions less nice to implement?
<geri> but give first class macros
<geri> is it also basically quoting the arguments before passing them to the function?
<abu[7]> No, it is all about evaluating and applying the args
<abu[7]> Look at 'apply' first
<abu[7]> ad
<abu[7]> and doc/structures
<geri> apply is even scarier
<geri> :D
<abu[7]> Mapping lists is applying the elements of all lists to the fun
<geri> that i know
<geri> i dont know how are you making it work with fexps
<geri> cause if mapcar is evaluating, and print is evaluating, then your list is eval'd twice and it doesnt work
<geri> (mapcar print '(1 2 3))
<geri> well
<geri> (mapcar print '(a b c))
<geri> mapcar will eval the list and get (a b c)
<geri> if you pass it as is to print, then it'll try to eval a and that's not bound and nothing works
<geri> if you quote it beforehand it should work...
<abu[7]> see doc/structures
<abu[7]> Apply
<geri> looks like binding stack
<abu[7]> It is more
<abu[7]> builds an exe
<abu[7]> which quotes the elements of the list
<abu[7]> by putting into symbols
<geri> doesn't sound much different from what i said
<geri> except putting into symbols instead of using quote
<abu[7]> T
<geri> brb lunch
<abu[7]> pil32 indeed used quote's in apply
<geri> if you know that the function doesn't evaluate its arguments (or does), you could make apply work with both, no?
<geri> just skip quoting step when it doesnt evaluate its arguments
<geri> abu[7]: why'd you switch from quote to symbol construction?
<geri> sounds like both are 1 pointer reference
<abu[7]> A non-evaluating fun (FEXPR) cannot be applied at all
<geri> why?
<abu[7]> 'apply' expects already eval'ed arguments
<abu[7]> "switch": Both are OK
<geri> switch?
<abu[7]> "switch from quote to symbol"
<geri> ah
<abu[7]> symbols are a little faster
<abu[7]> quote is a function call
<geri> okay, fair
<geri> honestly its also a little simpler
<geri> less consing
<geri> well, or less interning
<geri> :D
<geri> i like how the way picolisp quote works is more efficient while not being much different for typical use
<geri> cause people dont use (quote) often, more likely to use '
<geri> and '(hello) is equal in pico quotes and other lisp quotes
<abu[7]> T
<geri> )
<geri> and you don't even see it when pretty printing
<abu[7]> But shows ugly anon syms
<geri> :(
<geri> im writing yet another lisp interpreter cause fun
<abu[7]> 👍
<geri> made "gensym" just let you name the symbols arbitrarily
<geri> so if you use with-symbols or something like that the user wont even know those are gensym'd
<abu[7]> Then it is 'pack'
<geri> m?
<abu[7]> gensym with name
<geri> oh
<geri> maybe yeah
<abu[7]> or 'name'
<geri> does (pack) always create uninterned symbols?
<abu[7]> yes
<geri> oh nice
<abu[7]> only 'read' interns transients
<abu[7]> (name 'car)
<geri> so if i replace box with (name) or (pack) i could make the mechanism nice?
<abu[7]> I think so
<geri> nicer*
<abu[7]> (nicer)
<abu[7]> :)
<geri> (name) also always creates uninterned symbols?
<abu[7]> T
<abu[7]> or (char 66)
<geri> neat
<abu[7]> you can create also syms from a counter with 'format' to get a bunch of syms
<geri> and that's where you get actual gensym
<beneroth> hi all :)
<geri> in other lisps only difference between make-symbol and gensym is that gensym generates semi-random names, increasing index by 1 with every call
<beneroth> gahr, thanks for your help!
<beneroth> abu[7], tankf33der - thanks, as always <3
<beneroth> geri, what lisp dialects are you talking of? (honest curious question)
<abu[7]> Welcome beneroth :)
<geri> at least elisp and common lisp
<abu[7]> So gensym is closest to 'box'
<geri> from builtins i guess
<abu[7]> With the difference that pil anon syms can also be *read*
<geri> name and pack are closer to make-symbol
<geri> format pack is the actual strategy gensym uses in common lisp
<geri> abu[7]: how do you refer to something that doesnt have a name? xd
<abu[7]> I see
<abu[7]> $177770325252523 actually is the address
<geri> oh
<geri> yeah that's true i guess
<abu[7]> : (box 7)
<abu[7]> -> $177701060634235
<abu[7]> : (val '$177701060634235)
<abu[7]> -> 7
<abu[7]> Dangerous though ;)
<abu[7]> (val '$12345)
<geri> just as dangerous as doing pointer arithmetic on builtins
<abu[7]> T
<geri> much nicer
<geri> dont even need to edit code :D
<abu[7]> ☺
<geri> its pretty much the same thing as using (private) or abusing transient namespace though
<geri> reinventing the wheel is very fun though
<geri> i think you only care about collissions when setting things or evaluating arbitrary forms though
<geri> could also write a function that replaces all symbols with transient symbols with same value as current...
<geri> for no reason whatsoever!
<beneroth> meta-programming to generate FEXPRs would be a reason
<geri> it's an interpreted lisp
<beneroth> though generating FEXPRs is kinda... weird. Probably not using FEXPRs correctly or overdoing metaprogramming
<geri> everything we do is meta
<geri> :D
<geri> when you say generating fexprs i think of (eval (list 'setq thing1 thing2))
<beneroth> in FEXPRs you usually want the parameters and local variables to be transients (or namespaced) to ensure that no name collision/shadowing could happen in the evaluation within the FEXPR
<geri> oh yeah
<geri> in the first place i started writing this as a resolution to symbol collissions
<beneroth> a fexpr in picolisp is a (de foo X ...) or (de foo (EvalParam1 EvalParam2 . X) ...) function
<geri> for my interpreter though
<beneroth> X = unevaluated argument list
<geri> yeah i know that much
<geri> wait
<geri> did you see the file i sent?
<beneroth> so usually you then use (run) or (eval) with it within the FEXPR. unless the FEXPR is a full interpreter iterating through the parameters or whatever
<geri> that's like exactly what im doing, just limited to particular symbols
<beneroth> I haven't seen your file
<beneroth> FEXPRs are interpreter-functions, right. That's why they are not compilable (not in all cases), that's why compiled lisps dropped them
<geri> just replaces every symbol provided with transients and then evaluates the body
<beneroth> you know about (bind) yes=
<beneroth> ?
<geri> im literally using it in with-symbols
<beneroth> ah yes you use it
<beneroth> good
<beneroth> :)
<geri> the idea is, i dont need to rewrite anything but i ensure that Args and other args will never collide with anything else
<beneroth> yeah. you can think of (bind) relation to (let) like the relation of (set) to (setq) ;-)
<geri> its arguments are a little different
<geri> bind takes an alist, let just a list or even a symbol followed by some exp
<geri> s/just a list/flat list
<geri> also set can set pairs' car
<geri> :D
<geri> oh wait
<geri> abu[7]: does it work cause car of cons is in same position as value of a symbol?
<abu[7]> the CAR ?
<geri> (a . b) vs (head . value)
<abu[7]> CAR vs. VAl
<abu[7]> T
<geri> so in first case pointer points to a, in second to value
<geri> the function just sets whatever's directly at the pointer
<geri> hence double behaviour
<beneroth> it's efficient
<abu[7]> Exactuy
<abu[7]> ly
<geri> also mind bending
<geri> not like i mind that though
<geri> apply finally clicked today too
<beneroth> simply elegant :)
<geri> well, not the code but what it does in theory
<geri> :D
<abu[7]> (sorry, we are in Augsburg'c Xmas market, cant follow all the time)
<geri> enjoy
<abu[7]> ☺
<beneroth> abu[7], enjoy!
<abu[7]> family is getting angry ;)
<geri> haha
<geri> well, logs are there for a reason
<abu[7]> ok ☺
<geri> (dolist2 (X Args) (prin X) (prinl))
<geri> how do i properly destructure it into the X from car, Args from car and rest?
<geri> (let (((Var . L) . Body) Args) ...) seems to not be doing L right
<geri> without dot before L it's also wrong
<geri> actually wait, i forgot to eval it
<geri> actually nevermind again, i frogot that i got collissions
<geri> xd
<beneroth> I think you forgot a dot
<beneroth> ah no
<beneroth> it's a call, not definition
<beneroth> sorry I'm busy packaging here for a short holiday vacation :)
<beneroth> I can't follow you exactly
<beneroth> X is an atom value or a pair?
<geri> i fixed it
<beneroth> if you want to iterate through all arguments you could also do e.g. like (de foo X (while X (case (++ X) (namedParam1 ..) (namedParam2 ..) (T ...)))
<beneroth> ah okay
<beneroth> good :)
<geri> i also made the with-symbols function use a transient symbol for param
<geri> :D
<beneroth> good :)
<beneroth> you should dolist too, to handle the case when someone calls dolist with the symbol 'Args
<geri> dolist is solved using with-symbols
<geri> that exact case was the whole reason im even writing this haha
<geri> i'd say its done
<beneroth> I don't understand the (fill ...) in with-symbols tbh
<geri> honestly i dont either, but it works
<geri> XD
<geri> somehow it just replaces every symbol passed (i.e. (Args Var Body L)) in the body
<beneroth> the (run) is supposed to evaluate the second argument to with-symbols, and the first argument in with-symbols is the argument list you secure into transients before bindings, right?
<geri> yes
<geri> fexps are amazing honestly
<geri> too bad you cant compile them efficiently
<beneroth> you can. efficiency is not the problem. the problem is, some FEXPRs you cannot compile at all, because what they do is completely up to the arguments, which might be complete runtime-dependent (e.g. based on user input) so you cannot know what to do during compile time
<beneroth> how about:
<beneroth> (de with-symbols "Body"
<beneroth> (bind
<beneroth> (mapcar '((X) (cons X (name X))) (car "Body"))
<beneroth> (run (car "Body")) ) )
<beneroth> (not tested)
<geri> that won't replace the symbols with generated ones
<beneroth> the argument "replacing" is already happening with (bind), I think (fill) is not needed?
<beneroth> ah
<beneroth> you're right, I see
<geri> bind here actually only binds Body to "Body" and such
<geri> you can probably make it simpler though
<beneroth> T
<geri> or not :)
<beneroth> maybe
<geri> youll need to alter the (de) call a lot if you dont use fill
<beneroth> just use always transients (or namespaced) symbols for parameter names in every function definition, then you don't need this :)
<beneroth> (though in FEXPRs is enough)
<geri> also make sure you dont have collissions in a single file
<geri> its not needed per se, just fun
<geri> not in picolisp anyway
<geri> okay so if you have an interpreter only for fexps, you can implement lambdas with eval and mapcar
<geri> :D
<beneroth> see also (===)
<geri> ====*
<beneroth> FYI a (load) also closes and opens a new transient scope
<geri> yeah
<beneroth> can give tricky issues if you sprinkle multiple (load)s in your file instead of one at the top
<geri> fun
<beneroth> aye!
<beneroth> BBL
beneroth has quit [Quit: Leaving]
bjorkintosh has joined #picolisp
bjorkintosh has joined #picolisp
<abu[7]> geri: (prin X) (prin "!") (prinl) can be reduced to (prinl X "!")
galambo has joined #picolisp
bjorkintosh has quit [Remote host closed the connection]
DKordic has quit [Ping timeout: 265 seconds]
galambo has quit [Quit: Leaving]
galambo has joined #picolisp
chexum has quit [Remote host closed the connection]
chexum has joined #picolisp
bjorkintosh has joined #picolisp
bjorkintosh has joined #picolisp