freenode/#lisp - IRC Chatlog
Search
22:38:13
xsperry
hi. what would be the closest equivalent of list comprehensions in lisp? loop macro?
22:39:04
xsperry
particularly in cases when you iterate over two or more lists. do I need nested loops for that?
22:45:37
edgar-rft
a) what are "list comprehensions"? b) It's possible to iterate over several lists at once with the same pros and cons as in other languages. Nested loops are the simplest possibility.
22:46:45
Bike
list comprehensions are a syntactic construct in python and other languages that is indeed kind of like loop.
22:51:17
xsperry
ok, here's a simple example that is very easy to express with list comprehensions. given two lists, '(1 2 3) and '(4 5 6), make a list of conses consisting of each element from list A and list B. so '((1 . 4) (1 . 5) (1 . 6) (2 . 4) (2 . 5) (2 . 6) (3 . 4) (3 . 5) (3 . 6))
22:53:17
jasom
xsperry: I believe that's a nested loop in python as well (unless you use itertools which has that function builtin IIRC)
22:53:35
Bike
it would have to be a nested loop under the hood since you're iterating over both lists independently, anyway.
22:55:14
xsperry
jasom I think you don't, but I am not 100% sure. it has been years since I used python, but python's list comprehensions were inspired by haskell's, and in haskell you don't need to nest list comprehensions for this
22:55:47
xsperry
I am actually trying to replicate this really elegant example from haskell tutorial in CL
22:57:07
jasom
as in (loop for x in xs for y in ys collect (cons x y)) would return just 3 items with your inputs.
22:57:10
xsperry
jasom, you would zip lists first, and then then pattern match on resulting list. but at that point you probably wouldn't be using list comprehension
22:57:41
shachaf
Oh, LOOP iterates through lists together instead of nesting? That's what I get for saying something in here.
22:58:23
shachaf
In GHC Haskell you can write [(x,y) | x <- xs, y <- ys] for nesting and [(x,y) | x <- xs | y <- ys] for zipping. But zipping seems to me like a much more unusual behavior.
22:58:25
xsperry
this is the example I'm trying to rewrite in CL. it takes first 10 right triangle that has integers for all sides
22:58:40
xsperry
[(3,4,5),(6,8,10),(5,12,13),(9,12,15),(8,15,17),(12,16,20),(15,20,25),(7,24,25),(10,24,26),(20,21,29)]
22:59:22
xsperry
[1..] would probably be hard to emulate, but what about the rest? three nested loops? what are the alternatives?
23:02:00
jasom
xsperry: I'm not sure how the haskell example works; does it find all right triangles where the first side is of length "1" first?
23:03:10
xsperry
jasom, [1..] is an infinite list of integers. take 10 drivers computation, and since haskell is lazy it will only compute enough to take first 10 such triangles
23:06:27
jasom
it is indeed lazy which is <sarcasm>completely obvious from the source to anybody</sarcasm> https://github.com/jasom/itertools/blob/master/itertools.lisp#L406
23:07:13
aeth_
Well, that was an incredible mess. nickserv and chanserv were down but nearly every channel was +r and in every other one you couldn't speak. So if your Internet went down in a period of about 4-5 hours or you tried to connect, you were out of luck, apparently.
23:09:22
aeth_
And the best part is, when it forced my nick to Guest1234 or whatever when nickserv came back, it made my nick temporarily unavailable.
23:10:32
xsperry
jasom, ok, this is a lot more similar to the solution above than I imagined it to be. if I got it right, can I use loop to generate some lazy equivalent of a list (infinite list of right triangles), and then take first 10 such elements?
23:10:35
shachaf
As I'm trying to figure out some language ideas the language is becoming more and more like lisp. I guess this is an old story.
0:00:40
xsperry
_death, interesting, thanks. I wonder how close we can take it syntax wise with macros
0:11:05
_death
I guess something like this isn't too bad (take 10 (gen ((c (range 1)) (b (range 1 c)) (a (range 1 b))) (when (= (square c) (+ (square a) (square b))) (list a b c))))
3:38:15
krwq
how does slime figure out the arguments for macro/function? I tried to use function-lambda-expression but it seems it does something more clever
5:10:20
earl-ducaine
Use of the question mark (rather than -p) seems barbaric: https://gist.github.com/earl-ducaine/dd90263f81d44ab1de90c868bff86c1f
5:18:39
sabrac
earl-ducaine: https://www.cliki.net/naming%20conventions indicates that scheme uses the question mark.
5:35:47
sabrac
https://google.github.io/styleguide/lispguide.xml#Predicate_names notes some existing CL packages use ? but recommends against it
5:40:10
earl-ducaine
The code in question was written by Mlynarik (mly), who was working at Xerox at the time. So, it might have been a Interlisp convention.
6:01:39
aeth
The two main styles are either p for single words and -p for multiple words or -p for everything. -p for everything does have its users
6:07:06
aeth
The original style is foop and foo-bar-p. foo-p came later, either to make it unambiguous or because someone misunderstood the rules (probably both, depending on the person)
6:22:18
edgar-rft
The question mark was used in the 1980s as the suffix for "unknown" variables in logical pattern matchers, while the p suffix was used for logical predicate functions. That was long before Scheme used ? for predicates.
6:25:33
aeth
I use the ? and ! conventions from Scheme from time to time. Interestingly enough, I don't use it in implementing my Scheme. If CL doesn't have a foop function and Scheme has a foo? procedure it seems clearest just to define a foop function and then use that as the implementation of Scheme's foo? procedure, especially when barp does exist in CL.
6:25:55
aeth
I'm fuly aware that if I use foo? somewhere, 90% of the readers will despise it, though :-p
6:26:39
aeth
foo! is trickier because there's no direct equivalent so it might be the best choice if you need to communicate mutation. The f in setf or incf doesn't mean the same thing.
6:29:39
edgar-rft
What I wanted to point out is that using ? for Common Lisp predicate functions is historically wrong.
6:31:36
aeth
The only wrong answer is some convention from another more distant language like is-foo (or get-foo)
6:32:58
edgar-rft
there had been so many obscure conventions in the past that "wrong" becomes rather blurry in this context
6:34:09
aeth
It's funny that get-foo is, in my opinion, incorrect CL style that I wouldn't accept in any of my projects (just call it foo), but cl:get-TAB produces 9 results.
6:35:55
aeth
Similarly, define-condition is there as a define-foo, even though the style many use is deffoo or defoo vs. define-foo-bar
6:38:16
aeth
The standard doesn't have +foo+ for its constants, just foo. That one's annoying. e.g. this won't work in SBCL: (let ((most-positive-fixnum 42)) (1+ most-positive-fixnum))
6:51:26
aeth
Instead of using +foo+ you can just take the convention from C and write it as FOO. e.g. (defconstant FOO 42)
6:54:38
jackdaniel
aeth: that C convention is broken for lisp, because default reader converts to upcase anyway
6:56:14
aeth
jackdaniel: +foo+ is superior anyway even if you could write FOO because not every Unicode character that's valid for a symbol name has an upper case form (although some symbols have upper case forms if you trust IRC)
9:13:36
schjetne
beach: I stayed at home (meant to get my PPL current again, but weather got in the way), but more importantly I want to discuss some consulting opportunities at my company. What do you prefer, email?
9:21:52
dim
when playing with unicode variable names, don't forget about the ++ (using zero-width space) (you could use more than one)