ChanServ changed the topic of #picolisp to: PicoLisp language | Channel Log: https://irclog.whitequark.org/picolisp/ | Picolisp latest found at http://www.software-lab.de/down.html | check also http://www.picolisp.com for more information
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
<aw-> hi all
<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> (and
<Regenaxer> (assoc (car Value)
<Regenaxer> (quote
<Regenaxer> ("one" . do-something-one)
<Regenaxer> ("two" . do-something-two)
<Regenaxer> ("three" . do-something-three) ) )
<Regenaxer> (@ (cdr Value)) ) )
<Regenaxer> Not much shorter though ;)
<Regenaxer> ah, no
<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-> with (any) ?
<aw-> oh (intern) ...
<Regenaxer> (intern "three")
<Regenaxer> yes
<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-> hmmm
<aw-> i have this:
<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> intern
<Regenaxer> But building an exe and calling 'eval' is also overkill
<Regenaxer> Produces garbage
<aw-> 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
<aw-> i see
<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> yes
<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-> no
<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
<aw-> oh
<Regenaxer> case plus calling
<aw-> that's messy
<Regenaxer> sigh
<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)....
<aw-> same?
<Regenaxer> I think this is very ugly
<Regenaxer> you need error checks
<Regenaxer> intern is expensive
<aw-> right
<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 :)
<aw-> thanks
<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
<Regenaxer> No
<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
<Regenaxer> T
<aw-> thanks for the help
<aw-> as always
<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> big ;)
<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
<Regenaxer> true
<aw-> ("q" (done))
<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-> i see
<aw-> how many lines do you have on screen ?
<Regenaxer> 48
<Regenaxer> on the tablet
<aw-> oh wow
<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-> of course
<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> hi all
<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> and
<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 ;)
<beneroth> :)
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]