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
aw- has joined #picolisp
Hunar has joined #picolisp
<Hunar> Good morning :)
<Regenaxer> Good morning Hunar!
<Hunar> Regenaxer, there are alot of functions that return bool (1 or 0) in raylib, but to use (or) on them I need T and NIL ..  If I use native I would just do    (def isKeyDown (KEY) (=1 (native "libraylib.so" "IsKeyDown" 'B KEY)) )   but if I let  clang.l   generate the functions for me then I (think) I'll need another function which passes the
<Hunar> return through (=1) am i right? I dont want to make a function that calls another function that calls native.. can I do that with only clang.l?
<Regenaxer> Note that 'def' above is in fact 'de'
<Hunar> Sorry misspelled
<Regenaxer> I would not check for =1 but for =0
<Regenaxer> In C everything except zero is true
<Hunar> But the question is isKeyDown
<Hunar> so (not (=0 ..)) ?
<Regenaxer> or (n0 ...)
<Hunar> oh :)
<Regenaxer> or use the reverse flow functions
<Hunar> what is that
<Regenaxer> ifn, nond, unless, until
<Hunar> aha
<Regenaxer> (n0 X) is the same as (not (=0 X)) but faster
<Regenaxer> So yes, some comparison with zero is needed
<Hunar> Ok :)  what about the other issue.. using native is one function call + 1 native call .. can I do that with clang.l
<Hunar> Or I need 3 steps
<Regenaxer> How do you mean that"
<Regenaxer> ?
<Regenaxer> Avoid the =0 ?
<Hunar> Let me write some code :)
<Regenaxer> You could return directly NIL perhaps
<Regenaxer> It is the global $Nil internally
<Regenaxer> I never tried that, but I think you can specify the glue functon as 'T' return
<Regenaxer> then return $Nil; in the glue
<Regenaxer> the glue could be declared as void*
<Regenaxer> Perhaps you need to include "src/pico.h"
<Hunar> (clang "pilrays" '("-lraylib")
<Hunar>   (isKeyDown2 (KEY) isKeyDown 'B KEY )
<Hunar> /C stuff here
<Hunar> (de isKeyDown (KEY) #I'm trying to avoid writing this function and do it in the above step
<Hunar>   (n0 isKeyDown KEY))
<Hunar> (Perhaps you need to include "src/pico.h") would that increase clang compilation time?
<Regenaxer> (n0 (isKeyDown ...
<Hunar> sorry, speedtyping :)
<Regenaxer> No, you won't notice
<Regenaxer> Do you want to do key handling too?
<Regenaxer> This might be tricky, tty, raw mode etc
<Hunar> Actually it worked without any problems
<Regenaxer> I see, cool
<Hunar> https://pastebin.com/raw/3qCHqAFu  this worked without any issues
<Regenaxer> Page not found
<Regenaxer> now works
<Hunar> back to the problem, if i use (specify the glue function as 'T' return) that would also require me to write a c glue code, my intention was to reduce code :)   so i would just write the lisp code instead
<Hunar> just noticed, DrawCircle(x,y,r,col); this was a debugging code I should have deleted
<Regenaxer> On some point you need to do 0 -> NIL
<Regenaxer> So in the C part it is fastest
<Hunar> Ah
<Regenaxer> return !xxx? $Nil : $T
<Hunar> what is that syntax :/
<Regenaxer> I'm just not sure how to declare that in the C function
<Regenaxer> the return type
<Regenaxer> internally all values are just i64
<Regenaxer> in llvm
<Regenaxer> in C that is int64_t
<Regenaxer> see src/lib.c for internal glue
<Regenaxer> to the system functions
<Hunar> That would require some digging, I'll check it out later..
<Regenaxer> ok
<Hunar> one quick side-question .. what would be the most comfortable way to write/access vector (xy or xyz) data in pil? in C a struct is very easy and compact to use    a.x a.y a.z    but in pil I used a list (1 2 3) and (inc a) (inc (cdr a)) (inc (cddr a)) instead, is there a nicer looking solution?
<Hunar> are classes better?
<Regenaxer> I would go for lists here, objects are heavier
<Regenaxer> well (inc (cdr A)) for the second ~ I think there is nothing shorter
<Regenaxer> sometimel you will 'map' the vectors
<Regenaxer> (map inc A) increments all
<Regenaxer> but a single access is cdr or nth
<Regenaxer> You can keep local bindings
<Regenaxer> (let B (cdr A) ... (inc B))
<Regenaxer> btw, remember to use upper case locals
<Hunar> Cool :)
<Regenaxer> 'e', 'd' or 'u' are functions for example
<Hunar> I'll translate the names :)   don't worry
<Hunar> the library naming is all over the place
<Regenaxer> The names of the struct elements, yeah
<Hunar> I could make these functions    (.X VECTOR) (.Y VECTOR)  but I think pil programmers would get mad at me
<Regenaxer> yeah, better not too much hiding
<Hunar> I agree, I had that issue alot when I used c++
<Hunar> also common-lisp
<Regenaxer> T, it is hard to find a good balance
<Regenaxer> some abstractions, but not too much obfuscation
<Hunar> For the glue code, I think I'll also modify clang.l a bit to let people  (If they want to) use an .so file instead of recompiling it every time .. but maybe not if i was lazy
<Hunar> I'll just grab the temporary file and ship it with the releas
<Hunar> e
<Regenaxer> Yeah
<Regenaxer> no need to modify clang.l
<Regenaxer> (call "cp" (tmp "name") "somewhere/else")
<Regenaxer> hmm, but the calls need to be modified too, ok
<Regenaxer> I would not worry about the startup speed
<Hunar> In termux it was noticable
<Regenaxer> only the first time, I think. After that the compiler is cached, and runs faster
<Regenaxer> and it is only at startup anyway
<Hunar> For me, the initial startup takes 2 seconds, the following startups take 1 second
<Regenaxer> ok, I see
<Hunar> It only has one struct and a function that returns it.. so it's all the compile time
<Hunar> No body would use termux for my libraries at least :)
<Regenaxer> The compile is fast
<Regenaxer> it is starting clang
<Hunar> Aha
<Regenaxer> so the length of your code does not matter
<Hunar> I'll now go to dig into the (!xxx? $Nil : $T) problem
<Regenaxer> ok :)
<Hunar> :)
<Regenaxer> Cool, it works!
<Regenaxer> Could not resist to test the T return with Nil
<Regenaxer> http://ix.io/3FQd
<Regenaxer> No need to include full pico.h
<Regenaxer> just two lines
<Regenaxer> extern int64_t SymTab[];
<Regenaxer> #define Nil (0+1)
<Regenaxer> This is even better: http://ix.io/3FQh
<Regenaxer> just return Nil;
<Hunar> Great :D
<Hunar> I'll try them now
<Regenaxer> I like it :) Looks very useful
<Regenaxer> ok
theruran_ has quit [Ping timeout: 264 seconds]
theruran_ has joined #picolisp
<Hunar> I got distracted, then tried it and almost said it works.. but what to return instead of Nil?  this crashes when I press the button   http://ix.io/3FQm
v_m_v has joined #picolisp
<Regenaxer> Hunar, ah, sorry! Yes, we need also T
<Regenaxer> hmm, this is trickier
<Regenaxer> So it does need pico.h
<Regenaxer> you could return a number instead
<Regenaxer> eg 1 which is 18
<Regenaxer> 0x12
<Regenaxer> i.e. a short number (0x02) with value 1 (0x10)
<Regenaxer> For T see pico.h
<Regenaxer> #define T (17*2+1)
<Regenaxer> this is not good, because it *might* change with future pil releases
<Regenaxer> Including pico.h would be best
<Regenaxer> but how to make the path?
<Regenaxer> On Lisp it is "@src/pico.h"
<Regenaxer> but this must somehow be expanded in clang so that C understands it
<Regenaxer> Perhaps we should improve clang.l for that
tankf33der has quit [Quit: the lounge - https://webirc.envs.net]
tankf33der has joined #picolisp
Hunar has quit [Quit: Client closed]
Hunar has joined #picolisp
<Hunar> I used #define T (17*2+1)   it returns the number 2 .. I think the pil version i'm using is older
<Hunar> As long as it's not NIL it's fine for me
<Regenaxer> T is still (17*2+1)
<Regenaxer> you must return SymTab plus that value
<Regenaxer> just as Nil is SymTab plus 1
<Regenaxer> What if we make clang.l *always* include pico.h automatically?
<Regenaxer> Would make life easier
<Regenaxer> and clang.l knows the correct path
<Regenaxer> so it is easy here
<Regenaxer> You can also use the other C macros defined there
<Regenaxer> Works
<Regenaxer> Should I release that?
<Regenaxer> Or can it break something?
<Regenaxer> I think nobody used clang.l so far ;)
<Regenaxer> My simple test is then http://ix.io/3FQB
<Regenaxer> The question is: Does it do any harm if clang.l *always* includes @src/pico.h ?
Hunar has quit [Quit: Client closed]
Hunar has joined #picolisp
<Regenaxer> No, I don't change clang.l
<Regenaxer> Let's stay with just NIL
<Hunar> I'm back .. Chatting from work sucks, one sentence each hour
<Regenaxer> :)
<Regenaxer> I wrote something above
<Regenaxer> but reverted now
<Regenaxer> The nasty thing is to get the path to pico.h right
<Regenaxer> C wants pathnames relative to the source
<Regenaxer> Hard to get that portably
<Regenaxer> So if you like include pico.h instead of stdio.h yourself
<Hunar> One question, what was the problem exactly with these       #define Nil (SymTab+1)    #define T (SymTab+(17*2+1))     ... and if I include pico.h would I have problem if pil changes?
<Regenaxer> If the order of entries in SymTab should ever change, SymTab+(17*2+1) is no longer correct
<Regenaxer> pico.h would be updated
<Hunar> what if I made a local copy of the glue .so file .. then later versions would have problem?
<Regenaxer> yes
<Regenaxer> the offet to T could be wrong
<Regenaxer> I don't think SymTab will change in this place, but we cannot be sure
<Regenaxer> So if you want to use T, include pico.h instead of stdio.h
<Regenaxer> and write return SymTab+Nil;
<Regenaxer> instead of Nil in our first example
<Hunar> I might use pil code if it got more complicated :)
<Hunar> I mean, do it from pil code
<Regenaxer> yeah
<Regenaxer> 'native' does most conversions covered in pico.h by itself
<Regenaxer> So pico.h is probably not necessary
<Regenaxer> except perhaps for this Nil case
<Regenaxer> So we should perhaps just hard-code Nil into clang.l ?
<Regenaxer> ok, no
<Regenaxer> Let's not overdo it
<Regenaxer> Returning 0 or non-0 is C-ish
<Regenaxer> and checking (=0 on the caller side is all right
<Hunar> I initially thought the following would work,    look at this line when defining a function with clang.l      (pilName (pilVar) cName NIL cVar)    if i wanted to change something before sending it to native i did it here,  like   changing cVar to   (car cVar)   I thought there is also a way to modify the NIL such that before it
<Hunar> returns the result i can do something with it   chaning NIL to (prog (stuff) NIL)   but I soon found out it doesn't work like that
<Hunar> wait, I think we can do that
<Hunar> (def (car L)
<Hunar>   (list
<Hunar>     (cadr L)
<Hunar>     (cons 'native (tmp Nm) (name (caddr L)) (cdddr L)) ) )
<Hunar> by changing this from clang.l
v_m_v has quit [Remote host closed the connection]
v_m_v has joined #picolisp
<Hunar> if   (cadddr L)=something that we can detect      then       apply the thing we send to the result of (cons 'native (tmp Nm) (name (caddr L)) (cdddr L)) ) )         else   just do        (cons 'native (tmp Nm) (name (caddr L)) (cdddr L)) ) )
<Hunar> I want this    (pilName (pilVar) cName (T '((V) (n0 V))) cVar)    how can I detect if (cadddr L)   is a list that starts with T?
<beneroth> check the car of the List for (=T) ?
<beneroth> can combine it with the (cadddr L)
<Hunar> I want to determine if the argument is like this  T NIL S etc.. or a list, that starts with T
<Hunar> In common lisp there was    listp  which returns true of you passes a list to it, how can i detect list li pil
<Regenaxer> uuh
<Regenaxer> I don't really get it :)
<Regenaxer> To check for a list use 'pair' (or 'lst?' if also NIL for "empty list")
<aw-> or (flg?)
<aw-> because NIL is also a list
<Regenaxer> flg? checks only T or NIL
<aw-> oh sorry, checking for list not for flag
<aw-> I use (lst?) to check if it's a list, but as Regenaxer said NIL is also a list so be aware of that
<Hunar> I'm trying to make another thing besides the result specification, I want to check if the caller passed a function instead of these  NIL B C W I N P S -1.0 +1.0 T
<Hunar> aw- thanks:)   I thought it was list?
<aw-> Hunar: in your case, probably a (cond) is best, test for (flg?) first, that rules out NIL and T, then you can safely test for (lst?) and others..
<Regenaxer> or 'pair'
<Regenaxer> which is the *real* type check
<Regenaxer> lst? is (or (not X) (pair X))
<v_m_v> How I can limit my query like a sql "limit" ?
<Hunar> I think pair is easier to check for  (T . '((V) (n0 V)))   :)
<Regenaxer> I don't remember what "limit" does
<Regenaxer> '((V) (n0 V)))  is a tautology
<v_m_v> I would like to get only 10 records from my database
<Regenaxer> just n0 then
<Regenaxer> v_m_v, then do 10 iterations
<Regenaxer> in 'pilog'
<v_m_v> Hmm what do do mean by 10 iterations? I am getting all the events which timestamp is between N and Inf. But I would like to get only 10 of them
<v_m_v> I would like to limit the maximum amount of returned objects
<Regenaxer> You can do: (let Q (goal CL) (do 10 (bind (prove Q) ...
<Regenaxer> ie. do the same as 'pilog'
<Regenaxer> or simply throw
<v_m_v> ohh...so much complexity to get only 10 elements?
<Regenaxer> like in pil21/app/sales.l
<v_m_v> but throw will grab everything and then throw the things which I dont need right?
<Regenaxer> You can also check a count in your pilog
<Regenaxer> yes, throw cleans up
<v_m_v> So it will not limit my amount of data which I am grabbing from DB
<Regenaxer> I mean, what meaning do 10 results have, if therr are in fact more?
<Regenaxer> I never had this issue
<v_m_v> If you would like to build an pagination then how you would build that ? For example in DB you have 100 mln records.
<Regenaxer> Yes, pagination is done in GUI dialogs
<Regenaxer> +QueryChart
<Regenaxer> it fetches as many results as there are rows in the table
<Regenaxer> then you can scroll infinitely
<Regenaxer> 'goal' and 'prove' are the basic tools
<Regenaxer> (pp 'pilog) shows it too
<v_m_v> For each of those pages I would like to get X number of objects in my database. So I have an query: https://pastebin.com/gZQQfrh7 and I would like to add limit there ...
<Regenaxer> Don't use 'solve' then
<Regenaxer> look at 'solve
<Regenaxer> It is also simply goal and prove
<Regenaxer> And check out how the GUI in @lib/form.l does it
<beneroth> v_m_v, you can also use (make (catch 'finished ... (iter .. (link Result) (at (0 . 10) (throw 'finished)))). replace iter with pilog, but pilog guarantes now order
<beneroth> SQL is also getting all results (at least insofar as it needs depending on indexes and WHERE clauses) and then throwing stuff away, just happens in the server automatically
<Regenaxer> yeah, but (do 10 is easier I think
<beneroth> T
<Regenaxer> 'prove' is like CURSOR in SQL
<Regenaxer> 'prove' is the internal workhorse
<beneroth> T
<Regenaxer> The sales.l report above does
<Regenaxer> (at (0 . 10000) (or (flush) (throw))) )
<Regenaxer> but this is only to detect that the browser is gone
<Regenaxer> ie broken pipe if (flush) fails
<Regenaxer> normally (throw) is never executed and the report runs through
<Regenaxer> Anyway, long talk, but 'solve' is simply a for loop around goal and prove
<Regenaxer> (for (Q (goal CL) (prove Q))
<beneroth> Regenaxer, oh good point with the flush, I see. Haven't used that, no problems so far. But see what you mean, nice point.
<Regenaxer> It is normally not needed
<beneroth> yeah of course
<Regenaxer> but with wrong parameters a report may become too long
<Regenaxer> and users close the browser :)
<beneroth> though I have an application hosted here which is used by users in Asia, and I've problems. But only in upload, and it's likely a company network issue.
<beneroth> no problem when user use another network from same location, that is kinda a strong indicator...
<v_m_v> to be honest I don't understand how to change solve to prove with limit :/ It is out of my reach
<Regenaxer> oh, sorrt
<Regenaxer> sorry
<Regenaxer> Think of it as this: 'prove' gives you one result after the other
<Regenaxer> that's all!
<Regenaxer> You can do with it what you like
<Regenaxer> 'pilog' and 'solve' are just convenience funs
<Regenaxer> in fact seldom used
<Regenaxer> I use 'pilog' in reports like the above one
<Regenaxer> 'solve' I never used in a production app I believe
<Regenaxer> If I expect a result list, 'collect' with list functions is easier
<Regenaxer> "limit" per se is useless. You want to continue after that, right?
<Regenaxer> So you need a handle to the Query
<Regenaxer> (let Q (goal CL)
<Regenaxer> Then you can call (prove Q) whereever you like, and how often you like
<Regenaxer> Using normal Lisp level flow functions
<v_m_v> how the query would be different from solve ?
<Regenaxer> ap: (setq Q (goal '((db nr +Item @I))))
<Regenaxer> -> (((1 (0) NIL ((db nr +Item @I)) NIL T)))
<Regenaxer> ap: (prove Q)
<Regenaxer> -> ((@I . {B1}))
<Regenaxer> $ap: (prove Q)
<Regenaxer> -> ((@I . {B2}))
<Regenaxer> No difference
<Regenaxer> 'solve' only does (for (Q (goal CL) (prove Q))
<Regenaxer> (vi 'solve)
<Regenaxer> There is no magic at aul
<Regenaxer> all
Hunar has quit [Quit: Client closed]
<Regenaxer> So this is 'pilog' basically:
<Regenaxer> : (for (Q (goal '((db nr +Item @I))) (prove Q)) (bind @ (println @I)))
<Regenaxer> {B1}
<Regenaxer> {B2}
<Regenaxer> {B3}
<Regenaxer> {B4}
<Regenaxer> {B5}
<Regenaxer> {B6}
<Regenaxer> Then you limit it to 3 with:
<Regenaxer> : (for ((N . Q) (goal '((db nr +Item @I))) (prove Q)) (T (> N 3)) (bind @ (println N @I)))
<Regenaxer> 1 {B1}
<Regenaxer> 2 {B2}
<Regenaxer> 3 {B3}
<Regenaxer> -> NIL
<Regenaxer> But as I think such a simple case is useless
<Regenaxer> what with the other results?
<Regenaxer> So you want to continue upon some event
<Regenaxer> This logic has to be defined
<Regenaxer> Like in the GUI
aw- has quit [Ping timeout: 264 seconds]
razzy has quit [Ping timeout: 250 seconds]
v_m_v has quit [Remote host closed the connection]
razzy has joined #picolisp
v_m_v has joined #picolisp
v_m_v has quit [Remote host closed the connection]
Hunar has joined #picolisp
<Hunar> Regenaxer :) I did it, Here is the code with the modified clang.l on the top .. prepare your eyes for horrible looking too wide code http://ix.io/3FST   so now when using clang.l if the return type was a list, then car is the return type and the cadr is a function that takes the C result as input and makes the output for pil
<Hunar> If the result list is like (NIL fun) then fun is not going to be used, I'm not sure if that's a bad decision
Hunar has quit [Quit: Client closed]
Hunar has joined #picolisp
Hunar78 has joined #picolisp
Hunar has quit [Quit: Client closed]
Hunar78 is now known as Hunar
<Regenaxer> Hunar, ok, though it seems a bi overkill to me :)
<Hunar> The idea or the code
<Regenaxer> The idea
<Hunar> :) It makes me happy, that would reduce tens of lines in the binding
<Regenaxer> What kind of fun did you think of? '=0' ?
<Regenaxer> If it makes you happy, then it is perfect :)
<Hunar> What do you mean :/
<Regenaxer> kind of fun?
<Regenaxer> or happy-making?
<Hunar> Ah you're talking about the name
<Hunar> It wasn
<Regenaxer> Which name?
<Hunar> Sorry, can you rephrase this question :)   (What kind of fun did you think of?  '=0' ?) It seems that I didn't understand again
<Regenaxer> What kind of fun did you think of? '=0' ?
<Regenaxer> cadr is a function
<Regenaxer> the C result as input and makes the output for pil
<Regenaxer> So like (=0 (native ... ?
<Regenaxer> making a flg from a cnt
<Hunar> it makes this    ( '((V) (ne V))   (native ...
<Hunar> sorry, n0
<Regenaxer> again, '((V) (n0 V)) is a huge overhead
<Regenaxer> just 'n0' !
<Regenaxer> Lisp function calls are relatively expensive
<Hunar> I'll probably chose =1 instead then :)
<Regenaxer> Why?
<Regenaxer> n0 is better
<Regenaxer> for C
<Regenaxer> cause everything nonzero is true
<Regenaxer> I would not rely on 1
<Hunar> But you're saying it's a huge overhead :/
<Regenaxer> '((V) (=0 V)) is the *same* as just =0
<Hunar> Ah, now I get it
<Regenaxer> :)
<Regenaxer> Like:
<Regenaxer> : (mapcar '((V) (=0 V)) (1 0 2 0 3))
<Regenaxer> $: (mapcar =0 (1 0 2 0 3))
<Regenaxer> -> (NIL 0 NIL 0 NIL)
<Regenaxer> -> (NIL 0 NIL 0 NIL)
<Hunar> I didn't think of it, It's a little bit more flexible i think.. if the user wanted to do further stuff with the result before returning it .. but in that case they can manually add the '((V) ..) :) I'll change it then
<Hunar> small question, is there (not equal) in pil?
<Hunar> this is much better   (fun (N) fun '('I 'n0 N))  :)
<Regenaxer> yes, if a bigger function is needed then a Lisp function is necessary
<Regenaxer> not equal is either '<>' or 'n=='
<Regenaxer> opposites of '=' and '=='
<Hunar> I was searching for it the (doc '=) maybe it should be in the See also   section
<Regenaxer> true
<Hunar> I just had a thought, I wondered if minipicolisp would work in Arduino (AVR chip) .. I installed avr-gcc and tried compiling it .. It complained about fopen which can be removed since we don't have files in a micro controller .. but do you think the other errors are minor? http://ix.io/3FTD
<Regenaxer> Some people got mini running on several embedded systems, with as little as 100 KiB RAM
<Hunar> Wow :) do you have a page where they talk about it?
<Regenaxer> Search for "PicoLisp Mizar"
<Regenaxer> But the Mizar is not such small I think
<Regenaxer> Raman from India showed me a setup once with memory around 100 KiB
<Regenaxer> The point in miniPicoLisp is that all code goes to ROM (Flash)
<Regenaxer> so the RAM is free for heap and stack
<Hunar> That's amazing :)    but arduino is much smaller I think .. the cheapest one (Arduino UNO) has (2KB SRAM, 32KB Program memory)
<Regenaxer> ok
<Regenaxer> is it 32 bit?
<Regenaxer> pil32 runs on 32 or 64 bit hardware
<Hunar> Oh, nevermind then .. I've just read that it's ..... wait for it .... 8-bit :/
<Regenaxer> oh :)
<Regenaxer> I had an 8-bit Lisp (software-lab.de/8kLisp.tgz) but it is for Z80 ;)
<Hunar> :)
Hunar has quit [Ping timeout: 256 seconds]
alexshendi has joined #picolisp
<alexshendi> Good evening! (adjust for timezone)
<Regenaxer> Servus alexshendi!
<alexshendi> I must announce that I'm currently consuming "Captain Kidd's Punch from 1688".
<beneroth> ahoy alexshendi, nice to read you once again :)
<alexshendi> Hi beneroth, how is life?
<beneroth> too much action for not enough time
kuao has joined #picolisp
aw- has joined #picolisp
<razzy> alexshendi: Good evening. I must confess that intel management engine gives me PTSD.
<alexshendi> razzy: Use an ARM cpu. There you'll at least enjoy different surveillance methods.
<beneroth> Chinese are pushing for serious adoption of RISC V
<beneroth> pil21 using LLVM should work to build for RISC V afaik
<beneroth> have a good evening/night, bbl :)
<razzy> alexshendi: you mean different surveillance on ARM? or do you mean that with secure computing on arm, I will enjoy other surveilance as fun?