libera/commonlisp - IRC Chatlog
Search
18:35:49
_death
in a real program, consider using (:import-from :arrow-macros :->) instead of :use, to explicitly import the symbols you care about
18:37:11
didi
phoe: Sorry, but what's the name of the library which has literal tabs inside strings again?
20:35:22
pjb
yottabyte: you must read the documentation of the system, to know what packages it defines, and from what package it exports the names of the functions you want to use.
20:36:00
pjb
yottabyte: note: systems are named by lower case strings such as "foo"; while packages are usually named by uppercase string like "FOO".
21:35:53
_death
Josh_2: I actually stopped pulling changes from iterate because some library that used it broke, iirc
0:30:11
neominimum
mzan: I'm a perpetual newbie even though I've been casually using CL for a few years, my style suck-- I mean, my style is unconventional due my solitary practice. I'm trying now to be more conventional, so it's been great to get some specific feedback. Thanks for your suggestions. I wonder what is the reason why TCO needs to be supported by the standard, I mistakenly thought it was an implementation detail. I think I get it though... If the
0:30:11
neominimum
standard doesn't require it then implementations may not implement it. Does that make recursive code non-portable? Although my understanding is the standard doesn't require compilers to be optimising, professional users would not consider using one that lacked that facility. Like wise, I am interested to know if there is anyone that would consider a compiler that lacks support for TCO to be "Not Sufficiently Smart (tm)". I'm genuinely
0:33:45
jasom
first you need to define "what is tail position" (defun foo () (let ((*bar* 3)) (baz)) ; <-- the call to baz here will likely *not* be tail optimized on any CL compiler due to the dynamic binding of *bar*
0:35:01
jasom
Then once you've done that, you need to ensure that the function is compiled, as most interpreters will not eliminate the stack frame for tail calls
0:36:02
jasom
Then once you've done that, you need to ensure that the "optimize" declaration is set sufficiently high (in either the absolute or relative sense; some compilers may use the relative values of optimize v. debug, for example)
0:38:01
jasom
The one place I like to rely on TCO is when implementing state-machines; in that case the non-tail call approach is less readable IMO and will involve passing either closures or a list of function and arguments, both of which are more unweildy than a tail-call
0:39:20
jasom
I should also point out that non-tail-recursive code is *definitely* non-portable; the maximum recursion depth may vary not just from implementation to implementation, but from machine to machine even when using the same implementation
0:46:10
neominimum
Ok, so it's definitely not feasible in some situations due to environmental factors and the use of some language features.
0:50:36
neominimum
I do like recursion, more because I find it challenging. To me it definitely looks better than some iterative implementations sometimes, but as they say "When in Rome..."
0:51:32
jasom
Oh, there are times when recursion is more readable than iteration, but, in my experience, few of those cases are tail-recursive
0:52:08
jasom
The most obvious example is any sort of tree walker; the recursive form is almost trivial, the iterative form involves an explicit stack.
0:54:26
jasom
The naïve fibonacci is the most readable way to do fibonacci; I think the iterative vs. tail-recursive are of similar readability.
0:56:36
EdLangley[m]
Clojure's LOOP/RECUR is an example of an abstraction that makes this a bit nicer.
1:03:34
EdLangley[m]
If you (psetf arg1 (step arg1) arg2 (step2 arg2)) (go start) you can "pass arguments"
1:04:40
jasom
EdLangley[m]: right, but that's far less clear and sm2n was asking "why not use tagbody"
1:05:19
neominimum
If I understand correctly now. In the iterative form, walking a non-linear data structure, requires the use of an explicit stack. Compared to the recursive form utilising the implicit call stack.
1:05:24
jasom
also if you break in the middle of the state-machine, you more quickly get the information you want with most implementations it will show the current function
1:06:50
jasom
neominimum: right, my comment was that most of the times that recursion is more clear than iteration, it's due to the implicit call-stack, which means it's not a tail-call.
1:07:18
EdLangley[m]
Hmm, expanding to (defun foo (...) (macrolet ((foo () `(go start))) (tagbody start ...))) would mean you could just turn recursive calls into GOs
1:08:20
jasom
EdLangley[m]: at that point I'd rather just do a loop/apply/funcall and return a function/args list from each state
1:09:19
EdLangley[m]
I've used it in PHP before when the recursive version of a function was significantly easier to write than the iterative one.
1:09:43
jasom
I've done both and I find the tagbody gets unweidly quickly for complicated state machines
6:33:14
asarch
If you have: '(:beers 20 :tacos 3), how would you add the property :pizza 4 to the list?: (:beers 20 :tacos 3 :pizza 4)