ChanServ changed the topic of #picolisp to: PicoLisp language | Channel Log: https://irclog.whitequark.org/picolisp/ | Check also http://www.picolisp.com for more information
Blukunfando has quit [Ping timeout: 260 seconds]
razzy has joined #picolisp
razzy has quit [Quit: Connection closed]
mtsd has joined #picolisp
rob_w has joined #picolisp
<rob_w> good morning .. hello Regenaxer ... i still working me into my stuff and would love to get some attention from you by tomorrow , would that be possible ?
<Regenaxer> Serus rob_w!
<Regenaxer> yes, fine
<rob_w> great thx
<Regenaxer> Let's phone
<Regenaxer> tomorrow, today I'm a bit busy
<rob_w> tomorrow u mean ?
<rob_w> yeah np
<Regenaxer> T
<rob_w> soi need to figure out a way to screen share ... what would you suggest ?
<Regenaxer> We can use Jitsi, like for PilCon
<rob_w> yep works for me ..
<rob_w> nice
<Regenaxer> good
<rob_w> well Regenaxer .. a simple question .. how do i append log messages to your actual log file we use
<rob_w> ah nvm
<Regenaxer> I always redirect stderr from the start scripts
<Regenaxer> you can also use 'err'
<aw-> hi rob_w Regenaxer
<aw-> Regenaxer: how do i detect when a client disconnects from a socket?
<Regenaxer> Hi aw-
<aw-> i'm doing (in Sock ....) need to know if the client disconnected and won't send data anymore
<Regenaxer> You get NIL
<Regenaxer> yes
<Regenaxer> Normally in a 'task'
<Regenaxer> so the task wakes up
<aw-> without task'
<aw-> (if (in Sock ...) "still connected" "disconnected") ?
<Regenaxer> This will block, but it is the same
<Regenaxer> (in Sock (if (rd) (do something) (close Sock)))
<Regenaxer> (rd) or (read) or (line), (char) etc
<aw-> hmmm
<aw-> is it bad practice to do (in Sock ...) (in Sock ...) ?
<Regenaxer> no, this is fine
<Regenaxer> or, it is normal
<Regenaxer> How else?
<aw-> ok so in that case how do I know when the client is dead?
<Regenaxer> As I said, only from the return value
<aw-> ex: (if (rd) (do something) (close Sock)) (if (rd) (do something else) (close Sock)) ..
<aw-> this is not good
<Regenaxer> Why not?
<aw-> because (do something else) will never run
<Regenaxer> Different places, right?
<Regenaxer> If the socket is closed, you should not read from it, yes
<aw-> ok wait
<Regenaxer> it will return NIL again, so no big problem
<aw-> so if a client does (out Sock (prinl 1)) (out Sock (prinl 2))
<Regenaxer> yes
<aw-> ok wait, let me explain my use-case
<Regenaxer> After (out ...) the socket is not closed
<Regenaxer> you can call out many times
<aw-> how do I listen for multiple (out) calls?
<aw-> (loop (in Sock ...)) ?
<Regenaxer> yes
<aw-> but then it never exits
<Regenaxer> (in Sock (while (rd) ..)) (close Sock)
<aw-> no that's different
<aw-> (while (rd) expects multiple data on the same (out)
<aw-> it's different from multiple (out)
<Regenaxer> no
<Regenaxer> Don't care about *how* the sender sends the data
<Regenaxer> (out S (pr 1)) (out S (pr 2)) is the same as (out S (pr 1 2))
<aw-> oh ok
<aw-> but (while (rd) blocks), right?
<Regenaxer> yes
<aw-> it blocks until the socket is closed?
<Regenaxer> until *something* arrives
<Regenaxer> that *may* be EOF
<Regenaxer> 7
Regenaxer has left #picolisp [#picolisp]
Regenaxer has joined #picolisp
<Regenaxer> Wifi unstable
<Regenaxer> aw-, just experiment with two repls
<aw-> i've been doing that all day
<Regenaxer> :)
<Regenaxer> So where is the problem?
<aw-> if I knew, I wouldn't be asking ;)
<Regenaxer> true ;)
<aw-> i'm playing with the boss.l and it's been difficult
<beneroth> aw-, I like to second your distaste for IPv6. I started now with LXD (Linux containers + higher level API/management interface)... and as I didn't like the default iptables of it (vlan is fully trusted) I had to make all iptables/filtering myself.. and failed for ipv6 (I don't know ipv6 really). so solution was to disable it (not much value in a vlan anyway)...
<Regenaxer> boss is easy if you are in a child started with psh
<Regenaxer> (boss 'msg ''OK)
<Regenaxer> just start the app/ demo
<Regenaxer> then $ psh 8080
<aw-> how do I get out of (while (rd)) loop ?
<aw-> (pr (eof)) ?
<Regenaxer> no, (close Sock)
<aw-> my client disconnects, but the server is still waiting for data on the socket which is clearly closed
<Regenaxer> Can't be
<Regenaxer> it will get NIL immediately
<Regenaxer> (listen (port 4444)) + (in @ (rd))
<Regenaxer> (connect "localhost" 4444) + (close @)
<aw-> ok yeah i just did a test.. it is disconnecting
<beneroth> what about ungraceful disconnects?
<aw-> beneroth: yes avoid IPv6 unless necessary ;)
<beneroth> aw-, aye, so I do
<Regenaxer> But in the long range we can't avoid IPv6
<beneroth> it pains me a bit, but I don't deploy things I don't understand and cannot restrict for security...
<Regenaxer> aw-, in the above example
<Regenaxer> (in @ (rd)) blocks
<Regenaxer> then returns NIL
<beneroth> the main problem is the higher complexity, and that ISP's have low incentives to switch to IPv6
<beneroth> Regenaxer, what about ungraceful disconnects?
<beneroth> Regenaxer, whould wrapping (abort) around on the server side make sense?
<Regenaxer> What is ungraceful disconnect?
<Regenaxer> Process terminates? That's ok
<Regenaxer> Why abort?
<Regenaxer> What exactly is the problem?
<Regenaxer> An abort may be needed if the connection *hangs*
<Regenaxer> eg some router hangs
<Regenaxer> But I think this is not aw-'s problem here
<aw-> no i'm way beyond that
<aw-> i'm trying to do something and it's gotten too complex
<Regenaxer> tcp takes care of all :)
<Regenaxer> Normally you'll need 'tasks', due to the asynchronous nature of such connections
<aw-> right
<aw-> is it slower than (fork) ?
<Regenaxer> but the data transfer itself is trivial
<Regenaxer> (fork) is independent of that
<Regenaxer> if it is some longer handling independent
<Regenaxer> app/main.l does that for example
<Regenaxer> as a demo
<Regenaxer> if you fork, you normally communicate with otherr processes
<aw-> i looked at main.l
<Regenaxer> *What* do you want to do?
<aw-> everything happens in the child process
<Regenaxer> goid
<Regenaxer> good
<aw-> how do i share data between two child processes then?
<Regenaxer> 'go' in main.l forks
<Regenaxer> Via 'tell', and/or a database
<aw-> without writing to a db on disk
<Regenaxer> tell
<aw-> tell is not good
<Regenaxer> what is the problem?
<aw-> im trying to do similar to main.l, but send data to parent process
<Regenaxer> boss :)
<aw-> and then when other clients connect, they get the data from the parent
<aw-> i tried boss, it's not good
<aw-> there's no examples or explanation i have no idea how it works
<Regenaxer> But doing things in the parent is not recommended
<Regenaxer> bette keep it free from load
<aw-> not recommended* ... well that solves my issue then
<Regenaxer> and, remember that any future child inherits all that again
<aw-> i'll just use an external database
<Regenaxer> best is to fork children and let them do the work
<Regenaxer> The parent just supervises
<Regenaxer> Also safe from crashes
<Regenaxer> The parent should not crash or block
<Regenaxer> the children can
<Regenaxer> WHAT do you want to do?
<Regenaxer> It all depeds in the needs
<Regenaxer> depends
<aw-> i want the child processes to set and read variables in the parent
<Regenaxer> sigh, ok, then 'boss'
<Regenaxer> (boss 'setq '*Var ...)
<aw-> ex: child1 sets *Myvar 1, child2 sets *Myvar 2, child3 reads *Myvar
<Regenaxer> easy
<Regenaxer> How about 'later' then?
<aw-> how can i do that with (boss) ?
<Regenaxer> (boss 'setq '*Var ...)
<aw-> also using TCP sockets
<Regenaxer> app/main.l, then connect, and (pr 'setq '*Var ...
<Regenaxer> works out of the box
<Regenaxer> or with boss
<Regenaxer> $ psh 8080
<Regenaxer> : (boss 'setq '*Var ...
<Regenaxer> : (boss 'msg '*Var)
<Regenaxer> Boss prints the value to stderr
<Regenaxer> Have you looked at 'later'?
<Regenaxer> Creates a child, which sets a var in the current process
<Regenaxer> Might be just what you need
<aw-> ok i will look into it
<Regenaxer> (later '*MyVar (do something returning the value))
<Regenaxer> (do something ...) runs in the child
<Regenaxer> : (later '*A (wait 6000) (* 3 4))
<Regenaxer> after 6 sec *A has 12
<Regenaxer> : (later '*A (wait 6000) (* 3 4))
<Regenaxer> -> *A
<Regenaxer> : *A
<Regenaxer> -> NIL
<Regenaxer> : *A
<Regenaxer> -> 12
<aw-> ok wait, im trying now
<aw-> Regenaxer: in your (boss) example
<aw-> how do i send back a response from the parent to the child?
<aw-> i did something similar to main.l... but instead of (unless (fork)...) I do: (if (fork) (parent-response) (child-response))
<aw-> not sure if that's a good idea
<Regenaxer> (tell '*ChildPid ...)
<aw-> (tell) uses PLIO ?
<Regenaxer> yes
<Regenaxer> But that does not matter
<Regenaxer> it is about executing expressions
<Regenaxer> As long as you don't tell what your general plan is, I cannot recommend a way. As you see from the above, there are many ways ...
<aw-> oh (tell) doesn't send through the named pipe *Boss ?
<Regenaxer> no
<Regenaxer> boss is an add-on, tell is in the kernel
<Regenaxer> 'later' uses 'pipe', which in turn uses the child's stdout
<Regenaxer> So you could also use 'pipe' directly
<aw-> i see
<aw-> ok let me try some things.. maybe return later tonight or tomorrow with more questions
<aw-> thanks for the help
<Regenaxer> ok
<Regenaxer> But as long as I don't know what you need, 'task' is the most general and easiest way
<Regenaxer> 'later' also creates a task btw
<aw-> ok thanks
<aw-> Regenaxer: looking at this: https://picolisp.com/wiki/?task
<aw-> erik mentions "You may still have some main loop in your program"
<aw-> where would this 'main loop' go?
<Regenaxer> it is either 'key' or 'wait'
<aw-> where do i add it in thecode?
<Regenaxer> pil main.l -main -go -wait
<Regenaxer> or (wait) somewhere
<Regenaxer> Naturally always in the end
<aw-> right
<aw-> ok thanks
<Regenaxer> to get a REPL, you do
<Regenaxer> pil main.l -main -go +
<Regenaxer> So it falls throug to the repl
<Regenaxer> and thus 'key'
<aw-> (task) doesn't fork a process?
<beneroth> aw-, no
<beneroth> (task) stays in the same process
<Regenaxer> T, it is just an asynchronous event handler
<beneroth> basically during (wait) the installed tasks in *Run are checked and/or triggered by system calls (e.g. a socket connection has received data) and the associated prog executed
<beneroth> (wait) is called implicitly by some other picolisp functions where it makes sense, e.g. (dbSync) etc., when waiting for I/O
<beneroth> conceptually a process with (task)s installed is a bit similar to the parent process for forking children, as in you do all declarations and then usually spend most time in (wait) and execute the installed (tasks) whenever they trigger
<beneroth> Regenaxer, correct, more or less?
<Regenaxer> yes, very good
<Regenaxer> The first statement could add that tasks also oay be timers
<Regenaxer> may
<Regenaxer> thus either I/O events or timeouts
<beneroth> that is meant with 'main loop', after setup the process isn't doing much more then looping/waiting for tasks to trigger (or on forking server, for incoming connections, starting their handling, then continue waiting for next connections)
<beneroth> of course the process can do additional things
<beneroth> but.. it should spend time in (wait), because there the asynchronous stuff is triggered/executed
<beneroth> the whole thing is maybe a bit hard to understand the first time, because the abstractions are less deep/nested as in other stacks
<beneroth> other stacks run a full machinery of threads/background processes/similar, while the picolisp approach is more direct. but by default leaves away extra machinery which isn't needed for most cases
<beneroth> Regenaxer, maybe one could even say that picolisp asynchronous executions ('task, stuff executed by 'tell) is kinda like threads without scheduling, no?
<beneroth> what triggers first comes first, if the prog contains a (wait) (or I/O) this of course gives other asynchronous stuff a point to trigger...
<Regenaxer> Not sure. Threads have more parallelism
<beneroth> T
<Regenaxer> Threads are more like child processes, just in the same memory
<beneroth> picolisp is concurrency, not parallelism
<Regenaxer> cooperative, like coroutines
<Regenaxer> coroutines are like cooperative threads
<beneroth> Regenaxer, threads are funny.. the main point is having the same memory (vs. processes), but most newer stacks go pretty far to reduce the "same memory" feature so it's getting easier to handle (e.g. non-destructive memory)
<Regenaxer> hehe, yeah
<Regenaxer> threads are the new goto
<beneroth> same as goto their perfect for certain special cases when used correctly, but should not used lightly
<Regenaxer> T
<beneroth> I like to add the same applies to distributed databases, or actually network-distributed anything
orivej_ has quit [Ping timeout: 260 seconds]
orivej has joined #picolisp
<Regenaxer> So I would say 'task' (which is just a front-end to '*Run' is THE workhorse of PicoLisp
<Regenaxer> It is the "outer interpreter"
<Regenaxer> (if 'eval' is the "inner interpreter")
<Regenaxer> In that view, the REPL is also just an entry in *Run or 'task'
<Regenaxer> I think most people are not aware of this
rob_w has quit [Remote host closed the connection]
orivej has quit [Ping timeout: 260 seconds]
orivej has joined #picolisp
<beneroth> T for your applications, and in way for most server applications
<beneroth> for basic scripting (instead of bash scripting) 'task' is usually not needed (useful for some cases maybe) :-)
<Regenaxer> right
<Regenaxer> But even such scripts are usually tested in a repl
<Regenaxer> The terms "inner" and "outer" interpreter are also from Forth btw
<Regenaxer> the outer one in Forth is a repl though
<beneroth> I see, interesting!
orivej has quit [Ping timeout: 264 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 260 seconds]
orivej has joined #picolisp
patrixl has quit [Quit: Leaving.]
patrixl has joined #picolisp
orivej has quit [Ping timeout: 256 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 264 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 264 seconds]
orivej_ has joined #picolisp
mtsd has quit [Quit: Leaving]
Blue_flame has joined #picolisp
Blue_flame is now known as Guest68669
orivej_ has quit [Ping timeout: 246 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 258 seconds]
orivej has joined #picolisp
orivej has quit [Quit: No Ping reply in 180 seconds.]
orivej has joined #picolisp
Guest68669 is now known as Blue_flame
orivej has quit [Quit: No Ping reply in 180 seconds.]
orivej has joined #picolisp
orivej has quit [Quit: No Ping reply in 180 seconds.]
orivej has joined #picolisp
orivej has quit [Ping timeout: 258 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 256 seconds]
orivej has joined #picolisp
orivej has quit [Ping timeout: 246 seconds]
<beneroth> [OT] GnuTLS vulnerability discovered, allows MitM on TLS-connections https://gitlab.com/gnutls/gnutls/-/issues/1011
emacsomancer has quit [Ping timeout: 256 seconds]
emacsomancer has joined #picolisp
patrixl has left #picolisp [#picolisp]
patrixl has joined #picolisp
Blue_flame has quit [Quit: authenticating]
Blue_flame has joined #picolisp
orivej has joined #picolisp