freenode/lisp - IRC Chatlog
Search
16:07:25
another-user
why this is so slow? http://dpaste.com/0NSR3JR it takes eternity to process 4MB file
16:11:33
another-user
actually when i use (read-line stream) opposed to (read-line stream nil) it signals an error pretty quickly
16:17:27
jasom
another-user: it's a style thing. (null foo) implies that it's checking for nil being a null value rather than a true/false value
16:18:00
phoe
"while line is non-NIL" and "until line is NIL" are equivalent functionally, but there's a detail regarding NIL-checking functions in Lisp
16:18:13
beach
another-user: Because while line violates the expectations that WHILE should be followed by a Boolean, wheras LINE is not a Boolean, it's line or NIL which means a default value, and not a Boolean.
16:18:45
phoe
(not line) and (null line) are the same functionally, since NOT and NULL do literally the same thing
16:19:06
phoe
but presence of one and not the other conveys a meaning to the programmer - are you expecting a boolean, or are you expecting any Lisp datum
16:21:57
pjb
I beg to differ about not and null. The problem is that the language is specified in such a way that you have to understand what while line means.
16:23:08
pjb
So you'll get code that is slower, for no more clarity in the source code, and maintainer left to wonder why there's some negative logic or useless calls, when while line was perfectly clear and defined in the first place.
16:23:44
pjb
On the other hand, I would perfectly understand that you defined a language where while <boolean> would exclude while <line> with <line> being of type (or null string) (which is not boolean (member nil t).
16:24:23
pjb
But notice also that CL specifies predicates to reutrn generalized boolean, so you would have to change this specification or use while (not (not (= x 420))) etc…
16:25:50
jasom
pjb: "generalized boolean" is meaningless to a machine, since all values are generalized booleans. It's meaningful to a programmer though in that "the only useful information here is (eq X nil)"
16:26:35
pjb
jasom: it is not meaningless. It means that operator taking generalized boolean must already check specifically for NIL. (presumaly using null).
16:27:11
pjb
It's silly to write (not (null (not (null x)))) so don't write (not (null x)) when the operator already has to use (not (null .)) around your value, by specification.
16:28:39
jasom
pjb: If you follow the style suggested in LUV then "while X" implies that the only interesting thing about X is whether it is nil or not. but "until (null x)" implies that there are other interesting things about X.
16:29:38
jasom
It's about communicating extra information to the reader by convention, not about anything else; similar to (but less universal than) earmuffs.
17:00:03
_death
jasom: to me that would be more about while/until than about X.. personally I use "while line" because that's the normal case.. I would use until when some work must be done until some condition is satisfied, and that it's satisfied is what should be emphasized
18:33:22
jasom
_death: that's a style difference, I almost always use whichever allows me to eliminate a negation, but I see the advantages of your way as well.
20:19:45
pfdietz_
I use (not (not x)) to normalize "true" values to T. It's used all over the place in ansi-tests.
20:53:02
aeth
The correct solution, though, is always the one that's done through the type system. (handler-case (progn (check-type x null) x) (type-error () t))
20:58:24
grewal
I was trying to find a sillier way than aeth's example to get normalized truth values
21:12:03
aeth
Well you can have fun with heavyweight libraries to do a simple task, e.g. using specialization-store to type-dispatch: (defstore coerce-to-boolean (object)) (defspecialization coerce-to-boolean ((object (not null))) boolean (declare (ignore object)) t) (defspecialization coerce-to-boolean ((object null)) boolean object)
21:14:04
aeth
If you want to do something using just built-ins, I think this similar approach works: (defgeneric coerce-to-boolean (object)) (defmethod coerce-to-boolean ((object null)) object) (defmethod coerce-to-boolean ((object t)) (declare (ignore object)) t)
21:15:34
grewal
Yeah, I guess medium length joke things aren't as funny. It needs to be short or completely over the top
21:18:04
pjb
(not x) is one function call and one if. (not (not x)) is 2 function calls and two IFs. (if x t nil) is just one IF.
21:19:10
pjb
(not x) may be understood by random people, but they'll have a hard time, if they don't know lisp to infer that it'll return either the symbol T or the symbol NIL. (if x T NIL) on the other hand should be obvious to everybody, even most non-programmers.
21:20:22
aeth
pjb: trying to microoptimize this doesn't make sense because even the simplest optimizing compilers will probably optimize this away. e.g. I think SBCL has all of the simple examples as equivalent
21:21:00
pjb
aeth: I'm not optimizing the compiler, or compiled code, but the understanding by human readers.
21:23:08
Inline
truthy xes are also input to it but it just skips them, doin nothing on them or returning anything back....
21:26:48
aeth
This is the proper way to do things, btw. (let ((*print-case* :upcase)) (numberp (string/= "NIL" (format nil "~A" x))))
21:29:44
pjb
(mapcar (lambda (x) (let ((*print-case* :upcase)) (numberp (string/= "NIL" (format nil "~A" x))))) '(42 XLII NIL)) #| --> (t t nil) |#
21:38:16
sjl_
(defgeneric ensure-boolean (object)) (defmethod ensure-boolean ((object (eql nil))) object) (defmethod ensure-boolean (object) t)
21:47:01
selwyn
a few weeks ago, someone posted a good article that discussed how a hypothetical 'when-let*' macro would be fundamentally broken
21:48:41
mfiano
IIRC sjl_ posted about why, more than a few weeks ago: http://stevelosh.com/blog/2018/07/fun-with-macros-if-let/
21:49:14
sjl_
I don't think I claimed it would be fundamentally broken, only that's it's not as trivial as it appears at first glance.
21:49:45
sjl_
If you take care to do something reasonable with the declarations and such, I think you can have a fairly useful if-let*
21:51:18
sjl_
clojure's if-let doesn't support multiple bindings. is that maybe what you're thinking of? https://stackoverflow.com/questions/11676120/why-dont-when-let-and-if-let-support-multiple-bindings-by-default
21:52:55
sjl_
(and if there's only a single binding, there's no different between the -let and -let* variants, so it would make no sense to have it)
1:10:52
aeth
On the earlier topic of COERCE-TO-BOOLEAN, here's my latest attempt. It's too long to fit on an IRC line. https://gitlab.com/mbabich/cl-brainfuck/blob/5db780f08e6c0e686c1d8fe2f5ea78acf0d94163/brainfuck-examples.lisp#L64-105
1:11:37
aeth
pjb: and slight correction with earlier. It has to be ~S not ~A or else "NIL" also passes