libera/commonlisp - IRC Chatlog
Search
18:20:19
_death
to get better context for Dijkstra, imagine (tagbody <your whole program here, using go to jump around>)
18:20:26
Bike
the context of dijkstra's paper was that people were regularly using goto when they could have used better control constructs. nowadays that's not really a problem with tagbody
18:21:16
Bike
people rarely use tagbody, and when they do use it it's for some weird shit that's hard or impossible to express with higher level constructs. like in eclector off the top of my head
18:22:47
Bike
dijkstra was also writing when "structured programming" was new, instead of now where it's so basic people don't remember it had to be invented
18:29:16
yottabyte
I'm not too knowledgeable about namespaces, but when I quickload a library, how do I add it to my namespace so I don't have to call functions from it with the name? like instead of library:function just call function. I guess this can become a problem if the library contains a function that's already defined in your namespace? but yeah.
18:29:52
didi
Oh, well, I can't solve my format puzzle. I'll transform the argument. /me likes format "puzzles"
18:30:37
_death
Bike: aside from tagbody being useful for state machines and such, it may also be useful to expand to in macros..
18:33:20
_death
yottabyte: (defpackage :yottabyte (:use :cl :arrow-macros)) (in-package :yottabyte) (-> "Hello" write-line)
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