freenode/#lisp - IRC Chatlog
Search
21:53:26
jackdaniel
without peeking into repl: (let ((x 3)) (loop as x = x then 4 do (print x) (return)) ; what is printed?
22:07:12
jackdaniel
I don't know, I've treated it as a no-brainer to initialize a variable (and shadow it lexially)
22:08:04
jackdaniel
no-defun-allowed: are you sure you didn't peek in the repl? otherwise, what is your reasoning behind getting NIL first?
22:10:34
aeth
jackdaniel: I noticed this because I use :of-type a lot in my loops, which catches that.
22:10:54
Bike
well, for a "for x = x" binding i would expect nil, yes, because i've done it before and got some bullshit like that
22:12:12
Bike
"he for and as keywords are synonyms; they can be used interchangeably." oh, alright then
22:12:22
aeth
lol in this particular case in SBCL, of-type doesn't catch the NIL not being an integer it turns it to 0: (loop as x of-type integer = x then 4 do (print x) (return))
22:14:35
no-defun-allowed
jackdaniel: no, i did think about that one, since i've been bitten by that before
22:15:02
no-defun-allowed
LOOP binds new variables to NIL, so `(loop for foo = foo ...)` binds foo to NIL
22:15:36
no-defun-allowed
something like (let ((foo 42)) (loop for foo = foo then (next foo) ...)) doesn't work, since foo gets bound in the LOOP first
22:15:47
aeth
no-defun-allowed: except if you add "of-type integer" to the example code jackdaniel posted you get 0 in SBCL!
22:16:11
no-defun-allowed
didn't know that though, probably needs to get the uninitialized type right
22:16:46
no-defun-allowed
i don't want to read through MIT loop but it's probably in there, since the "uninitialized" value has to have an appropriate type
22:16:50
aeth
Well, I guess SBCL and CCL do the same thing that they do for array default values here.
22:17:17
aeth
as in, NIL unless it can't be NIL, in which case it's the appropriate type's 0 (e.g. 0 or 0f0 or 0d0) or #\Nul
22:31:56
specbot
Local Variable Initializations: http://www.lispworks.com/reference/HyperSpec/Body/06_abb.htm
22:31:59
pillton
"If the optional type-spec argument is supplied for the variable var, but there is no related expression to be evaluated, var is initialized to an appropriate default value for its type."
22:34:02
aeth
This doesn't work for every type because not every type has a default value. e.g. string (surprised it wasn't an empty string) or (integer 3 4)
22:34:32
aeth
Actually, I think (integer 3 4) should have an appropriate default value: the number closest to 0 (so in this case, 3) since 0 itself is off limits but would otherwise be the default
22:38:47
aeth
It would be nice to have a standard default value and a way to retrieve it given a type specification. So (type-default-value 'integer) would be 0 and (type-default-value '(integer 3 4)) would be 3 (closest to 0) etc. Then you could define your own. Obviously would have to rely on some portability library.
22:40:21
aeth
Even better if it handled types like '(or null foo) and was able to detect that NIL is preferable there even if foo has a default. Would be hard for something like '(or integer character) though.
22:44:28
aeth
Well, you would want to prefer NIL when NIL was possible. You'd also want to prefer the simplest 0 possible (probably 0 then 0f0 then 0d0 or something) for numbers.
22:46:00
aeth
You'd probably want to prioritize empty sequences, or sequences of default values of the minimum length if 0 is not allowed. Sequence hierarchy would probably be NIL before vector (i.e. #() if empty) before specialized vector (like string's "")
22:46:16
aeth
I can see why this wasn't standardized even though there are several places that rely on default values
22:53:52
aeth
pjb: Type rules would be the hard part to solve, but imo would be worth solving. It would mostly be AND/OR combinations as well as numbers and sequences that would be tricky. Hard, but a finite problem.
22:55:43
aeth
Satisfies would be impossible to solve here afaik. Would probably just be best to extend deftype at that point.
23:07:12
aeth
pjb: well, having a method that could override the default for a class would be preferable to a specified initial-element every time imo
23:08:45
aeth
Types are trickier. "Closest to 0 in a range and of the simplest type" probably makes the most sense for numbers. "Closest to length 0 and if not length 0 filled with elements of the default" makes the most sense for a sequence type. AND, OR, SATISFIES, etc., might be too hard, although I'd really like to see (or null foo) work at the very least.
23:18:52
pillton
I'm not sure all of this complexity is worth it. What is appropriate depends on the context as is illustrated by finding the maximum element of an empty sequence.
23:23:31
aeth
pillton: But it would be very useful for custom defstructs/defclasses where you provide a type and get a reasonable default value from that automatically, even if no implementation uses it for LOOP, MAKE-ARRAY, and wherever else the standard uses defaults.
23:25:10
aeth
Right now the only easy automatic default value is NIL, which requires the type to be (or null ...) or one of the handful of types that supports NIL (list, sequence, symbol, boolean, T, etc.)
23:26:26
aeth
You also see default values in gethash and a few other places (in the function calls themselves), which other macros/functions might want to override in a somewhat smart way.
23:43:39
pillton
For that case you could use the prototype object specified by MOP. (What I and pjb said before).
6:56:28
no-defun-allowed
map works best if you just have one function to "map" over, or you don't mind a small lambda
6:56:29
verisimilitude
So, if you know what you're doing ahead of time, LOOP is in all likelihood going to be more efficient.
6:56:58
verisimilitude
LOOP is also more general, being able to traverse hash tables and non-structures.
6:57:21
no-defun-allowed
loop executes entire expressions, which may be more wordy for simple things, but loop is probably less consy and faster than, say map + remove-if-(not) and related functions
6:57:59
no-defun-allowed
i wrote a test program which would try to buy low and sell high on one share over 100 days
7:00:34
hectorhonn
that means other than convenience, there is no particular reason to choose one over than the other right?
7:00:35
no-defun-allowed
it's not great though, usually about 10%ish profit over 100 days but you don't need an awful lot to win apparently
7:01:21
verisimilitude
So, if you know what you're doing ahead of time, use LOOP; in all likelihood, you will use LOOP more than MAP.
7:01:31
no-defun-allowed
>loop is probably less consy and faster than map with remove-if and other higher order functions, and works on expressions instead of functions
7:01:59
verisimilitude
Furthermore, LOOP permits doing more than traversing lists and whatnot, such as maintaining multiple numbers and other things.
7:02:32
no-defun-allowed
also true, map would require the likes of reduce or remove-if(-not) to further process results
7:03:24
no-defun-allowed
oh dear, that stuff about buying was directed for #lispcafe, please ignore that
7:04:16
sindan
if it's down to preference I go to great lengths to use map*, I think they are prettier. That said, loop does more, more elegantly, when more is needed.
7:05:05
no-defun-allowed
yeah, use map for the small things where you just need to call a function with each element, or you don't mind a small lambda to do it
7:41:12
hectorhonn
i think loop is nicer when there is some "state" to keep when progressing from one element to another. using map in that case would need an extra let clause.. just my 2c
7:50:24
sindan
yes, one nice side effect of loop (for me anyway) is that one avoids having to name variables that will do boring stuff. The code looks neater.
7:57:13
aeth
You use loop for things like conditional collect where you can't really use map like ":when foo :collect foo :into foos" because the alternative to that is remove after map
8:01:22
aeth
Similar reasons to use loop include conditional append (like above) and multiple return values (e.g. to build several lists at once)