freenode/#lisp - IRC Chatlog
Search
20:18:51
oni-on-ion
prolog i set right next to lisp for macro, not sure about scheme and hygenia, but julia right below it because im still a newbie with it
20:22:36
jasom
hmm; python lets you manipualte the AST, but I don't know that it makes it homoiconic; we may be getting OT at this point going too-far down the Julia path
20:22:45
oni-on-ion
although there is one thing, if you have a macro 'john' and want to call it, @john is how. i forget the reasoning behind this but i think it is just syntax sugar. not sure where CL stores its own macros; in the function slot ?
20:23:55
jasom
In a homoiconic language, the primary representation of programs is also a data structure in a primitive type of the language itself. <-- obviously this doesn't just mean AST, otherwise all self-hosting languagese would be homoiconic (assuming the compiler or interpreter parses to an AST at some point)
20:26:19
oni-on-ion
i am really not sure about julia macros. have to play with it more, the manual is too dry
20:26:27
jasom
oni-on-ion: all lisps can use symbols for many things; lisp-1 v lisp-2 is just a question of if the function-call position is separate from the value
20:28:14
jasom
lisp-1 v lisp-2 is a question of (X X) <- does X represent the same thing when this is evaluated.
20:29:49
oni-on-ion
that is the second thing i like about scheme. which julia was written in (chez) but anyhow, homoiconicity to me is extremely important for 'real' macros. and to 'flip the switch' with quote/unquote
20:31:08
jasom
and of course if you make a hash table that is keyed with symbols, you've added a new namespace.
20:31:29
oni-on-ion
jasom: and also very important for the ability for anaphoric macros =) as nickname reminds me
20:32:21
oni-on-ion
change package, change namespace. wouldnt that count for 'how many namespaces' there are
20:33:25
anamorphic
From page 836 (apparently, I don't have my copy in front of me) of PAIP he says Common Lisp has 7 namespaces
20:33:29
jasom
oni-on-ion: that's because symbols are string-designators, and defpackage/in-package take string designators
20:36:48
jasom
oni-on-ion: don't forget that symbols are upcased so you need to do e.g. (in-package "CL-USER")
20:38:14
jasom
oni-on-ion: if packages were named as symbols, you might see code written like this https://github.com/jasom/spm-reader/blob/master/spm-example.lisp (I wrote a proof-of-concept reader macro that uses symbols to name packages, with the keyword package being the root namespace)
20:39:30
oni-on-ion
whoa that is trippy, is this file copied twice ? if i page up/down in emacs it looks the same.
20:40:15
oni-on-ion
i see 4 of the same thing, my dyslexia is acting up and im starting to see moire patterns
20:40:44
jasom
oh, the first line of each are: json:encode, clj:encode-json, :yason:encode, :cl-json:encode-json
20:43:19
_death
I think he wants a macro to "abstract" the 4 forms.. not realizing it would serve no purpose but obfuscation
20:44:52
aeth
oni-on-ion, jasom, etc.: You can't do "FOO-BAR" and be fully portable. If you use literal strings you have to generate them at read time with #.(symbol-name '#:foo-bar) to get "FOO-BAR"
20:47:23
_death
aeth: someone who changes the readtable case and expects things to work is deluding himself
20:48:11
aeth
_death: As long as the readtable case doesn't change *multiple* times during the execution of the program #.(symbol-name '#:foo-bar) will work.
20:49:42
jasom
aeth: if the readtable case has been changed, then #.(symbol-name '#:cl-user) will not work.
20:49:49
aeth
oni-on-ion: I use it everywhere in my code, e.g. if I wanted to prefix foo- in a macro I would use #.(symbol-name '#:foo-)
20:50:02
jasom
if it's e.g. case-preserving then it will look for "cl-user" which is not required to exist, while "CL-USER" *is* required to exist.
20:50:41
jasom
I'm fine with #. for such short uses, but in this case it's flat out worse than using a string, as a string will always be right.
20:52:13
jasom
also (in-package #.(symbol-name '#:foo)) is going to be identical to (in-package '#:foo) since there is an implicit call to symbol-name (probably via cl:string) in the in-package macro
20:52:31
aeth
_death: There are two acceptable uses for #. imo. symbol-name (like above) and to get a constant number in an unquoted type specifier like (let ((bar 42)) (check-type bar (integer 0 #.(isqrt most-positive-fixnum))) bar)
20:53:15
_death
aeth: in most-positive-fixnum that may work.. in your own constants that may not depending on when you define them
20:54:06
aeth
_death: Just wrap the constant in eval-when and that fixes it, at least for CCL, which does complain about such things. But almost all of the time it will be something like most-positive-fixnum
20:54:17
oni-on-ion
shift 3 dot shift 9 symbol-name quote shift 3 shift semicolon foo shift 0 shift 0 ..... thats a lot of dang-ed typing !!
20:55:55
aeth
_death: something like this: (defun fixnum-square (number) (check-type number (integer 0 #.(isqrt most-positive-fixnum))) (expt number 2))
20:56:22
jasom
aeth: I'm also trying to figure out why you are using #. for the symbol-name; symbol-name 'foo will never change since foo is read in once; is it just an optimization?
20:59:40
aeth
jasom: I've been doing this for a while now but I believe that the reasoning was to get the performance of "FOO" but with more reliability. I don't think it would make a difference in SBCL, though.
20:59:58
aeth
At the very least SBCL seems to turn (defun foo () (symbol-name '#:bar)) into a function that constantly returns "BAR"
21:05:41
aeth
Why specify a boundary? All that's required is to prove to the compiler that is remains a fixnum so the arithmetic stays inline. The actual bounds are your memory and patience.
21:06:01
aeth
It would be impossible to leave fixnum with that algorithm, though, because you would certainly run out of memory.
21:09:15
younder
The marshaling and representation stands the potential of being a major bottleneck.
21:15:04
aeth
No, what I actually care about is generating the primes as quickly as possible. I would rather have every implementation generate as many as it is capable of doing efficiently than artificially limit 64-bit SBCL or create a misleadingly high bound for the rest.
21:15:55
aeth
I can use fixnum, I can create something that is efficiently only in 64-bit SBCL, or I can artifically limit what 64-bit SBCL is capable of doing. (This is the case because 64-bit SBCL has the largest fixnum.)
21:16:02
_death
but, if you have an array of things, then you don't care about fixnum, but a subtype of it
21:19:39
aeth
Don't run a high-performance prime sieve on a 16-bit CL with the standards-specified 16-bit-friendly absolute minimums for everything, then.
21:22:00
aeth
If you use double-floats in a computationally intensive way, CLISP exists to make your life hell.
21:25:07
aeth
In general, though, in my personal experiences, code involving numbers will run almost instantly in SBCL, may run almost as fast in SBCL or have unexpected slowdowns in CCL, will sometimes be much slower in ECL, and will usually be basically unusable in CLISP.
21:28:26
aeth
Hypothetical 16-bit everything-is-the-minimum-in-hyperspec Common Lisp would be even worse than CLISP here. And I'm pretty sure I have some docstrings longer than 1024, which would also not be conforming.
21:29:51
aeth
Okay, the longest docstring I can think of in my code is 749, but it will probably pass 1024 at some point as more details are added. That will no longer be fully portable. Will I limit myself to 1024 character docstrings? Absolutely not.
21:30:08
_death
so my approach would be to give bounds, and if an implementation can't generate efficient code for that bound, so be it, don't use them if you expect something fast, but at least they won't break..
21:33:04
aeth
_death: So your approach would either (1) make code that's only fast in SBCL or (2) artificially limit SBCL so you can at least support CCL and maybe a few others similarly. Depending on whether your bounds are SBCL-friendly or CCL/etc.-friendly.
21:33:51
aeth
_death: If you want #2 you can write a trivial inline function with a lower CHECK-TYPE.
21:35:26
aeth
anamorphic: The standard permits 16-bit implementations (otherwise it wouldn't have ridiculously low minimums like 1024 for arrays, which include strings)
21:36:38
aeth
They were probably slow, barely usable, not very useful, and a subset of the language. Almost certainly made for the old CL, pre-CLOS.
21:39:54
_death
but again, in this specific case you actually care about array length, not about fixnum.. even if you don't have explicit bounds to specify, fixnum is often a poor candidate
21:45:11
aeth
_death: This is low level code that would ideally produce efficient code in any reasonable implementation. If you want a constant interface so (foo n) will work for any constant value n in a program, wrap it with a trivial inline function that establishes a second set of bounds. The inner function has bounds that produces efficient code (keeping it fixnum).
21:46:02
aeth
_death: You cannot go the other way around and make an efficient function from one that either artificially limits SBCL or produces code that's only efficient on SBCL (since intermediate values might become bignum in the other implementations).
21:47:02
aeth
_death: It's possible in some strange cases, the part that keeps it fixnum for efficient fixnum arithmetic won't line up so one of the arrays will be created too large. This isn't C, though. You'll get an error there.
21:47:39
aeth
If for some reason that shows up in an implementation (unlikely), then that's the time to spend the time addressing it.
21:51:08
aeth
I don't even check for bounds with my float functions in general because that would greatly slow things down because there are too many of them (think things like vec+). I do find and document them, though.
21:52:05
aeth
A user who cares could wrap the functions or, more ideally, wrap a function that uses several of these and derive the final safe input bounds (and it's actually unnecessary here because you'll get an overflow/etc. error at some point unless you turn off float traps... and the documented bounds just document what causes *these*)
21:53:35
aeth
But in general, when I work with integers they're either (1) trivial enough that I'll just inline them and bignums are OK if that's what you want or (2) nontrivial enough that fixnums or (un)signed bytes of size 32 or 64 are imo the right thing. Usually the latter two these days, actually.
21:58:23
_death
if you generate two versions of code, for fixnums and bignums, that's good and non-fragile.. that's how CL works..
21:58:24
aeth
There is one place where I use fixnums very incorrectly, though. I use them as the type of a vector index. Afaik array-dimension-limit should be the bound instead, which in SBCL is off by 2 (in practice, no difference since you'll run out of memory before getting to those 2). So the type alexandria:array-index
22:07:15
aeth
Hmm, in CCL a fixnum is about 16x larger than array-dimension-limit... but again, you'll run out of memory first because array-dimension-limit, assuming a *bit* array, would make that array be about 8 PiB or 9 PB
22:08:21
aeth
(And, for semi-completeness, ECL's most-positive-fixnum is its array-dimension-limit.)
22:18:25
aeth
This seems to be fairly common: (let ((foos #(1 2 3))) (loop :for foo :across foos :for i :of-type alexandria:array-index :from 0 :do (format t "~D ~S~%" i foo)))
22:18:53
aeth
Of course it'll probably not have a type, or it will incorrectly have the type fixnum if there is one... and it probably won't be optimized
22:21:11
aeth
Yes, but it could be optimized. Without the type declaration, the compiler will not know enough to realize that i cannot be a bignum, and with the type declaration of array-index or fixnum, there will be a type check every iteration.
22:21:53
aeth
The type declaration is probably the way to go if you're doing something fancier with it... but the type declaration shouldn't be necessary for it to be known that it's not a bignum.
22:23:06
aeth
(It's probably actually better to use fixnum here than array-index because the fixnum type check might be faster.)
22:24:47
_death
I would write this as (dotimes (i (length foos)) (format t "~D ~S~%" i (aref foos i))) btw
22:25:36
aeth
_death: It's hard to come up with a trivial LOOP that demonstrates something about LOOP without the LOOP itself being unnecessary.
22:28:47
aeth
Conditional collect/append is probably the only place where a somewhat trivial LOOP is actually the nicest way to write it.
22:29:38
_death
a "smart enough compiler" could deduce that I is of type array index.. loop or no loop, but of course you don't want to rely on a mythical compiler if performance is important
22:32:22
aeth
_death: But how would you work around something like that other than turning safety off (assuming that even turns safety off)? I guess the way in the loop would be to do :from 0 :to (length foos) except that might now do two end condition checks when one will do
22:33:20
aeth
The equivalent map nil with an outer i variable will behave very similarly, including potentially having optimized access for iterating across vectors. dotimes might actually be the most efficient here, but only when the bounds of foos are known.
22:33:56
aeth
_death: I guess my point is only the sufficiently smart compiler will have this optimized at all, so you would have to rely on the "mythical compiler" for maximum performance here.
22:38:03
aeth
Compilers already include AI. For example, style-warnings are 'automated code review', which should be a pretty hot field of AI, right?
22:42:47
_death
quite an interesting page from historical perspective https://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node91.html
23:08:42
jcowan
Compilers are "automatic programming", one of the first AI fields. In fact, so are assemblers.
23:48:55
jasom
has anyone tried writing an ASDF plugin that lets you specify a particular lisp file should be loaded with a particular read-table?
23:50:42
jasom
It seems obvious enough that *someone* must have looked into it. I was just mulling over racket's language modules and considering how I might implement something similar in CL.
23:53:32
scymtym
jasom: fare's syntax-control (i think that was the name) branch would probably be good starting point
23:54:41
jasom
scymtym: that branch had different purposes; I was thinking of just defining a new component type
23:55:39
jcowan
IMO TRT is to allow specifying the version of read that the compiler/loader/eval uses
0:04:47
aeth
jcowan: That example actually survived in the HyperSpec. http://www.lispworks.com/documentation/HyperSpec/Body/m_prog_.htm
0:44:03
no-defun-allowed
I wouldn't trust shit on codeproject tbh. People who call themselves coders are probably losers.
0:47:13
aeth
LdBeth: There's an argument there, it's just that the author doesn't know Lisp. e.g. ":type float" is probably not what you'd ever want to use since it's basically (or short-float single-float double-float long-float) and probably won't get you anything over ":type number" (or maybe even ":type T"!). If you're going to use a float in a struct, you probably want a specific type of float. The author probably meant "single-float" and was think
0:50:22
aeth
No surprise that the author primarily knows Clojure. Clojurists seem to have the wrong idea of how Common Lisp works but seem to think that they know how Common Lisp works.
0:52:28
aeth
And, yes, the author has no mention of specialized arrays as an option (or multiple return values!), which is strange.
0:53:52
aeth
(I didn't mean to insult Clojure programmers, although in hindsight I see how it could seem this way... let me just put it differently: I know I don't know Clojure, so I don't blog about Clojure's weaknesses. Plenty of Clojurists who don't know CL seem to blog about CL's weaknesses.)
0:54:43
LdBeth
aeth: I didn't noticed the type thing. But I mean, tuple is more close to vector and any saner (Common) Lisper would use vector ranther than list for it
0:55:44
aeth
It's pretty strange that the author argues that Python, Ruby, and JavaScript are more popular than Lisp because Common Lispers don't use statically typed structs very often.
0:57:59
aeth
LdBeth: There is a point that could be made in a similar essay. There is a long tradition in Lisp of people using lists when they are completely and totally inappropriate. e.g. 2.2.4 in the famous Worse is Better essay. http://dreamsongs.com/WIB.html
1:01:10
LdBeth
aeth: It is sometimes understandable because the writer wants it to be comaptble with other dialects, especially for someone had used MacLisp or InterLisp for a while
1:07:20
aeth
This means that he tested it in something other than SBCL, one which doesn't do type-checking in the struct constructor. I'm betting CLISP.
1:13:56
jcowan
I'd say he thinks that because he declared the slots to be floats, he assumes the constructor will cast its arguments to floats
1:14:33
aeth
jcowan: But then he prints it out, which should then make that assumption very clearly disproven
1:15:44
oni-on-ion
are they ever out of order? i wouldnt assume any of them optional given the name 'vec3d'
1:16:52
aeth
oni-on-ion: There are two common approaches for this sort of thing (vec3s). One is to use a specialized array, and the other is to use defstruct to define a specialized array rather than to define a struct. The result is basically the same, except the latter automatically creates accessors (but not a type, which is strange because defstruct normally defines a type and the type can still be useful if it's a specialized array)
1:18:23
aeth
oni-on-ion: I use a macro to make my own specialized array instead of using defstruct. I call it define-array-and-type: https://gitlab.com/zombie-raptor/zombie-raptor/blob/b90f23cf6168f892fce8fd980649eaf882662acb/util/array.lisp#L55-67
1:19:04
aeth
e.g. (define-array-and-type vec3 (single-float '(3)) (x y z)) and then (vec3 1f0 2f0 3f0)
1:19:23
jcowan
Tuples make sense in the context of destructuring-bind, but without such things, not so much
1:19:57
jcowan
The point of a tuple is that it is both heterogeneously typed (in the sense that every object in it has a known type) and indexable.
1:23:43
aeth
You could, if you assume tuples to be immutable, use a macro on top of defstruct to build tuples for CL since defstruct also has :read-only for each slot (just set every slot to read-only). Of course, the compiler won't optimize it because it's not a common idiom.
1:23:47
jcowan
I have been seeing in my current job how people who have never used dynamically typed languages are actually afraid of code written in them, and I think this is an example.
1:27:21
cgay
I'm not that familiar with defstruct. Can you really use it to implement tuples, which have unbounded length?
1:30:00
jcowan
Terminology is loose, but most people talk about tuples as being of a particular length: there are pairs, triples, quadruples, ....
1:30:10
aeth
cgay: Hmm... If you need unbounded length tuples, you could create the tuple on demand with deftuple if it doesn't currently exist.
1:30:59
jcowan
The result is nominally rather than structurally typed, but that really is a fine detail.
1:31:25
jcowan
"tuple" doesn't necessarily mean "immutable tuple"; in Python it does, but not everywhere.
1:34:01
jcowan
in Maclisp hunks were mutable in content, immutable in size, and had to be a power of 2.
1:34:10
cgay
Interesting because just yesterday I was noticing that in Dylan <stretchy-collection> is not a subclass of <immutable-collection>.
1:35:44
cgay
Interesting because just yesterday I was noticing that in Dylan <stretchy-collection> is not a subclass of <mutable-collection>.
2:24:18
HighMemoryDaemon
Does most people's Lisp programming session (At least Emacs users) start by doing the follow? : Open Emacs, Open your project's ASD file, M-x slime, C-c C-c l (load file to Slime), (cl:quickload 'my-project)
2:36:22
HighMemoryDaemon
oni-on-ion: You don't need to 'C-c C-c l' the ASD file if you are in the folder that contains all your projects?
2:41:53
HighMemoryDaemon
Very nice, so changing directories with eshell wouldn't even matter since QuickLisp looks in the local-projects folder by default.
3:22:55
drmeister
I gave two talks in the last two days in the Bay Area with “Common Lisp” in the title.
3:25:09
drmeister
I think I’ll use the term “flexible compiler for a compiled dynamic language” in the future.
3:33:53
no-defun-allowed
i don't think FOSS writers do much CUDA, it's a proprietary language and only useful on nvidia machines unfortunately
3:39:36
no-defun-allowed
I am looking to make cl-vep use GPGPU, but it'll probably be in OpenCL/oclcl. The interfaces for oclcl and cl-cuda are fairly similar so it could be possible to port it anyway.
3:51:34
no-defun-allowed
funny you bring it up, beach and i have been poking at (presumably) amdgpu crashing and halting our computers
4:05:33
no-defun-allowed
he's not working on it, but we've both had problems with it freezing recently
4:06:16
no-defun-allowed
nothing happens before it freezes, but then it becomes unusable and doesn't respond to the usual TTY changes, SysRq keys, etc
4:06:42
no-defun-allowed
my motherboard has lights which indicate when something went terribly wrong, and the GPU one lights up when that happens though