<markasoftware>
are (declare)'d argument types always enforced?
libertyprime has quit [Ping timeout: 256 seconds]
libertyprime has joined #lisp
<mfiano>
Implementation must only obey the declaration identifiers NOTINLINE, SPECIAL, and conform to some OPTIMIZE/SAFETY rules
<aeth>
This is why I'm going to eventually put in the work to change the default behavior of my DEFINE-FUNCTION macro to be implementation-specific: i.e. DECLARE when it works (* unfortunately in SBCL with (safety 0) imo it doesn't "work" and I don't think there's a way to detect that) and CHECK-TYPE when DECLARE is ignored
<aeth>
But short of putting in too much effort writing a macro that does both DECLARE and CHECK-TYPE, if you must have it checked as a priority use CHECK-TYPE and assume DECLARE is for optional performance.
Necktwi has quit [Ping timeout: 246 seconds]
edgar-rft has joined #lisp
<jackdaniel>
sbcl adds declare /type/ and check-type are independent spec wise. sbcl indeed usually adds check-type, but that's its custom safety policy
<aeth>
SBCL's DECLARE (when not (safety 0)) has afaik two distinctions from CHECK-TYPE. (1) you cannot provide an object at runtime that satisfies the type if you give an object of the wrong type, which probably speeds things up a tiny bit; and, (2) it gives information for type inference and a bit of static checking
<aeth>
(with CHECK-TYPE, it infers that the object in the variable before that point is of type T since it can be anything and the user can just provide something of the correct type after that point)
<aeth>
It calls the CHECK-TYPE error a SIMPLE-TYPE-ERROR and the DECLARE error a TYPE-ERROR.
gravicappa has quit [Ping timeout: 264 seconds]
Necktwi has joined #lisp
<aeth>
It's a bit confusing, but beyond this, SBCL internally distinguishes between an inferred type and a declared type, which can differ. The only place where this is really exposed in a convenient way is in SLIME's debugger, but there are probably some internal functions for that.
Oladon has quit [Quit: Leaving.]
<aeth>
Oh, and it also does the DECLARE type check at a different point in the function, before the output of the standard DISASSEMBLE, which you can only see with sb-disassem:disassemble-code-component.
<aeth>
This is its typecheck for LIST when doing CAR... notice how it's only in the second disassemble:
<aeth>
(format t "Standard disassemble of CAR~%~%") (disassemble #'car) (format t "~%Full disassemble of CAR~%~%") (sb-disassem:disassemble-code-component #'car)
pve has joined #lisp
yitzi_ has joined #lisp
edgar-rft has quit [Quit: Leaving]
shifty has quit [Ping timeout: 240 seconds]
shifty has joined #lisp
yitzi has quit [Ping timeout: 256 seconds]
yitzi_ is now known as yitzi
vutral has quit [Quit: Connection closed for inactivity]
red-dot has quit [Remote host closed the connection]
<phoe>
> and I don't think there's a way to detect that
<phoe>
aeth: (sb-ext:restrict-compiler-policy) and check the output
shifty has quit [Ping timeout: 265 seconds]
<aeth>
great
shifty has joined #lisp
<aeth>
I wonder if inserting CHECK-TYPES for (safety 0) and slowing down code would be what users want, though.
<aeth>
(I think I'd also have to parse DECLARE to check for OPTIMIZE, but that's easy)
<aeth>
Unrelated, but I found a small bug in my DEFINE-FUNCTION while writing a bunch of simple REPL cases because of this conversation, which I guess is one of the reasons why I don't recommend anyone should use it yet. There's a lot of surface area to cover.
peterhil has quit [Ping timeout: 256 seconds]
jonatack has joined #lisp
<phoe>
aeth: I wouldn't expect typechecks on safety 0
<phoe>
if I explicitly tell the compiler to use no safety, then I'd expect the compiler to use no safety
shifty has quit [Ping timeout: 264 seconds]
shifty has joined #lisp
<beach>
phoe: That's a strange thing to want in itself, though, don't you think?
<aeth>
phoe: The problem is that SBCL's (safety 0) is essentially semantically broken and is even less safe than C. It removes runtime checks like a lot of languages can do, as expected, but it also removes static checking that the compiler can do, making bugs way easier to write.
<aeth>
There are very few reasons to use it, and those can all be inside of LOCALLY, not done globally or per-function.
hendursaga has joined #lisp
<aeth>
But, I mean, if that's what they want, then I guess I shouldn't undermine that in a macro by adding CHECK-TYPEs.
hendursa1 has quit [Ping timeout: 240 seconds]
<aeth>
(Okay, the reason to use it globally is benchmarks, I guess, but it's not a useful benchmark mode if the only acceptable time to run it is in benchmarks.)
gaqwas has joined #lisp
gaqwas has joined #lisp
gaqwas has quit [Changing host]
shifty has quit [Ping timeout: 240 seconds]
shifty has joined #lisp
<phoe>
beach: sure, but that's not the part that I want to discuss here
space_otter has quit [Remote host closed the connection]
akoana has left #lisp [#lisp]
Bourne has quit [Ping timeout: 240 seconds]
MMMNNNO has joined #lisp
jonatack has quit [Ping timeout: 256 seconds]
MMMNNNO has left #lisp [#lisp]
gioyik has quit [Quit: WeeChat 2.9]
peterhil has joined #lisp
igemnace has joined #lisp
bhartrihari has left #lisp ["Disconnected: Replaced by new connection"]
Lord_of_Life has quit [Read error: Connection reset by peer]
<jackdaniel>
for those who are interested in ecl history, the graph of inheritance has changed - apparently ECL is a descendant of DELPHI Common Lisp (the history chapter is updated)
Lord_of_Life has joined #lisp
__jrjsmrtn__ has quit [Ping timeout: 264 seconds]
<gendl>
jackdaniel: history chapter? Is there a book going on that i've missed? (I don't keep up in this channel enough..)
mankaev has quit [Ping timeout: 256 seconds]
__jrjsmrtn__ has joined #lisp
<jackdaniel>
gendl: ECL's manual has a chapter "History", in this pull request I've incorporated some information kindly provided by professor Attardi
<gendl>
ah.
<jackdaniel>
(ECL history dates back to 1984 when KCL was developed)
Bike has joined #lisp
Lord_of_Life_ has joined #lisp
Lord_of_Life has quit [Read error: Connection reset by peer]
Lord_of_Life_ is now known as Lord_of_Life
<phoe>
jackdaniel: nice!
contrapunctus has left #lisp ["Disconnected: Replaced by new connection"]
bhartrihari has left #lisp ["Disconnected: Replaced by new connection"]
contrapunctus has joined #lisp
bhartrihari has joined #lisp
_whitelogger has joined #lisp
rippa has joined #lisp
ahungry has joined #lisp
vutral has joined #lisp
renzhi has joined #lisp
dra has quit [Remote host closed the connection]
mason has joined #lisp
yitzi has joined #lisp
rpg has joined #lisp
gaqwas has quit [Remote host closed the connection]
sjl_ has joined #lisp
Cymew has quit [Ping timeout: 265 seconds]
<jackdaniel>
sjl: a fix for the loop dbind is waiting for the review
yitzi has quit [Quit: yitzi]
<sjl_>
Interesting. That doesn't break anything else? Any why do you need it after every sublist? Won't a single &optional at the beginning do the same thing?
<sjl_>
Oh, no, I see. by sublist you mean tree
<sjl_>
I was thinking it was going to do (&optional x &optional y &optional z). Haven't had coffee yet.
bsd4me has joined #lisp
mankaev has joined #lisp
contrapunctus has left #lisp ["Disconnected: closed"]
contrapunctus has joined #lisp
ghard has quit [Remote host closed the connection]
CodeSpelunker has quit [Ping timeout: 256 seconds]
gaqwas has joined #lisp
oxum has quit [Ping timeout: 256 seconds]
gaqwas has quit [Remote host closed the connection]
jw4 has quit [Read error: Connection reset by peer]
jw4 has joined #lisp
oxum has joined #lisp
jw4 has quit [Read error: Connection reset by peer]
jw4 has joined #lisp
oxum has quit [Ping timeout: 240 seconds]
nullman has quit [Quit: leaving]
nullman has joined #lisp
gaqwas has joined #lisp
jonatack has quit [Ping timeout: 272 seconds]
jonatack has joined #lisp
<aeth>
phoe: To be fair, anything that prints to *standard-output* can print to `(with-output-to-string (*standard-output*`... and be grepped with cl-ppcre, so while not ideal, it technically provides a "Lisp value"
<aeth>
(well, I guess not *g*repped.)
q3d has joined #lisp
<phoe>
aeth: yes, but it's vomit-inducing
<aeth>
agreed, it's just that this channel likes to be really technical
<aeth>
I think I'd call it a "fragile value" or something if it's in a string. Yeah, you can get it, but it is even less protected from breaking than normal implementation internals.
<aeth>
(a string or a stream, which are essentially equivalent if you want the data since you can turn one into the other)
<aeth>
(to be really technical, equivalent in this particular use case... obviously you can e.g. have an interactive stream or something like that)
Bit_MCP has joined #lisp
Bit_MCP has quit [Remote host closed the connection]
oxum has joined #lisp
gaqwas has quit [Ping timeout: 256 seconds]
ghard has quit [Ping timeout: 260 seconds]
MichaelRaskin has quit [Ping timeout: 260 seconds]
Lycurgus has quit [Remote host closed the connection]
mindCrime has joined #lisp
theseb has joined #lisp
ahungry has quit [Ping timeout: 256 seconds]
oxum has joined #lisp
ahungry has joined #lisp
kaftejiman has joined #lisp
shifty has quit [Ping timeout: 256 seconds]
shifty has joined #lisp
<ralt>
hm
<ralt>
it is probably a dumb question, but how do you set bitflags? I have 16 bits where I want to set some bit flags, and having to have each bit flag being e.g. #*0000000000000001 sounds a bit... wasteful
<ralt>
I just find the syntax to write a flag a bit cumbersome
<ralt>
if not error-prone
gravicappa has quit [Ping timeout: 246 seconds]
<ralt>
like, one of my flags is #*0000000000000001, so I can run (bit-ior ... my-flag), but is there a better way to write my-flag then (defvar my-flag #*0000.....1)?
<ralt>
s/then/than/
orivej has joined #lisp
CodeSpelunker2 has quit [Quit: CodeSpelunker2]
<ralt>
ok, a way that is just as verbose but at least not error-prone (because I get an error if the number of elements don't match) is `(make-array 16 :element-type 'bit :initial-contents '(0 0 0 0 ..... 1))`
<ralt>
> There are 15 elements in the :INITIAL-CONTENTS, but the vector length is 16.
<ralt>
if the elements don't match ^
<ralt>
so that's already better
<phoe>
ummmm
<phoe>
I'd make a bit-array of all zeroes and then just SETF the proper AREF
<phoe>
optionally with the use of a helper function
<phoe>
or, even better - I'd use an unsigned-byte instead of a bit array
<phoe>
and then go #.(ash 1 N)
<ralt>
I'd have to convert the unsigned-byte array into a bit array in order to run BIT-IOR on it
<phoe>
;; well, for relatively small integers, at least
oxum has quit [Ping timeout: 240 seconds]
lucasb has joined #lisp
ahungry has quit [Remote host closed the connection]
shifty has quit [Ping timeout: 246 seconds]
shifty has joined #lisp
random-nick has quit [Ping timeout: 246 seconds]
duuqnd has quit [Remote host closed the connection]
random-nick has joined #lisp
<edgar-rft>
Does anybody here know some historical reference *why* bit-vectors were introduced in Common Lisp? I learned Assembly as my first programming language and until today I'm using fixnums instead of bit-vectors. Somehow it appears to me as if I haven't understood what bit-vectors are good for at all. But maybe that't because I'm particularly stupid. Anybody knows some historical background?
<fwoaroof[m]>
I'd generally rather access bits by position than try to get the math right
<fwoaroof[m]>
The math isn't hard, it's just doesn't really express what you're trying to do
<_death>
they pre-date Common Lisp.. in some scenarios they may be convenient because they are sequences, so sequence functions are applicable.. they also have an identity and are mutable
eric[m]5 has joined #lisp
telior has quit [Remote host closed the connection]
kaftejiman has quit [Remote host closed the connection]
<edgar-rft>
yes, I know, bit-vectors are not only a Common Lisp thing, but (logior #b00000001 #bXXXXXXXX) reads *much* easier to me than all that back-and-forth conversion hassle above.
<_death>
their type makes clear their use, and they are printed in a way that can be convenient to the programmer
<fe[nl]ix>
edgar-rft: often you don't really care about representation, whether the index 0 is the most or least significant
<fe[nl]ix>
as long as the implementation ensures a compact representation
<edgar-rft>
I agree that making them distinguishable from fixnums *is* an advantage. I'm not against bit-vectors (like I'm not against gravity) but I try to understand their advantage in practical code.
<aeth>
You use bit vectors when there's a clear boolean true/false (although you have to wrap it to turn it into 1/0 instead of using t/nil) for very long sequences
<aeth>
One example would be a prime sieve (possibly prime or definitely not prime), where you really are only limited by memory.
<fe[nl]ix>
imagine you need to keep track of 20k flags
<aeth>
Another example would be if you're organizing your data (probably in the KBs) into multiple parallel arrays that you iterate over simultaneously and you only need one bit of data for something.
<fe[nl]ix>
maybe for some sort of cache
<fe[nl]ix>
you don't want to implement the bit-fiddling on your own
<fe[nl]ix>
it's just a waste of time
<_death>
I don't know that back-and-forth conversion is necessary.. for example I have some classifier code that takes a bit-vector for input (the number of bits is known at construction time and can be large).. I could've chosen to take an integer instead, but that would be a hassle
* edgar-rft
already has problems with imaining 20k flags :-)
<aeth>
Then you iterate over active? and unless (zerop (aref (active? foo) i)) you do something with (aref (foos foo) i)
<aeth>
This is much simpler than having an array of, say, (unsigned-byte 64)s and manually mapping a bit in that array to the index of the foos
<fe[nl]ix>
edgar-rft: 20k is only 80MB worth of 4k blocks (e.g. for a file-system)
<aeth>
(And it's also simpler and safer, but more memory wasteful, than having some kind of invalid value, like using a NaN, which isn't even portable, and which you might get as a result from your calculations)
<fe[nl]ix>
ext3 performs pretty well with bitmaps a few orders of magnitude bigger
<fe[nl]ix>
of course, file-systems that need to scale beyong a TB or so use specialized trees
<edgar-rft>
...I meant where do I get room for 20k flagpoles
<aeth>
Anyway, I use bits in integers when I want to associate multiple boolean things with one index, and I use bit-vectors when I want to associate one boolean thing with one index.
<_death>
for "flags" I'd often use an unsigned-byte and not a bit-vector, if not a list (set) of keywords or somesuch
<edgar-rft>
yes, that only was a pitiful joke, semaphores (many booleans in one variable) are the first thing when I think about bit-vectors.
yitzi has joined #lisp
<aeth>
_death: Right, one collection of bits for one thing, use an integer. One bit for a sequence of things, use a bitvector and iterate both sequences simultaneously in one LOOP/DO/etc.
<aeth>
You can even get sophisticated and have a 2D array, where the first part of the AREF is the same as the AREF for the bitvector
remexre has quit [Quit: WeeChat 2.8]
sonologico has quit [Remote host closed the connection]
leo_song has quit [Quit: ZNC 1.7.2+deb3 - https://znc.in]
dra has joined #lisp
leo_song has joined #lisp
<edgar-rft>
summary so far: bit-vectors are useful to distinguish fixnums (number family) from semaphores (boolean family), everything else so far I consider as "esoteric use-cases", any disagreements? :-)
<fwoaroof[m]>
bit-vectors are useful when you want a sequence of bits, basically?
<phoe>
a fixed-length sequence of bits
<aeth>
iterating over two arrays simultaneously isn't very esoteric
<aeth>
it's basically built into LOOP, MAP, and a bunch of other stuff
<phoe>
bit vectors have constant performance characteristics whereas integers don't when they evolve into bignums
<phoe>
this is important for large vectors.
<fwoaroof[m]>
Can you have an adjustable bit-vector with a fill pointer?
<aeth>
Yes, you can even do that with strings
<edgar-rft>
hmm, isn't in a computer *everything* a sequence of bits?
<aeth>
all vectors are just vectors with special :element-types
<phoe>
(make-array 256 :element-type 'bit :adjustable t :fill-pointer 128)
<aeth>
(it's just only bit/character are mandated)
<phoe>
fwoaroof[m]: yes
<fwoaroof[m]>
because that means that bit-vectors can also be used with non-fixed-length sequences of bits
<phoe>
sure, if you're okay with eventually copying them
<aeth>
edgar-rft: In C, everything's a sequence of bits, in CL, the underlying hardware is unspecified. This makes CL closer to the underlying hardware, because floats are iirc stored in special registers as a separate thing and treating them as just bits like C treats them is inefficient and probably requires a conversion.
<edgar-rft>
aeth: does CL support tri-state logic?
<phoe>
edgar-rft: not really unless you implement it yourself
<edgar-rft>
optional fill-pointer is a good argument
<aeth>
fwoaroof[m]: I'd say being able to use them in MAP is more useful. That is, going back to the earlier struct... (defstruct foo (foos (make-array 30000 :element-type 'single-float :initial-element 0f0) :type (simple-array single-float (30000))) (active? (make-array 30000 :element-type 'bit :initial-element 0) :type (simple-array bit (30000))))
<aeth>
you can do this: (let ((foo (make-foo))) (map nil (lambda (foo active?) (unless (zerop active?) (format t "~A~%" foo))) (foo-foos foo) (foo-active? foo)))
<aeth>
You can't do that by manually creating your own bitvectors out of fixnums whose indices don't match the other sequence's indices
<fwoaroof[m]>
yeah, makes sense
<aeth>
I could definitely see myself doing something like this if I could remember that such a thing can be done, but odds are I'd forget and write a messy LOOP instead
<aeth>
You could even map-into the foos array based on what the bit-vector tells you to do, although you might want to reorder things, so at that point the built in higher order functions might not be that useful
<aeth>
i.e. (map-into foos #| some lambda |# foos this-bit-makes-something-happen)
random-nick has quit [Ping timeout: 240 seconds]
<aeth>
You could also make that an octet vector and assign a meaning to each bit and get really fancy and low-level-ish.
<edgar-rft>
that sounds as if you have invented unicode :-)
<aeth>
You could go much further if there were a lot of buildings for working with multidimensional arrays since 2D array rows gives you so much more here.
<aeth>
s/buildings/built-ins/
<aeth>
Although, idk, maybe they need buildings to write all the code in
* edgar-rft
imagines CL buildings
akoana has left #lisp ["Leaving"]
dra_ has joined #lisp
<phoe>
I would like living in a CL building because then I could just leave trash anywhere in my flat and then it would get automatically collected
<dra_>
You could also just keep changing your building while living in it.
<_death>
well, we have FLOOR and CEILING already
<dra_>
But the C people have the -Walls. Dammit!
dra has quit [Ping timeout: 240 seconds]
dra_ is now known as dra
<edgar-rft>
Thank you all, I think I have really learned something! And you can be proud ouf yourselves because makinge edgar learn something is a really remarkable achievement.
dra has quit [Quit: Leaving]
mangoicedtea has joined #lisp
rpg has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]