freenode/#lisp - IRC Chatlog
Search
22:34:30
jasom
makomo: https://github.com/jasom/cl-fccs/blob/e01f45a00577c22200ffdf8113efc421d3f00e10/src/util.lisp#L25
22:36:01
jasom
makomo: also note that I use vectors for json lists as well, so nil is unambigously false.
22:39:37
jasom
actually null would also decode to nil, but my data shouldn't have nulls in it for this case.
22:41:36
jasom
makomo: https://sites.google.com/site/sabraonthehill/home/json-libraries#TOC-Quick-JSON-syntax-refresher cl-json decodes 4! JSON types to something that could be nil by default :(
22:43:29
jasom
com.gigamonkeys.json is the only one on the list with a JSON->lisp->JSON that can survive a round-trip by default.
22:44:44
makomo
hm yeah, i only thought about the false/null case, but object/arrays could ofc be empty
22:46:15
jasom
the number of times that I've needed to distinguish betwenn "false" and "null" in javascript code is approximately zero, so that one is the most forgivable.
22:49:30
jasom
hmm, I was bad and didn't use safe-json-intern for making the keyword there though...
23:16:22
stylewarning
So you could product efficient parsers into whatever data structure you prefer
23:28:25
makomo
yeah, that's what i thought. thought there might be some neat way using and/or or something, but they both return either nil or the last value/the first non-nil value
23:35:37
aeth
If you're going to be unclear and use (and x t), you could still use if's implicit nil else and just say (if x t)
23:36:54
aeth
All three should have identical disassemblies with a sufficiently smart compiler. Works in SBCL.
23:38:01
makomo
i agree it's not very clear so i probably won't use it. i was wondering whether a clever trick like that is idiomatic or not.
23:40:49
aeth
Still identical disassembly in SBCL. In fact, all four functions (I called them foo, bar, foobar, and barfoo) have 100% identical disassemblies in SBCL.
23:43:33
aeth
for the lazy: (if x t nil) (and x t) (if x t) (when x t) (not (not x)) (not (null x)) (not (eq x nil))
23:44:28
_death
(let ((m (make-hash-table))) (setf (gethash nil m) nil) (defun bool (x) (values (gethash x m t))))
23:45:15
aeth
That's going to fool SBCL because you're using a mutable data structure and it's not that sophisticated... I think. Let's see
23:47:06
Fare
sjl: ASDF needs a new maintainer... but I don't know anyone paying for ASDF maintenance at the moment.
23:48:09
_death
aeth: (defun bool (x) (case x ((nil) nil) (t t))) seems to give slightly worse results
23:50:04
aeth
_death: I get identical results, as in 100% identical except "disassembly for BOOL" instead of "disassembly for FOO" and a different origin
23:55:56
jasom
(disassemble (lambda (x) (declare (optimize (speed 3)))(when x t))) is what you want, I think
23:57:00
mfiano
aeth, no regression: https://gist.github.com/mfiano/20b05bed9fe971de14085b89e13a9de6
23:58:46
aeth
definitely shorter. CMP MOV CMOVEQ MOV MOV CLC POP RET BREAK and 26 bytes with the disassemble lambda version
23:59:34
jasom
26 bytes for (disassemble (lambda (x) (declare (optimize (speed 3)))(if x t nil))) here
0:00:13
_death
35 bytes.. oh, I forgot that I also have (declaim (optimize (debug 3) (safety 3))) in .sbclrc
0:02:31
_death
it doesn't matter much anyway, since you'd likely also want to declaim that function inline
0:03:00
jasom
_death: I think we were using the disassembly of the lambda for a proxy of the inline code that would be generated
0:04:05
_death
jasom: I'm thinking about some peephole optimizer or something mutilating it into something better
0:06:22
aeth
one way to benchmark more directly would be to compare two functions, one that calls an inline version and one that calls a notinline version
0:36:11
_death
aeth: https://gist.github.com/death/665262a6585d68356095adc28c094f26#gistcomment-2305664 silly code for comparing functions :)
0:43:53
jasom
oh, if anybody has tips for getting SBCL to generate CMOV rather than CMP/JNE, let me know. I have a portable utf-8 decoder that is slower than SBCL's built-in only because of that difference.
0:56:49
jmercouris
well, you see the message, I'm getting really close to completing the GTK port, looking at your code has been very enlightening
0:57:59
jmercouris
AeroNotix: No, I just don't have a lot of energy in general, I sleep like 10 hours a day or so
0:58:22
AeroNotix
Just not a fan of GTK in all honesty. I think it's because of the heavy old style C naming conventions and (IMHO) crappy docs that continually put me off it
0:59:02
jmercouris
can one easily add and remove views from GTK without redrawing the whole display?
0:59:27
jmercouris
but I don't want to have to add all buffers beforehand to the view, it should be possible to add and rmove them right?
1:00:01
jmercouris
I was worried that GTK was going to be a huge pain, and it is because I'm developing in a VM, but programmatically speaking it is quite okay
1:00:06
AeroNotix
You can dynamically add new webkit views to anything really. I think there's a way to hide them from being drawn as well, but it's all long old memory
1:00:23
jmercouris
AeroNotix: Yeah, they can be hidden automagically, they must be told to be rendered
1:00:47
jmercouris
I guess it is not such a big deal if I have to add new webviews to some magic container, I'm just worried about removing them later
1:01:10
AeroNotix
Yes, I had issues with garbage collection and doing dynamic allocation of webkit views
1:01:50
jmercouris
like "prepare-to-close" where it collects system resources, and then some call to dealloc or whatever
1:01:54
AeroNotix
I don't recall now but I seem to remember coming across a more automatically generated set of bindings for webkit-2
1:02:09
jmercouris
yeah, joachim was talking about some generation tools for making the bindings actually
1:02:29
jmercouris
there was an issue opened, and when I emailed him, he mentioned it again, so it is probably a good path
1:03:01
jmercouris
yeah, he is quite busy, but if he can just give me some guidance, I might be able to pick it up
1:04:08
jmercouris
the implementation of the GTK stuff is opaque to nEXT via an API, so it can be improved REALLY easily
1:07:44
jmercouris
_death: didn't know it was a full help prompt and everything, useful to know as well, thank you
1:11:48
earl-ducaine
Hi Lisponians! I'm remembering that it's a bad idea to use defun in a non-toplevel form. But I'm not remember why or what I should use instead. Anyone have anything thoughts? CLHS doesn't seem to have anything to say about it directly.
1:12:36
pjb
earl-ducaine: you can use it, but if it's not in toplevel, then the compiler cannot notice that you defined a function. This is the main drawback.
1:13:04
Bike
but yeah, earl-ducaine, e.g. later code might not be aware that there was a function defined earlier so you get an undefined function warning, kind of thing.
1:13:06
pjb
(declaim (function foo)) (let ((x 0)) (defun foo () (incf x))) (defun g () (list (foo) (foo) (foo)))
1:13:51
Bike
because you don't always need or want functions to be globally accessible through names
1:14:32
jmercouris
I feel like it should be part of the defun spec that you can declare anonymous functions
1:16:55
Bike
Yes, the minimum functionality of defun is basically (defun foo (x) x) => (setf (fdefinition 'foo) (lambda (x) x))
1:17:05
earl-ducaine
Bike: it's a poor mans objects system, i.e. create the binding at run-time based on whether you're running in a Uinx env (CLX) or in an Mac env.
1:17:17
pjb
jmercouris: actually (defmacro defun (name lambda-list &body declarations-and-body) `(progn (setf (fdefinition ',name) (lambda ,lambda-list (block ,name ,@declarations-and-body))) (declaim (function ,name)) ',name))
1:18:44
jmercouris
I always envisioned defun as a special form for declaring a function, but now I see that it is for associating a lambda with a name
1:19:44
aeth
It's more obvious in Scheme, where (define (foo x) x) is just syntactic sugar over (define foo (lambda (x) x))
1:30:34
Bike
and while lambda isn't a special operator, the symbol LAMBDA has a special meaning to the FUNCTION special operator in a way that can be conceptualized as a kind of special operator.
1:31:41
dmiles
backquote would not have entered my mind had quote not been an been a special operator
1:42:13
jasom
man read-byte is poorly optimized on sbcl; slurping a stream with read-byte is slower than slurping a utf-8 stream with read-char...
1:46:10
earl-ducaine
It's been up for a while. (last April) But in case you haven't seen it, the old GigaMos k-machine emulator along with all the associated LMI branch Lisp Machine code has been posted on bitsavers
1:47:32
jasom
If anybody hasn't been able to figure out how to do X with clack, PRs and Feature requests for my tutorial are accepted here: https://github.com/jasom/clack-tutorial/blob/src/pages/getting-started-with-clack.org
1:47:53
jasom
(pretty version here: https://jasom.github.io/clack-tutorial/pages/getting-started-with-clack/)
1:50:51
jasom
There is zero good reason that I can think of for it to be a class, since there is an infinite variation in which keys might be present in it...
1:54:01
jasom
but yes a list of values with no structure is stupid, particularly since defstruct lets you define a tagged list of values...
1:57:41
jasom
where there is one value that you will almost always want, but a second value that you only sometimes want. Plus it avoids consing on most implementations
1:58:11
aeth
values is a nice way to write pure functions where you would otherwise use a very short list or vector that conses to do the same thing, evne if you need the 2nd, 3rd, etc., values.
1:58:55
aeth
Using it a lot will probably add an overhead of maybe one instruction, but it gives you pure functions for "free"
1:59:35
jasom
did they ever figure out a way to implement it efficiently in wasm? There was a tempest in a teapot about that a few years back...
1:59:49
aeth
(It's not really free, but afaik you pay the cost for efficient multiple return values whether you use them or not. But you do need to implement support for them at the compiler level.)
2:00:32
aeth
There are lots of cool things you can do in languages that C++ can't do... good luck getting those efficiently implemented in wasm.
2:03:20
mfiano
Can anyone tell me why uiop:safe-read-file-form coerces floats to doubles (d0 suffix), as compared to uiop:read-file-form which does not?
2:06:55
mfiano
Looks like it's binding *read-default-float-format* 'double-float, but why is it 'unsafe' not to?
2:11:56
mfiano
I just tracked down a bug that stems from this function coercing all my floats to doubles. Looks like I'll have to just safely read on my own. I just don't understand how not coercing is unsafe
2:13:37
aeth
if *read-default-float-format* is 'double-float, you can still get single-float from 1.0f0, 2.0f0, etc.
2:14:30
aeth
I never assume *read-default-float-format* because that has bitten me before, in source code!
2:14:44
Bike
there is no "verbatim". 1.0 can mean any one depending on how it's read. single-float is just the default binding.
2:15:01
Bike
perhaps you could petition fare or whoever mantains uiop to let you provide the float format yourself, though.
2:16:01
aeth
It's always single-float initially. http://www.lispworks.com/documentation/HyperSpec/Body/v_rd_def.htm
2:18:18
mfiano
Thanks. I guess it makes sense to change my machine-generated dsl data format over using my own reader function.
2:19:42
aeth
If I had to read numbers as single-float without the "f0" suffix, I'd probably do what they do in the example to make sure it's single-float and then read it, i.e. (let ((*read-default-float-format* 'single-float)) ...)
2:21:03
mfiano
It makes total sense to change the file data instead, since these files may be used by other developers too.
2:21:14
aeth
e.g. I turn off *read-eval* but I make it configurable just in case someone is using that feature for some reason.
2:21:54
mfiano
ie; unless i write a user api for parsing these files, rather than just provide them for users to do whatever, i should encode the data in an unambiguous method
2:26:31
Fare
Bike, discussed changing the *read-default-float-format* in 2014 or so, and the overwhelming reaction was that ASDF should stick to the standard.
2:27:29
mfiano
The question is, what would be the best way to write out 1.0f0 to a file, such that it is not read and then written as 1.0 ?
2:27:46
Fare
rpg, after it gets merged (or rejected), the document should be updated to reflect the current situation and current plans.
2:28:21
Fare
mfiano, bind *read-default-float-format* yourself inside a with-{safe,standard}-io-syntax
2:32:47
aeth
I tend to just write my own custom writer, though. It's hard to get the output just the way I want it.
2:33:37
aeth
Fare: If short-float is single-float, then it'll write as 1.0, not 1.0f0. It's probably safe to assume a separate single-float and double-float. Conforming implementations that don't do this will probably be broken by some dependency before they get to the unique code.
2:34:20
aeth
It's very easy for some niche Lisp to be broken by a dependency or a dependency's dependency.
2:36:15
aeth
As far as read and write not being portable... ime read tends to work more or less as I want it, but write is trickier because of where it decides to newline long s-expressions.
2:40:44
aeth
Often when I write a custom reader, I'll try to rely on the built-in read where I can get away with using it.
3:19:42
aeth
Fair point. I've mostly used read for things like configuration files and programming languages, where the user is essentially trusted.
3:27:51
jasom
aeth: almost all architectures introduced after 1990 support at least 3 return values with zero overhead (and 8 is not unusual) in hardware; there is no cost to the caller if it doesn't use them, and the cost to the callee is only an extra register store (to marke the RV count)
3:29:23
jasom
aeth: well Power, ARM and MIPS can each do at least 8 (though the common ABIs often don't define that many, it is 100% compatible to use all caller-save registers)
3:32:32
jasom
x86-64 ABI specifies 7 volatile registers, so 6 return values could be done cheaply; I'm not sure if sbcl does this though...
3:34:24
jasom
looks like SBCL on'y uses 4 of them for return values, and one is a count, so 4 will require stack access
3:59:15
cryptomarauder
mfiano: I am a string whore myself which may not work on some systems applications but for keeping the format good on something like 1.0f0 unaltered I throw it in a string like a do tortillas. Otherwise if it's not dealing with standardized definitions which would endure the data integrity in your output you just can't be sure in a portable way.
4:02:42
lildragon
Is there a good book/guide to learn (Common ?) Lisp that is straight to the point?
4:03:12
minion
lildragon: look at PCL: pcl-book: "Practical Common Lisp", an introduction to Common Lisp by Peter Seibel, available at http://www.gigamonkeys.com/book/ and in dead-tree form from Apress (as of 11 April 2005).
4:03:22
lildragon
And Practical Common Lisp is too verbose. I don't care about your dad, I don't need you to repeat the same idea five times for me to learn how a list works.
4:03:32
parjanya
what’s the smart way of getting just some values that get-decoded-time outputs? if I use multiple-value-bind it gives me a warning if I don’t use all the variables... I thought of using multiple-value-list and then selecting just the parts I want, but isn’t there a better way? something like (grab (0 2 4) (get-decoded-time)) to output only the first, the third and the fifth values
4:03:48
lildragon
mfiano: Thanks, see my problem with the book, two chapters in and I am already bored. :P
4:04:21
mfiano
lildragon: That's ok, because the book is very short, and you won't find another like it.
4:05:22
lildragon
"A single record, however, does not a database make. You need some larger construct to hold the records. Again, for simplicity's sake, a list seems like a good choice."
4:05:27
mfiano
You could start with Common Lisp Recipes, which is a bunch of concise "recipes", but it is designed to be a companion to PCL.
4:12:52
parjanya
beach: thanks! is this decent, (list (nth-value 5 (get-decoded-time)) (nth-value 4 (get-decoded-time)) (nth-value 3 (get-decoded-time))), or would be better to collect the values in a list and then extracting what I want from it?
4:14:22
aeth
And for the things you don't use, just do this so the compiler doesn't warn you: (declare (ignore foo bar baz))
4:18:33
pfdietz
Might use it for variables that will just be used in, say, debugging or logging statements that may or not actually be compiled (due to #-/#+ or macros).
4:43:29
lildragon
beach: It looks really good in terms of the content, the user interface is monstrosity though.
4:45:18
lildragon
beach: Couple of hours into finally committing to learn Lisp I see a common pattern across everything lisp related, there is a strong commitment in the early ages of computer human interaction (I avoid the term UX because that is too modern). :P
5:25:03
lildragon
beach: I think it is not that bad after all, thanks for reminding me that it is not that long.
7:16:38
cryptomarauder
Nice chat. You guys never quit being eager to help. I am such a lurker but I get so much with virtually no snark. Golden lol
9:59:24
phoe
On SBCL: (trace (setf config)) ;;=> WARNING: (SETF CONFIG) is not a valid function name, not tracing.
10:06:18
Shinmera
It's been a while since I implemented it, but I remember discussing the available options at the time and coming to the begrudging conclusion that a SETF "pre-processor" is the best way to go
10:06:55
Shinmera
It was something about the SETF facility not giving you access to a variable amount of multiple values, which I needed.
10:07:06
phoe
AFAIK needs to be a custom one because of how Qtools hacks around the reader - only the symbols requested by the client code are generated, et cetera.
10:09:33
Shinmera
Essentially (setf (q+:size foo) (values 400 500)) is read as (setf (q+ set-size foo) (values 400 500)), so in that case it needs two values, but let's say (setf (q+:rect foo) (values a b c d)) needs four and so forth.
10:10:35
Shinmera
Anyhoot, the SETF wrapper turns that into (q+ set-size foo 400 500) or whatever else depending on the VALUES form.
10:11:34
Shinmera
You might think I could just specify like a hundred values or something expecting that no function call will ever need that many, but then you also never get any information from SETF about which values were actually passed and which weren't, so you can't compose the proper call.