<stacksmith>
Trying to get file extension from a path string... This: (stem (split (chop "filename.ext") ".")) works, except in case there is no extension I'd like to return a nil. Is there an elegant way to do it, or should I bind result and check length against original string? Thanks!
<stacksmith>
Sorry, I meant (stem (chop "filename.ext") ".")
_whitelogger has joined #picolisp
_whitelogger has joined #picolisp
<Regenaxer>
stacksmith: I do not use any IDE, yes, but also not slime or similar
<Regenaxer>
Just one terminal with vim (vip to be exact), and one with the repl
<Regenaxer>
Usually I don't even call (load ...), but do just ^D ^C in the REPL window
<Regenaxer>
Then ESK-K in the shell to restart the *whole* application
<Regenaxer>
It is sooo fast, it starts in a few milliseconds
<Regenaxer>
so there is really no worry about loading partial files
<Regenaxer>
However, most of the time I modify GUI files, and these dont need to be reloaded explicitly anyway
<Regenaxer>
Just a click in the browser reloads them
<Regenaxer>
They are reloaded permanently anyway, also in production
<Regenaxer>
So I restart the whole app only when one of the files er.l, lib.l or gui.l were changed
<Regenaxer>
But as I said, even restarting the whole app is just a snap
abel-normand has joined #picolisp
_whitelogger has joined #picolisp
<cess11>
stacksmith: '(cadr (mapcar pack (split (chop "thing.ext") ".") perhaps. Depends on what you need, general parser or just access to part of a string you know how it will be shaped.
<Regenaxer>
Well, if just the CADR is desired, better not build the whole list of packed symbols first ;)
<Regenaxer>
And 'last' is perhaps better
<Regenaxer>
hmm, no, not if there is no exension
<Regenaxer>
ok, so (pack (cadr (split (chop "filename.ext") ".")))
<Regenaxer>
but then "file.name.ext" won't work
<Regenaxer>
So correct is perhaps (let L (split (chop "filename.ext") ".") (and (cdr L) (pack (last L]
<cess11>
The other way around in 'and, no?
<Regenaxer>
(and (cdr L) .. checks if there is any dot
<cess11>
Right, now I see.
<Regenaxer>
it will be (("f" "i" "l" "e"))
<Regenaxer>
I always recommend to use 'cdr' to see if a list has length 1
<Regenaxer>
(=1 (length L)) is much more expensive (for long lists)
<cess11>
Yes, I usually test for 'cdr instead.
<Regenaxer>
or 'c...r' or 'nth' for a general case :)
<cess11>
The '(mapcar pack ... is useful when tuning the parsing, seeing the packed list can make it easier to decide what and how to exfiltrate, but I agree, a little clunky.
<cess11>
T, 'nth too.
<Regenaxer>
true
abel-normand has quit [Ping timeout: 240 seconds]
_whitelogger has joined #picolisp
mtsd has joined #picolisp
<beneroth>
hi all
<beneroth>
m_mans, congratulations! looking forward to here that story and how it unfolds. good luck :)
<cess11>
beneroth: Hi!
<beneroth>
Hi cess11 !
alexshendi has joined #picolisp
abel-normand has joined #picolisp
xificurC has joined #picolisp
xificurC has quit [Client Quit]
<beneroth>
Regenaxer, are you around?
<Regenaxer>
Not fully ;)
<Regenaxer>
Can I help?
<beneroth>
I want to get the object with the highest +Aux key
<beneroth>
lowest key would probably work with (leaf) ?
<Regenaxer>
'maxKey'?
<beneroth>
highest key: (fetch Tree (maxKey Tree)) or how?
<Regenaxer>
'leaf' is not useful here I think
<Regenaxer>
yes
<beneroth>
so (fetch Tree (maxKey Tree))
<Regenaxer>
I wonder why leaf is there ;)
<beneroth>
and the equivalent to fetch the lowest Aux key would be (leaf Tree) ?
<beneroth>
well either leaf should have an equal for maxKey or... dunno xD
<Regenaxer>
Hmm, 'leaf' seems lower level
<Regenaxer>
rather minKey
<Regenaxer>
Let me check
<beneroth>
so (leaf Tree) should behave same as (fetch Tree (minKey Tree)) ?
<beneroth>
(so I understand the documentation)
<Regenaxer>
'leaf' is independent from the index key
<Regenaxer>
it operates directly on the nodes
<beneroth>
yeah I guessed so
<Regenaxer>
I don't remember
<beneroth>
I guess it just iterates to the end node on the lower-branch of the tree?
<beneroth>
k
<beneroth>
doesn't matter
<beneroth>
important question was if (fetch Tree (maxKey Tree)) is the way to go :)
<beneroth>
thanks!
<Regenaxer>
yes, just mechanically
<Regenaxer>
(fetch Tree (maxKey Tree)) is the "normal" way
<Regenaxer>
also minKey
<beneroth>
okay
<beneroth>
yeah
<Regenaxer>
I wonder why leaf is there ;)
<beneroth>
I never used fetch directly until now
<Regenaxer>
ok
<Regenaxer>
I'm searching
<Regenaxer>
but I don't have all here on the tablet
<Regenaxer>
or the keller server
<beneroth>
"(leaf" I find only in documentation xD
<beneroth>
so it appears not to be used in code within the distro
<beneroth>
np
<beneroth>
not important
<Regenaxer>
yeah, also not is all projects I can reach here
<Regenaxer>
There must have been some reason
<beneroth>
surely
<Regenaxer>
minKey is older
<Regenaxer>
leaf appeared with picoLisp-2.3.0
<Regenaxer>
30sep07
<beneroth>
okay
<beneroth>
I'm on board since 3.1.8 or so
<Regenaxer>
I search around another day
<beneroth>
yeah, not important
<Regenaxer>
in the snapshots
<Regenaxer>
yeah
<Regenaxer>
just interesting
<beneroth>
I guess one could easily create the leaf-equal for the highest leaf?
<beneroth>
T
<beneroth>
just start with the car instead of the cdr ?
<Regenaxer>
probably
<Regenaxer>
At least it is very efficient
<Regenaxer>
no search involved, just node pointers
<Regenaxer>
no key comparisons I mean
<beneroth>
yeah
<Regenaxer>
But that was not the reason
<Regenaxer>
I faintly remember it has some lower-level reason
<Regenaxer>
I take a note to check later
<beneroth>
maybe a reason which was specific to pil32 or pil64 ?
<beneroth>
kk
<beneroth>
let me now when you found out :)
<Regenaxer>
sure
<Regenaxer>
pil32 or pil64 are the same here I think
<beneroth>
hm
<beneroth>
T
<beneroth>
the tree structures are the same
<Regenaxer>
T
<beneroth>
only the block structure is different, right?
<Regenaxer>
yes, and only slightly
<beneroth>
yeah, so no diff on lisp level. only on file io
<Regenaxer>
the format external symbols are stored
<Regenaxer>
right
<Regenaxer>
But it is very efficient
<Regenaxer>
it does not traverse the tree twice as with minKey + fetch
<Regenaxer>
Perhaps this was the only reason
<Regenaxer>
(and I forgot about it)
<beneroth>
yeah
<Regenaxer>
Good that you found it!
<beneroth>
the traversal is also a bit quicker than with (minKey) in this case, I assume
<Regenaxer>
yes, though the number of disk reads is the same
<beneroth>
T
<Regenaxer>
so it should not matter much
<beneroth>
T
<beneroth>
so.. why (leaf) then? :D
<beneroth>
it is a riddle :)
<Regenaxer>
at fetch time it is cached already
<Regenaxer>
indeed
<beneroth>
(collect) always returns as by index lowest .. highest (when not specifying a range)
<beneroth>
ah now
<beneroth>
T ref gives other sort order
<beneroth>
nice
<beneroth>
thx
<beneroth>
all those little detail tricks :)
<Regenaxer>
T ref ?
<beneroth>
ref being the value
<Regenaxer>
using T as infinite?
<beneroth>
(collect 'index 'Cls ref) vs (collect 'index 'Cls T ref)
<beneroth>
aye
<Regenaxer>
yeah
<Regenaxer>
or (T . ref) in some cases
<Regenaxer>
Pilog
<beneroth>
oh
<beneroth>
I guess (fetch) returns NIL when the given value is not in that index, right?
<Regenaxer>
yes, needs an exact match
<beneroth>
so this could also be used to check for an entry in an index without get the list of all entries?
<Regenaxer>
how?
<Regenaxer>
with NIL?
<beneroth>
e.g. to check for absence of a +Ref +Bool relation -> go through a +Key index and check each entry by fetch from the +Bool index ?
<beneroth>
vs. getting both index lists and using (diff)
<Regenaxer>
Non-existing +Bool's cannot be accessed directly, yes
<beneroth>
well this way one could find those objects without loading the objects
<beneroth>
right?
<Regenaxer>
yes, this works for any relation
<beneroth>
ofc
<Regenaxer>
fetch does not load
<Regenaxer>
just returns the object
<beneroth>
so I grokked it right. Thanks for checking :)
<Regenaxer>
not the contents (value etc)
<Regenaxer>
good :)
<Regenaxer>
just returns the object -> just returns the symbol
<beneroth>
yep
<beneroth>
the record identifier
<Regenaxer>
just a short number in fact
<Regenaxer>
T
<beneroth>
just having a record identifier makes the DB so much more powerful vs. relational xD
<Regenaxer>
I think so too
<Regenaxer>
direct pointers kind of
<beneroth>
yes
<beneroth>
and no extra overhead or space used by your approach (block id). only a high limit on number of records.
<Regenaxer>
right
<beneroth>
it is better as the usual auto increment primary keys so often used
<Regenaxer>
yes, a key needs a lookup to use it
<beneroth>
yes, and their limit is lower as they're usually signed 32 byte integers
<Regenaxer>
The limit is 2**42 (4 Tera) Blocks per file
<Regenaxer>
in total 2**16 Files -> 288 Peta objects
<Regenaxer>
absolute max
<beneroth>
yeah, high enough for all usage below CERN
<Regenaxer>
but the block size may be large ;)
<Regenaxer>
I think so too
<Regenaxer>
For bigger things communicating DBs could be used
<Regenaxer>
(not distributed)
<Regenaxer>
The 2**16 Files are also for a distributed DB
<Regenaxer>
usually
<beneroth>
yep
<Regenaxer>
I did not hit that limit yet ;)
<mtsd>
Evening folks
<Regenaxer>
Good evening mtsd!
<beneroth>
Good evening mtsd
<mtsd>
Good evening Regenaxer and beneroth!
<mtsd>
Spoke to the new job yesterday. They use a traditional setup,Python and Postgres, today.
<Regenaxer>
uh ;)
<mtsd>
They told me it was ok to consider a rewrite in another language. ANd I thought -"if they only knew what I would choose"
<beneroth>
what data work do they do?
<Regenaxer>
You should evangelize them
<Regenaxer>
So it sounds not hoplless :)
<Regenaxer>
hopeless
<beneroth>
well there are some non-technical things to consider for such changes... for a company.. but yeah, sounds like an opportunity :)
<mtsd>
They communicate with loan institutes and banks, trying to negotiate better interest rates for people
<beneroth>
ok. so they need ACID :D
<beneroth>
pilDB delivers (if you use all arguments of pool)
<mtsd>
Lots of XML apis etc etc
<Regenaxer>
ok
<mtsd>
Could perhaps be an opportinuty to infiltrate yet another place and change it from the inside ;)
<beneroth>
ugly. but easy to handle with picolisps stream text capabilities I hope. I just sold a project where I want to talk to SOAP web interface (XML) with pil
<Regenaxer>
cool
<Regenaxer>
yes, XML is ugly but easy
<Regenaxer>
JSon would be better
<Regenaxer>
best is plio of course ;)
<mtsd>
Of course, I have to get to know the existing platform well first
<beneroth>
other two solutions were azure functions (so called "serverless" code running on cloud.. but they have no SOAP implementation)
<beneroth>
and C# MVC.. which I argued just takes too long :P
<beneroth>
mtsd, yeah
<mtsd>
Json would be better, but banks here are very, very conservative whe it comes to technology
<beneroth>
mtsd, how many other internal programmers work on that code?
<beneroth>
be aware of strange text encoding, look out for that. if it is not all utf-8 than pil could be a bit more work then expected
<mtsd>
Just one, and he is actually employed by another company. He was actually the one who said "rewriting in another language would be ok to do", haha
<Regenaxer>
well, just a pipe
<Regenaxer>
iconv or recode
<beneroth>
mtsd, hm, okay. so re-training staff is not the problem, as you are the only staff which counts (probably)
<mtsd>
T
<beneroth>
external one can always get replaced with Regenaxer or me :P
<beneroth>
Regenaxer, nice idea. thanks
<mtsd>
Yes, I believe we can form a scheme here ;)
<beneroth>
just now that this talk here is public ;)
<beneroth>
s/now/know
<mtsd>
hahaha, yes. Forgot the channel log
<mtsd>
Anyway, I am not rewriting anything before I get to know the system. Would not want to botch it and make Pil look bad
<beneroth>
T
<beneroth>
no rewrite if it does the job and not much new-dev is going on.
<beneroth>
the main business power of pil is it's flexibility for changes, I think.
<mtsd>
I like the minimalism, low resource usage and stability very much as well
<beneroth>
T
<mtsd>
The apps I have running in the wild just do their job, nice and quiet. No problems
<mtsd>
The way programs ought to
<beneroth>
low resource usage is a good point in comparison to this runtime-heavy stacks
<beneroth>
T
<beneroth>
Regenaxer, best way to calculate microseconds (as given by (usec)) to milliseconds? just (/ (usec) 1000) ?
<beneroth>
(without rounding, I want to round down always)
<Regenaxer>
Sorry, was interrupted
<Regenaxer>
yes, (usec)
<beneroth>
you get exact microseconds from kernel?
<Regenaxer>
depends, never the full resolution
<Regenaxer>
usually just milliseconds I believe
<beneroth>
so the rest is noise?
<Regenaxer>
with a 1 MHz clock
<Regenaxer>
probably
<Regenaxer>
And on Unix times are never exact unless on a realtime system
<Regenaxer>
Depends on when your process gets a time slice
<beneroth>
understood.
<stacksmith>
Thanks for your responses re file extension extraction. cdr is a great way to check if split returns more than one element - thanks!
<Regenaxer>
hi stacksmith
<stacksmith>
Regenaxer: sorry, I asked the same question you already answered before about workflow...
<beneroth>
hey stacksmith :)
<stacksmith>
Should have gotten some sleep before asking...
<stacksmith>
Hey!
<Regenaxer>
no problem at all
<stacksmith>
Today's question: Is there a way to redirect the repl io temporarily?
<Regenaxer>
only outside pil I think
<Regenaxer>
$ pil + |tee logfile
<stacksmith>
OK. So there isn't a separate file handle or IO channel or something inside a running pil...
<Regenaxer>
Not sure
<beneroth>
what do mean / what do you want to achieve, stacksmith ?
<Regenaxer>
you can redirect with 'out' but then have no console output
<beneroth>
Regenaxer, the psh falls into this. but.. I guess that isn't what he means, and it's very complicated ^^
<beneroth>
ah right
<beneroth>
and (error)
<Regenaxer>
yes, psh is another matter
<Regenaxer>
not complicated though
<beneroth>
T
<beneroth>
not complicated
<beneroth>
just prone to errors
<Regenaxer>
just psh 8080
<Regenaxer>
yes, and only for running web apps
<beneroth>
I got it running with pil code. didn't manage it when the pil code doing psh was called by bash script for some reason.
<beneroth>
but yeah, I needed a re-implemented psh
<beneroth>
doesn't matter. never mind.
<Regenaxer>
basically it is the 'ctty' function
<Regenaxer>
So as beneroth asked, stacksmith, what do you need it for?
<Regenaxer>
"So there isn't a separate file handle or IO channel": It is a normal channel
<Regenaxer>
'out' and 'in'
<stacksmith>
Well, I am still wrestling with the environment. I should probably give up and try to write some code and see how it feels before spending any of your time on it. Just thinking about wrapping some tools around a running pil, without losing console IO.
<Regenaxer>
yeah, I believe it is not needed ;)
<stacksmith>
My OCD taking over.
<stacksmith>
Premature toolmaking.
<Regenaxer>
:)
<stacksmith>
But since you mentioned channels - there is no way to 'rebind' a channel?
<Regenaxer>
yes
<Regenaxer>
'out' or 'in'
<Regenaxer>
also 'pipe'
<Regenaxer>
'load' also does this
<Regenaxer>
'load' is 'in' plus read/eval
<Regenaxer>
Just (load) *is* the REPL
<stacksmith>
May I ask why your answer was no to my original question?
<Regenaxer>
ie. reading from NIL which is stdin
<Regenaxer>
which was the original one?
<stacksmith>
Ah, is it possible to redirect the REPL
<beneroth>
we didn't understand your question
<Regenaxer>
yeah, so it *is* possible?
<Regenaxer>
I thought you mean redirecting the output
<Regenaxer>
(load "file.l") redirects the *input*
<Regenaxer>
The above |tee duplicates the output, but outside pil
<stacksmith>
OK, perhaps poorly phrased question. I envisioned something - maybe a vim script, maybe some *ugh* IDE-like thing that lets you edit, shove forms into the repl, provide completion and help about functions. Minimal and unobtrusive, of course.
<beneroth>
ah
<stacksmith>
While still letting you use the repl.
<beneroth>
just use (edit)
<beneroth>
:P
<beneroth>
I mean
<beneroth>
(vi)
<stacksmith>
I know, but once you edit you can't use the repl until you quit.
<beneroth>
or (edit)
<Regenaxer>
yep, so I use 2 terminals
<stacksmith>
I think I am missing something...
<Regenaxer>
completion is provided by the line editor
<beneroth>
when you start picolisp in debug mode ($ pil +) then you can do arrow-up to get the last inputs btw..
<stacksmith>
Can i have two terminals on the same instance of pil?
<Regenaxer>
(edit 'sym) edits value and properties of 'sym'
<Regenaxer>
Not two terminals. What for?
<Regenaxer>
Well, psh connects to a running process, possibly in another terminal
<stacksmith>
Let's say I edit something. I am looking at it, and want to run a test at the repl, or see something else.
<Regenaxer>
but gives still only 1 repl
<Regenaxer>
You edit in one term, then save
<beneroth>
stacksmith, have the file open with an editor, have another window with the terminal, in the terminal type (load "thefile") ?
<Regenaxer>
then load in the other
<Regenaxer>
(load "thefile") is in history then
<Regenaxer>
can be repeated easily
<Regenaxer>
up arrow
<Regenaxer>
or ESC-k
<Regenaxer>
Typical pil source file have no effect if loaded repeatedly
<Regenaxer>
only changed definitions give a "redefined" message
<Regenaxer>
So it does not matter if you just load *all*
<Regenaxer>
even a tree of source files
<Regenaxer>
takes really just milliseconds
<stacksmith>
right. I guess I could get used to it.
<Regenaxer>
In praxis, I don't even call (load ..)
<Regenaxer>
as I wrote
<Regenaxer>
stop the app server repl with ^D ^C
<Regenaxer>
then repeat the start line in the shell
<stacksmith>
OK. I will write some code before wasting anymore of your time on that.
<Regenaxer>
It loads *all*, opens the db, starts the gui
mtsd has quit [Quit: Leaving]
<beneroth>
stacksmith, curios: what is your workflow with other language which you try to take over to pil ?
<Regenaxer>
Don't worry! It is a pleasure
<stacksmith>
Well, one of the reasons I keep coming back to PicoLisp is that other environments suck and are huge.
<beneroth>
true, haha
<stacksmith>
However I got used to emacs with 3x2 panes on my widescreen monitor, with a repl in the middle and 2-3 buffers to look at in 5 remaining panes. Sometimes more.
<stacksmith>
I hop around the panes, compiling functions with C-c C-c, mostly.
<stacksmith>
Then mess around in the repl.
<beneroth>
have you tried out the picolisp-mode coming with picolisp distro?
<beneroth>
I use it in combination with paredit, though I also use a repl outside of emacs
<beneroth>
it gives possibility to have a repl inside emacs
<stacksmith>
tslime for vim almost works like that, but it is absurdly slow (sometimes a couple of seconds to send the keystrokes of a two-line form). tslime is not slime, pretty much just C-c C-c and a couple of other commands.
<stacksmith>
I am trying to lean vim, got a bit sick of emacs with yet another lisp in it.
<stacksmith>
learn
<beneroth>
ok
<beneroth>
then maybe try out vip :)
<beneroth>
Regenaxer works with vim / vip
<Regenaxer>
T
<Regenaxer>
but any editor is ok
<beneroth>
T
<stacksmith>
Yes, I was thinking of using vip and rigging up a C-c C-c form feeder into pil...
<beneroth>
in the beginning I worked with "nano" and a custom syntax highlighting for it
<Regenaxer>
It is just this "feeder" which I cannot see useful
<beneroth>
why not just mark and copy to terminal window + middle mouse key?
<stacksmith>
Lots of keystrokes...
<stacksmith>
Or mouse.
<stacksmith>
I don't know why, but I feel somehow lost without being able to send a form to lisp.
<beneroth>
you got enough time for that.
<beneroth>
the productivity gain allows some more time with mouse or keystrokes :P
<beneroth>
ok
<beneroth>
only in the beginning you want to send forms (sexprs?) to the repl often
<stacksmith>
I am not completely a zealot, but would love to not touch the mouse if I can help it.
<Regenaxer>
Sometimes I test an expression in the repl
<Regenaxer>
just ESK-k
<Regenaxer>
edit the line perhaps
<beneroth>
I think that is what he is looking for
<Regenaxer>
There are 2 versions of the line editor
<Regenaxer>
default is vi style
<Regenaxer>
but there is also em
<Regenaxer>
(haven't tried)
<Regenaxer>
And just (edit 'foo) lets you modify a function on the fly
<Regenaxer>
it is automatically loaded immediately
<stacksmith>
Right. I got into the habit - probably a bad one - of messing with a source file, like having 3 or 4 versions of a function and doing a bunch of debugging, then cleaning up leaving the final version... So I could not recompile the file full of stubs and notes... Having an easy way to send forms in slime makes it possible to use the source as a scratch buffer.
<Regenaxer>
Ah, I do that too
<Regenaxer>
test files
<beneroth>
stacksmith, you can just leave all your notes and other versions in the picolisp source file.. just put NIL on a line before it
<Regenaxer>
I often have several versions of the same function in it
<beneroth>
NIL stops picolisp from reading the source file.. it handles it as EOF
<stacksmith>
great!
<Regenaxer>
just "comment" it with '
<beneroth>
or that :)
<Regenaxer>
'(de foo ...
<Regenaxer>
'(de foo ...
<Regenaxer>
(de foo ...
<beneroth>
haha, nice trick!
<Regenaxer>
a fast way to disable
<beneroth>
ugly but ok during development
<beneroth>
haha ^^
<Regenaxer>
exactly
<Regenaxer>
Yes, NIL is also a good way
<beneroth>
stacksmith, it is not really a comment, but than the whole expression gets read as quoted list instead of an function call (to de) which gets executed
<Regenaxer>
I put garbage below it
<beneroth>
yeah me too
<beneroth>
other variants, tests
<Regenaxer>
T
<beneroth>
bigger comments for later improvements
<stacksmith>
I wind up with pages of code and notes, which generally turn into 4 lines of code when I am done realizing how to do it right...
<Regenaxer>
understand
<beneroth>
makes sense
<Regenaxer>
So perhaps start to experiment with NIL and ' first
<beneroth>
this effect is even stronger with picolisp, because often you need here only very few lines
<Regenaxer>
or #{ ... }# perhaps
<beneroth>
sometimes weird... optimized 5 lines of code for a week or so :P
<Regenaxer>
haha, yes, often
<stacksmith>
will do. Is there something like 'time' in CL - benchmark and show consing and gc?
<beneroth>
(bench)
<Regenaxer>
yes, 'bench'
<Regenaxer>
consing not directly
<Regenaxer>
(heap) gives the heap size in MiB
<beneroth>
stacksmith, see also (doc) and (help)
<Regenaxer>
There is no statistics of gc. It is quite invisible
<Regenaxer>
It isn't even recorded internally
<stacksmith>
Is gc a simple mark/sweep?
<Regenaxer>
yel
<Regenaxer>
yes
<stacksmith>
Funny how simple ways of doing things are generally pretty close to best.
<Regenaxer>
exact
<stacksmith>
trying to squeeze the last 10% always gets you in trouble.
<beneroth>
you can pre-allocate memory with (gc 'megabytes) if you do large imports or such, to prevent too much gc work.
<stacksmith>
OK, thanks for great advice. I should probably try to write some code before asking any more questions. Except one: is there a transcript of this chat somewhere?