freenode/#lisp - IRC Chatlog
Search
22:17:31
frodef
yes, but remove-if-not and the :test-not args are "deprecated", which makes me suspect there's supposed to be another way...
22:18:15
Bike
it was deprecated like twenty years ago because they thought COMPLEMENT would be more useful.
22:18:53
Bike
but there is no problem using remove-if-not and even if there was somehow a new standard revision, they probably wouldn't actually remove it.
22:29:20
mfiano
It's surprisingly actually smaller code size on SBCL, too (though code zie is not a good measure of performance).
22:54:36
frodef
Bike: right, thanks, COMPLEMENT was probably the piece of the puzzle I'd forgotten about.
22:57:04
frodef
...and even more so for (remove keep-value ... :test-not 'eql), which is not very readable at all.
23:00:57
frodef
-- "Several alternative names for REMOVE-IF-NOT were suggested: KEEP-IF, ABSTRACT, FILTER. We did not pursue these suggestions." Oh well.
0:07:53
aeth
a true IF-NOT in the language would have a second branch and just reverse the order of the IF
2:12:35
dbotton
if anyone over next day or so has time and can try out my tutorial 8 from CLOG running at http://office.botton.com:8080/ I made some critical changes from last test (thank you for using it those that did). The source is at https://github.com/rabbibotton/clog/blob/main/tutorial/08-tutorial.lisp
2:14:13
brandflake11
Hey all, I have a question for you all. I am writing a function in lisp, and need to create a list out of the function's arguments. Here is what I have for the function:
2:14:56
Bike
please use a pastebin service for multi-line pastes. anyway, so this function is supposed to randomly select and return one of its three arguments?
2:15:40
Bike
The only problem I see in this paste is that you meant to write (list note1 note2 note3).
2:17:07
Bike
you wrote (note1 note2 note3). this means it will call the function NOTE1 with two arguments. Since there's no function called NOTE1, you get an error.
2:17:45
Bike
your compiler might alert you to this. SBCL says "Undefined function: NOTE1" when you compile, and "The function NOTE1 is undefined" when you actually call it.
2:19:11
Bike
No, but if you all you want to do is pick one of the arguments randomly, you probably don't need to make a list.
2:19:13
brandflake11
I tried '(note1 note2 note3), but they gave me the literal variable names as members in the list
2:23:24
brandflake11
Does the &rest args stand for something? Like is it an abbreviation of a phrase in English?
2:40:30
brandflake11
One more question: can you use &rest with other mandatory variables? Like (note1 note2 &rest args) making note1 and note2 arguments mandatory?
2:43:22
fiddlerwoaroof
If you know you have 3 arguments, something like this is probably better: (define pick-three (a b c) (ecase (random 3) (0 a) (1 b) (2 c)))
2:54:12
saturn2
you could also get the best of both by adding (define-compiler-macro pick-random (&rest args) `(ecase (random ,(length args)) ,@(loop for arg in args for i from 0 collect (list i arg))))
2:57:17
saturn2
that macro writes code like what fiddlerwoaroof wrote, but for any number of arguments
2:59:38
saturn2
they are functions that return lisp code, which is then inserted in place of the macro call
2:59:57
brandflake11
saturn2: I haven't learned about macros yet either. But man, that is really cool.
3:03:55
saturn2
and of course you can have regular loops in your macro, the one i wrote above has one
3:07:05
aeth
brandflake11: So with quote, it basically follows the distributive property. '(a b c) is essentially like (list 'a 'b 'c) just like (* z (+ x y)) is like (+ (* z x) (* z y))
3:07:27
aeth
Quasiquote is a quote you can unquote. `(a b c) is essentially the same as '(a b c) because there's nothing to unquote so it's just all quoted.
3:07:49
aeth
`(a ,b c) however, will "unquote" b and so it's like (list 'a b 'c) instead of like (list 'a 'b 'c)
3:09:05
aeth
,@ is a bit more complicated. It's unquote splicing. It basically appends the inner list into the outer list
3:10:58
aeth
As for why you'd need ,@ it's mostly for targeting some macros like LOOP, e.g. (loop repeat 3 do (print "hi"))
3:11:49
aeth
If you're writing a macro with quasiquote that generates a loop, you'll probably have to do something like this: (loop ,@(generate-the-clause-here) do (print "hi"))
3:12:09
brandflake11
saturn2: That makes sense, since you don't want separate lists together. You want one lits
3:12:59
aeth
The other time you see ,@ a lot is with `(progn ,@body) in macros that have an &body body which is essentially just giving you the rest as a list just like &rest rest
3:15:44
aeth
The defmacro for WHEN might look something like this (name changed so you can evaluate it): (defmacro when* (test &body forms) `(if ,test (progn ,@forms) nil))
3:18:33
aeth
If a function is (defined in another file that's loaded first) or (wrapped in an EVAL-WHEN) then it can be used as a helper function... at least for macros; I've never really had to use compiler macros.
3:20:33
brandflake11
Is a helper function one that is previously defined to be used in another function?
3:21:33
aeth
I personally see it as a function that's designed to keep another function (or a macro) short/simple/easy even if it's only going to be called from one caller (at least, outside of unit tests)
3:22:30
aeth
A lot of people don't like functions that are only called from one place, but I love them, especially in macros.
3:22:45
aeth
As for unit tests, those are tests of a unit... usually a function or a class or things like that afaik.
3:23:18
aeth
If you break up a big, messy macro into lots of functions, then you can test to make sure that any changes you make don't change any of those functions, which gives you more confidence to mess around with really tricky macros
3:24:15
aeth
If you just have the macro, then you'll have to write a lot of tests on the macro directly, probably with MACROEXPAND-1 to test expanding the macro
3:27:16
aeth
More concreately, you could have a function for your macro that turns (foo bar baz) into ((foo (make-quux 'foo)) (bar (make-quux 'bar)) (baz (make-quux 'baz))) and this is small, simple, and easy to test.
3:28:48
brandflake11
aeth: Have you had to change the way you format your macros in professional environments because some people don't like formatting like that?
3:30:20
aeth
Try to match the style of the person who originally wrote the file. There are lots of little things that can be different in styles.
3:39:03
brandflake11
Thanks to all of the help I received on here. I have created my random sequencer in common music successfully!
4:30:08
beach
FILTER is not a great name for a filtering function, because it doesn't say whether the objects for which the predicate returns true are kept or discarded. REMOVE-IF and REMOVE-IF-NOT are much better.
4:43:50
beach
Dizidentu: So I saw in the logs that you are a C++ programmer. I think it would be a good idea for you to learn some Common Lisp to get another perspective on programming.
5:56:21
beach
Python is a pure interpreter, which means you can't really get any performance out of it, unless you write your code in C.
5:56:44
beach
Most Common Lisp systems compile on the fly, so you can write all your code in a truly high-level language.
5:57:21
beach
Furthermore, Python is not homoiconic, so you can't really do any metaprogramming in it, like macros.
5:57:50
White_Flame
each languages seems to have its own definition of "metaprogramming". For python, it seems to be adding hooks on object methods
5:58:29
beach
White_Flame: Thanks. I am not following the Python terminology, so I appreciate the information.
5:58:41
Dizidentu
I would stay but I just got back and I want to catch this flight into slumber land while I still can :|
6:01:17
beach
And, no, I think the purpose of Python is as a "scripting language", whereas Common Lisp is a general-purpose programming language.
6:05:50
White_Flame
because most people don't actually do core programming anymore, but rather call libraries (iow scripting)
6:07:51
beach
drmeister once showed us a site that gave the cost in electric power per computation unit for various languages, and Python is really bad.
6:16:24
parjanya
mornings! Is there a function, or an easy test... to check if an object can be printed readably?
6:24:35
beach
The answer would be influenced by things like methods on PRINT-OBJECT, and the existence of reader macros.
6:29:18
White_Flame
(handler-case (let ((*print-readably* t)) (write-to-string <item> nil)) (t (t) t))
6:31:10
White_Flame
actually, (ignore-errors (...try to print readably...) t), returning NIL if it isn't readable, is easier
6:33:53
parjanya
ah, very good idea, thanks! I tried finding a way to chase the method for printing, but no luck
7:04:16
White_Flame
I just tested with function objects, and those blew up when *print-readably* was set
7:10:23
White_Flame
if you truly do want to prune the values, then (values (thing-that-returns-multiple-values...)) does only return the first
7:18:23
White_Flame
"If printing an object readably is not possible, an error of type print-not-readable is signaled rather than using a syntax (e.g., the ``#<'' syntax) that would not be readable by the same implementation."
8:58:33
xificurC
yesterday someone pointed out I can define a package local nickname for a package, where can I do that? I don't see this option in the defpackage clhs page
9:06:18
xificurC
I'm really glad this is getting implemented, it's a huge boon in the lisp that doesn't like to get discussed here (or even be called a lisp)
9:13:00
beach
xificurC: There is widespread agreement, even among the commercial Common Lisp vendors to implement package-local nicknames. But how does the implementation of package-local nicknames for Common Lisp benefit "other lisp"?
9:15:40
xificurC
I'm saying I've been using local nicknames (aliases) in clojure and am happy I can use them in CL now as well
9:16:11
xificurC
I mentioned it because I thought it might have been an inspiration to finally implement it
9:18:42
xificurC
the last thing I'd like is for `(i:iter (for i from 1 to 10) (collect i))` work. But the reader screws me over, even though `iter` could resolve `for` and `collect` during macroexpansion
9:23:36
beach
LOOP can do it, so I don't see why ITER could not. But it would likely require a radical restructuring of the code.
9:24:49
beach
xificurC: It is a simple matter of using the names of the symbols involved instead of the symbols themselves.
9:25:00
flip214
xificurC: how about i::(iter (for i from i to 10) (collect i))? but then the symbol "i" would be in the iter package...
9:25:14
beach
xificurC: But I am guessing that FOR is a local macro introduced by ITER, and that would have to change.
9:26:24
beach
xificurC: It is possible that ITER can do some things that LOOP can not, but the fact that ITER is not standard is an argument against it, especially since LOOP can handle most situations.
9:27:03
beach
xificurC: The argument that people use in favor of ITER and against LOOP is often that "LOOP is not Lisp-y", which is silly of course, since it is part of the standard.
9:27:13
xificurC
mfiano why shy away? I don't find it much harder to read or understand than loop. Are there some inherent flaws in its implementation?
9:28:36
xificurC
beach I thought the main argument is that an external package can extend iter, e.g. a database library exposing a cursor can plug it into it
9:28:47
beach
xificurC: An external library that may or may not be maintained in the future, and that does little more than a standard facility should be given some thought before being used.
9:28:52
heisig
xificurC: It is a question of the amount of 'vocabulary' that I need to know to read your code. LOOP is (for good or for bad) part of the vocabulary we all know. ITER isn't.
9:29:12
mfiano
It's not standard Lisp which everyone is familiar with, it can have its forms broken up and spread out, it is often used like it is standard with use-package.
9:30:20
flip214
heisig: but the same argument applies to lparallel, cl-who, alexandria, and so on and on.
9:31:12
xificurC
beach I was showing the simplest example, not a real one. At this point in time I'm not using anything that loop doesn't handle, so it's easy to switch back
9:31:25
heisig
flip214: It is a difference whether you introduce functions or macros. And even with macros, there is a difference between introducing an obvious WITH-* macro, or an entirely new control-flow construct.
9:31:38
beach
xificurC: So in that case, use LOOP for everything that does not require an extension.
9:32:31
mfiano
In 15 years I have not needed LOOP to do anything else. One has to be careful about shiny things, features you think you might need, or think they will benefit you, but in turn do more harm than good.
9:32:32
xificurC
this is the lisp schizofrenia I never understood - an infinitely extensible language that nobody wants to extend
9:32:47
flip214
beach: I don't think that's a good argument. If something is being used often, it becomes mainstream - and then you'll see it so often that you'll just know it.
9:33:12
flip214
so your argument sounds to me like "something must be used everywhere to be used everywhere", which is loopy ;)
9:33:40
beach
xificurC: It is extended most often on a per-application basis. That's the beauty of it.
9:33:40
xificurC
that was a reaction to "It is a question of the amount of 'vocabulary' that I need to know to read your code"
9:35:27
beach
xificurC: Applications introduce new vocabulary in the form of functions, macros, classes, etc. That vocabulary becomes specific to the application and its domain.
9:36:13
heisig
xificurC: Extending Lisp is just something that shouldn't be done lightly. If you are working with music, this is a good reason to introduce custom notation. But 'I don't like LOOP' is not a very good reason for introducing custom notation.
9:37:42
beach
"The argument that people use in favor of ITER and against LOOP is often that "LOOP is not Lisp-y", which is silly of course, since it is part of the standard."
9:37:53
mfiano
The flexibility of Lisp allows you to use iterate or extend the language with new syntax of your own. This is why Lisp suffers from NIH, being so flexible and thus designed for small teams, makes it often more desirable and easier to re-implement a piece of software yourself, than to try to understand someone else's code. After all, code is just a projection of your mind, and trying to understand
9:37:55
mfiano
someone else's moulding of the language for a particular domain usually doesn't map too well.
9:43:11
xificurC
mfiano "In 15 years I have not needed LOOP to do anything else" - I find this thinking backwards. LOOP was chosen and implemented by a committee. That committee could have accepted SERIES just as well. Or it could have accepted none of them and we would be writing mapcars and the like. In that world if a user comes asking about LOOP, which is now a
9:43:11
xificurC
library, would the argument be "In 15 years I have not needed LOOP because mapcar and friends can do everything LOOP can"?
9:43:56
mfiano
xificurC: If we had series for decades of widespread use I would have "thought forward"
9:47:05
xificurC
I only picked up 2 dependencies so far. I see iterate is not, ehm, famous around here :) The second is trivia. Is trivia OK?
9:47:20
heisig
xificurC: I think I know how you feel about LOOP. It is not that I haven't used ITER myself because it is more powerful and flexible. But here I am, back to using LOOP. And why is that? Because having a powerful iteration construct is really not that important.
9:48:07
mfiano
When I first began using Lisp I too used iterate for a short while, but I couldn't agree more with heisig.
9:48:12
flip214
heisig: and ITER isn't as readable as LOOP? Which difference (apart from the parens) do you see, in typical use?
9:48:16
xificurC
heisig so you're saying in the years you programmed you find LOOP more readable than ITER, is that correct?
9:49:17
flip214
another feature of ITER is that the clauses like COLLECT can be used in subforms as well - LOOP requires them at the loop-level, which is awful sometimes
9:49:36
heisig
xificurC: 100% of the Lisp programmers know about LOOP, but only at most 60% (at most) know about ITER. That settles it for me.
9:50:33
mfiano
LOOP only cares about the symbol name for LOOP keywords. Iterate requires you to modify symbol property lists for synonyms.
9:53:43
flip214
heisig: 10% of programmers know Java, but only 1% of programmers know Lisp. How is that an argument against Lisp? (numbers invented)
9:55:10
flip214
of course, there's no reason to invent new code-flow macros all the time - but a nearly 1:1 translation of a construct defined in the standard is on the safe side, me thinks.
10:01:15
heisig
flip214: I think the benefits of using Lisp over Java are greater than those of using ITER over LOOP. But even then I occasionally choose Java or Python over Lisp for some projects, because it is more accessible for the target audience. (Not often though, and not gladly)