orivej has quit [Ping timeout: 255 seconds]
alexshendi has quit [Remote host closed the connection]
orivej has joined #picolisp
aw- has joined #picolisp
dtornabene has joined #picolisp
<
Regenaxer>
Hi aw-!
<
aw->
i'm trying to simplify a function, maybe someone can help
<
aw->
maybe i'll pastebin
<
aw->
i know how to do it, i just want to see how others would improve this
<
Regenaxer>
I think this is fine, isn't it?
<
aw->
well there's a lot of repeating elements
<
Regenaxer>
or use 'assoc' to make it shortea
<
aw->
i have something that uses (eval) to generate the (do-something- ...
<
aw->
or.. to call it
<
Regenaxer>
How about:
<
Regenaxer>
(de my-fun (Value)
<
Regenaxer>
(assoc (car Value)
<
Regenaxer>
("one" . do-something-one)
<
Regenaxer>
("two" . do-something-two)
<
Regenaxer>
("three" . do-something-three) ) )
<
Regenaxer>
(@ (cdr Value)) ) )
<
Regenaxer>
Not much shorter though ;)
<
Regenaxer>
needs a CDR
<
Regenaxer>
((cdr @) (cdr Value))
<
Regenaxer>
So not nice
<
Regenaxer>
Another way is to intern one, two and three, and define them
<
Regenaxer>
Then (and (getd (intern (car Value))) (@ (cdr Value)))
<
Regenaxer>
But this will intern other wrong symbols (if they appear at all)
<
aw->
oh, how do i do that?
<
aw->
oh (intern) ...
<
Regenaxer>
(intern "three")
<
Regenaxer>
It all depends on the real situation
<
Regenaxer>
Where these values come from
<
Regenaxer>
There is usually a more direct, clean way I think
<
Regenaxer>
Where do "one" etc. come from?
<
Regenaxer>
OOP might be better in some cases
<
aw->
[de my-fun (Value)
<
aw->
(eval (list (any (pack "do-something-" (car Value))) (cdr Value))) ]
<
Regenaxer>
'any' is overkill
<
Regenaxer>
It starts a full parser (reader)
<
Regenaxer>
Also a security hole (read macros)
<
aw->
how can I do it without (any) ?
<
Regenaxer>
But building an exe and calling 'eval' is also overkill
<
Regenaxer>
Produces garbage
<
Regenaxer>
Why not a single 'do-something' function with a 'case'?
<
aw->
each function does something completely different
<
Regenaxer>
Garbage in the sense of building a list only to execute and throw away
<
Regenaxer>
yes, so a typical 'case' (something different)
<
aw->
yes but 'case' requires me to know beforehand what all my options are
<
Regenaxer>
For separate functions too
<
Regenaxer>
you need to write them all
<
Regenaxer>
If the range of functionalities must be often extended, OOP is usually better
<
aw->
ok so, case like in my pastebin example?
<
Regenaxer>
Define new classes later etc
<
Regenaxer>
It is all perhaps mainly a matter of taste
<
Regenaxer>
Calling 'intern' all the time (and 'any' which calls 'intern' internally) is rather expensive too
<
Regenaxer>
Cause it looks up the symbol by name
<
aw->
what if I already have a list, such as (setq *Values '("one" "two" "three")) ?
<
aw->
why should i write a (case) for each "one" "two" "three" value?
<
Regenaxer>
If in doubt, 'case' is probably the best to associate code bodies with constants
<
Regenaxer>
Because you have a different code body for each value
<
Regenaxer>
(case ("one" (do1)) ...
<
Regenaxer>
There is nothing simpler and more efficient
<
aw->
but if i extend *Values, then i need to another case, AND another function/code body for it
<
Regenaxer>
Unless the cases are very many
<
Regenaxer>
thousands
<
aw->
instead of just adding another function
<
Regenaxer>
it is the same
<
Regenaxer>
(de foo ...) vs adding a case
<
aw->
(de foo ...) + add case VS add case
<
aw->
with my (eval) example, only need (de foo ...)
<
Regenaxer>
yes, so then as I say: 'case'
*only*
<
Regenaxer>
not both
<
Regenaxer>
case plus calling
<
Regenaxer>
(eval (list is a mess
<
aw->
then i end up with a huge function with so much code for each case
<
aw->
how about (eval ((intern (pack "do-something-" (car Value)....
<
Regenaxer>
I think this is very ugly
<
Regenaxer>
you need error checks
<
Regenaxer>
intern is expensive
<
Regenaxer>
creates garbage
<
Regenaxer>
you clobber the namespace
<
Regenaxer>
And
*still* need to define the functions somewhere
<
aw->
ok so my pastebin example is best :)
<
Regenaxer>
yeah :)
<
Regenaxer>
Though I would not write separate functions
<
Regenaxer>
No worry about big case statements
<
Regenaxer>
They are linear, and easy to read
<
Regenaxer>
A huge list of functions is not simpler
orivej has quit [Ping timeout: 260 seconds]
<
Regenaxer>
And you don't hurt the locality principle
<
Regenaxer>
Did you look at src64/emu.base.c ?
<
Regenaxer>
The case statement there has 4182 cases
<
Regenaxer>
It has 16591 lines :D
orivej has joined #picolisp
<
aw->
hmm i can't find that file
<
Regenaxer>
But OK, it is generated, not maintained manually ;)
<
Regenaxer>
It is generated with (cd src64; make emu)
<
aw->
maybe that's why emu is slow
<
Regenaxer>
Never mind
<
aw->
if it needs to try up to 4182 cases
<
Regenaxer>
This case statement is fast
<
aw->
it's indexed?
<
Regenaxer>
C indexes directly if the cases increase monotonuously
<
Regenaxer>
Looking up so many cases would indeed be very slow
<
Regenaxer>
I would not make such one in Pil
<
Regenaxer>
But Ersatz does the same
<
Regenaxer>
(not so long though)
<
aw->
ok. i guess a dozen or so case statements in pil wouldn't be slow
<
Regenaxer>
I think so too
<
aw->
but i'll use functions :P
<
Regenaxer>
Perhaps until hundred
<
Regenaxer>
Though hundred is too much prabably
<
Regenaxer>
a few dozen then
<
aw->
we need a "best practices in PicoLisp" document
<
aw->
to accompany the style guide
<
Regenaxer>
yeah, though hard to decide sometimes
<
aw->
i could run (bench) on a hundred case statements but i'll still get a result under 1s
<
aw->
kind of difficult to measure
<
aw->
thanks for the help
<
Regenaxer>
I think I don't have many case statements in pil
<
Regenaxer>
usually only for char lookup
<
Regenaxer>
@lib/led.l and @lib/vip.l
<
Regenaxer>
vip.l has many
<
Regenaxer>
nested ones
<
Regenaxer>
But Vip is not time-critical here
<
aw->
oh yeah i see it
<
aw->
wow that's a big case statement
<
aw->
not so big actually
<
aw->
but yes, nested...
<
aw->
commands eh.. i see
<
Regenaxer>
yeap, but I feel perfectly comfortable with it
<
Regenaxer>
Imagine writing that huge number of functions, and maintain both
<
Regenaxer>
locality principle ... !
<
Regenaxer>
I hate to have to maintain the same thing in two separate places
<
aw->
haha yes i see, but the body is relatively short in those
<
aw->
i wouldnt make a function just for that
<
aw->
maybe for ("ls"
<
Regenaxer>
Right, if a body part were more than say half a page I would factor it out
<
aw->
and ("w" and ("bd"
<
aw->
how many lines do you have on screen ?
<
Regenaxer>
on the tablet
<
Regenaxer>
So let's say "one page" ;)
<
aw->
i'm set to 40 on my monitor
<
Regenaxer>
ok, I usually split
<
Regenaxer>
either in vip or in tmux
<
aw->
half a page to refactor.. interesting
<
Regenaxer>
well, no strict rule
<
aw->
i try to limit to 10 lines usually
<
aw->
but it depends, sometimes a bit more is ok
<
Regenaxer>
Yes, that's optimal
<
aw->
ok i'm done for today, g'nite
aw- has quit [Quit: Leaving.]
<
beneroth>
I've a bunch of cli tools implemented in picolisp. using (case) and (cond) quite regularly there. simple and useful.
<
beneroth>
tends to become long code sometimes, but that only when the code is basically content anyway
<
beneroth>
e.g. a help function with help texts for every command
dtornabene has quit [Quit: Leaving]
<
Regenaxer>
Hi beneroth
<
beneroth>
hi Regenaxer :)
<
beneroth>
I love (cond)
<
Regenaxer>
yes, elegant
<
beneroth>
is it your invention? or you took it from something older? I often miss it in other languages
<
Regenaxer>
No, this is one of the oldest Lisp functions
<
Regenaxer>
"special form"s
<
Regenaxer>
Originally the only special forms were 'cond' and 'setq' or so
<
Regenaxer>
plus recursion and 'prog'/'goto'
<
Regenaxer>
I would say there was never a Lisp without 'cond'
<
Regenaxer>
How about Scheme?
<
beneroth>
no idea :)
<
beneroth>
afaik Scheme is a lisp child. is it not considered a lisp dialect?
<
Regenaxer>
Perhaps
<
Regenaxer>
Though this seems wrong:
<
Regenaxer>
(and a b) = (cond (a b) (else #f)
<
Regenaxer>
(or a b) = (cond (a #t) (else (b))
<
Regenaxer>
I would say (or a b) = (cond (a a) (else b)
<
Regenaxer>
I errors in one Line ;)
grp has joined #picolisp
himmAllRight has quit [Ping timeout: 264 seconds]
himmAllRight has joined #picolisp
orivej has quit [Ping timeout: 260 seconds]
orivej has joined #picolisp
grp has quit [Quit: box shutting down...]
reed has joined #picolisp
alexshendi has joined #picolisp
orivej has quit [Ping timeout: 240 seconds]