<mfiano>
I seem to recall this discussed quite a few times: "Don't use WHEN for a return value; only for side-effects.". I'm curious how popular this convention actually is these days.
attila_lendvai has quit [Ping timeout: 240 seconds]
<mfiano>
Like, how about anyone that reads this IRC channel? Do you ever use bind the return value of WHEN as a generalized boolean variable?
<mfiano>
s/use//
<sbenitezb>
_death: Thank you! That's exactly my use case
<yitzi>
I think using WHEN in MAPCAN is fun....when I'm not in the mood for LOOP.
<_death>
I'd use WHEN in a function body that way, but for result bound with LET I'd probably use AND
<mfiano>
Ok, so this "rule", is not followed so strictly these days. IIRC it's pretty dated (from the LUV slides perhaps?)
<mfiano>
But need more samples than that :)
<_death>
I don't follow it strictly if I could use the implicit progn.. others may differ.. it's also possible that I'd use COND for the implicit progn
<_death>
basically it depends on what I want to emphasize
azimut has quit [Ping timeout: 255 seconds]
tyson2 has joined #commonlisp
attila_lendvai has joined #commonlisp
perrierjouet has quit [Quit: WeeChat 3.7.1]
ec has quit [Ping timeout: 255 seconds]
perrierjouet has joined #commonlisp
ec has joined #commonlisp
eddof13 has joined #commonlisp
<jcowan>
I wouldn't use WHEN for its value, because the last form might happen to evaluate to NIL, in which case the value would always be NIL.
<kakuhen>
I've used a WHEN form as the input to some functions that get really angry when they take a NIL... I learned the hard way since then to not use WHEN forms as arguments to a function
<kakuhen>
with that said, now that I'm aware of what is arguably an obvious thing, I don't mind using WHEN forms as values where appropriate
eddof13 has quit [Quit: My MacBook Air has gone to sleep. ZZZzzz…]
<shunter>
mfiano: Normally I bind a variable to (when test form) to mean the var's value is something only when the test is true.
gxt has quit [Remote host closed the connection]
Fare has joined #commonlisp
<mfiano>
If I have an integer that is assumed to be a 1d row-major index suitable to pass to row-major-aref, how might I transform that efficiently into multiple subscripts? (or is there an alternative to array-in-bounds-p like there is for aref?)
gxt has joined #commonlisp
triffid has quit [Remote host closed the connection]
triffid has joined #commonlisp
Guest3 has quit [Quit: Client closed]
jolby has quit [Quit: Client closed]
<Josh_2>
Never heard of a conditional, I just #'change-class and call the same method :joy:
karlosz has quit [Ping timeout: 256 seconds]
dipper has quit [Remote host closed the connection]
dipper has joined #commonlisp
gxt has quit [Ping timeout: 255 seconds]
gxt has joined #commonlisp
bilegeek has quit [Quit: Leaving]
attila_lendvai has quit [Ping timeout: 256 seconds]
nij- has joined #commonlisp
<nij->
I'd like to ask a question with no actual use. I'm just curious. -- CL spec is very large (roughly 1000 pages?). However, that doesn't mean it is 'hard' to implement it. If I understand correctly, while implementing CL with an imaginary language X, one only has to implement a small subset of CL in X. Once that's done, the rest of the CL can be bootstrapped from the then existing CL-subset. Of course, there could be places where
<nij->
optimization is needed, but let's suppose performance isn't an issue for now. My question is what's such a minimal subset (non-unique)?
<Bike>
it is kind of still hard to implement it.
<Bike>
and can be described in different ways. for example, typep is generally more involved than consp and may practically speaking be implemented in terms of it, but if you take typep as primitive you can implement consp trivially.
perrierjouet has quit [Quit: WeeChat 3.7.1]
perrierjouet has joined #commonlisp
<nij->
Yeah, there are multiple ways to "settle the basics".
<Bike>
sure but what i mean is a "minimal" subset may not be practical
<nij->
In CLHS there are 25 special operators. Won't it be enough to implement them, and a few other things like environment and a repl?
<Bike>
how would you do cons?
<nij->
Yeah, I"m aware that it would be impractical. I'm still curious though
<Bike>
(yes, you can implement objects in terms of closures, but then you couldn't tell them apart with functionp/consp)
<Bike>
i don't mean impractical, i mean you couldn't do it
<Bike>
i suppse you could make your own functionp
Oladon has joined #commonlisp
<nij->
I see. So the 25 special ops aren't enough..
<nij->
How about 25 special ops, a repl, struct, and the 7 basic things that can bootstrap eval (due to McCarthy)?
<Bike>
depending on what you mean by implement, all you "really" need is lambda
<nij->
By implement I mean to get to a runtime that satisfies what CLHS specifies.
mzan has joined #commonlisp
<Bike>
i mean, for example, the CLHS includes file i/o
<Bike>
you could make some sham version of that that wouldn't operate with the underlying filesystem, with lambdas etc, but eh
<nij->
Yeah, so there should also be ways to file io.
<nij->
So now we have - at least 25 special ops, a repl, 7 ops to get to eval, file i/o.. what else?
<Bike>
But I mean you could make a technically conformant version that doesn't actually use the underlying operating system. or just implements its own operating system.
<nij->
If it doesn't actually use the underlying OS, would it still be conformant?
<Bike>
i don't see why not. on lisp machines the lisp kind of was the operating system.
<Bike>
you can see the weasel words they use - "typically", etc
tyson2 has quit [Remote host closed the connection]
<aeth>
You'd obviously want to implement CONSP in terms of TYPEP
<aeth>
since TYPEP is probably going to check the type bits in general, or at least you can implement it that way
<nij->
Bike cool that means we don't even need it to do io to OS
<aeth>
while TYPEP that uses CONSP in its implementation is one giant messy COND or something
<Bike>
typep is going to have to do some kind of cond regardless, practically speaking.
<Bike>
which is why i'm sort of nitpicking this question a lil
<nij->
what's left to be nitpicked?
<aeth>
It's going to generate the same low level code either way, probably. It's just going to be messier with TYPEP-on-CONSP than CONSP-on-TYPEP. Plus, the built-in types without predicates would still need low-level TYPEP support unless you write %foop for them
<nij->
I don't really mind which makes more sense.
<nij->
I just hope to see a small subset of CL on which the small CL can be used to make the whole CL.
<nij->
The small subset doesn't have to be perfectly minimal.
lechner has quit [Ping timeout: 240 seconds]
lechner has joined #commonlisp
saura is now known as tron
tron is now known as thoughtron
lechner has quit [Remote host closed the connection]
Fare has quit [Ping timeout: 256 seconds]
<beach>
nij-: Also, writing a Common Lisp system in some language other than Common Lisp, and building up the system from subsets of Common Lisp is not a great way of creating a Common Lisp system.
<beach>
nij-: Having said that, I should say that I started a project (BOCL) much like what you describe. Start with C and then build up a complete Common Lisp system, but using as little C as possible.
<nij->
!!
<nij->
Did you get to a conformant CL?
<beach>
Nah, I am not working on it very much. I mostly amuse myself by thinking about strategies.
<beach>
It is amusing, because I am not used to disregarding performance. So the strategies are completely different. My main project is to create a Common Lisp using only Common Lisp.
<beach>
BOCL means "BOotstrap Common Lisp" and was meant for those distributions of operating systems that require every package to be built from the C tool chain only.
<nij->
Would you mind sharing some minimal things to achieved in order to get to a conformant CL?
<beach>
Creating a Common Lisp system by building on successive subsets results in a maintenance nightmare, and (more importantly) is too hard for the size of my brain, apparently. I just can't think in terms of subsets.
<nij->
Besides the 25 special ops, a repl, 7 ops to get to eval,
lechner has joined #commonlisp
<beach>
The current thinking is to write a minimal compiler in C that translates a minimal Common Lisp into C. That way, many of the "library" functions could be written in Common Lisp. Then an evaluator could perhaps be written in that minimal Common Lisp.
<nij->
yeah, I'm very curious how minimal that minimal-CL can get. The answer doesn't have to be perfect.. but I want to have some sort of idea.
<nij->
So the question is: what is "that minimal CL" you had in mind?
<beach>
Basically a subset of DEFUN, LET, IF, TAGBODY.
<Bike>
it sort of depends on what you have in the runtime. for clasp, a couple months ago we wrote a pretty basic VM and a pretty basic compiler in C++ that compiles any common lisp code to the VM. works great. but it doesn't only have the special operators - the compiler doesn't know about them, but the runtime has a big portion of the standard library pre-bootstrap
<beach>
With some discipline, all those can be directly translated to C.
<aeth>
the idea being that it's very early in the bootstrap process of building, say, SBCL
pdietz has joined #commonlisp
<beach>
nij-: Another idea is to represent all Common Lisp objects the same way, as standard objects. Then a lot of code can be factored.
<aeth>
and then maybe shorten it to 'axcl'
Fare has joined #commonlisp
<Bike>
but i definitely want to agree with beach that doing something at all "minimal" makes things harder rather than easier.
<Bike>
having a minimal base means everything built on it is in fact bigger than it ought to be
<nij->
beach: so DEFUN, LET, IF, TAGBODY, standard objects, and a repl.. that's enough?
<Bike>
"loop isn't available yet, so i have to write this mess of tagbodies instead"
<beach>
Heh, yeah.
<beach>
nij-: What's so magic about the REPL?
<nij->
But the point, Bike, is that loop can be written in the smaller CL.
<Bike>
if you hate yourself, it can be
<Bike>
it's like trying to write a novel without using prepositions
<nij->
beach hmm I'm just thinking of a way for the machine to know how to parse input strings into list of symbols, and how to evaluate them using environment.. etc.
<Bike>
or, well, better example, you know how principia mathematica only manages to prove 1+1=2 several hundred pages in?
<beach>
nij-: You would write a minimal reader in C that can read only that small subset, and that assumes that it is well formed. Then you would later load Eclector.
<nij->
Bike: how is that 1+1=2 relevant? im curious
<beach>
nij-: And if you compile that subset into C, you can then write the evaluator in Common Lisp. The REPL can be written that way.
<nij->
beach oh yeah
<nij->
beach How about environment?
<Bike>
what i mean is that PM starts with a very basic logic, and then has to arduously define basic concepts like natural numbers, and more fundamentally just the compound logical concepts needed to define those concepts, in terms of that logic. and it takes forever and is pretty unreadable.
<Bike>
simplicity was the point for them, rather than practicality, so that's fine. but it's not much fun for a practical software system
<nij->
Oh I see. They wanted to start everything with 1st-order lang, on top of which they built set theory, and on top of which they build numbers as {{{{{{}}}}}} or something like that.
<beach>
nij-: Sure, those would need to be represented as well. But we have both Clostrum and Trucler, so it might be possible to do a subset in C.
<nij->
Instead, they could have defined integers as something else that's more intuitive, but less favorable for their "reductive plan".
<nij->
I don't know either of them. Would you hint how they are relevant?
<beach>
Clostrum implements global environments, and Trucler implements compile-time lexical environments.
<beach>
nij-: Basically, a lot of what is needed exists in the form of libraries written in Common Lisp. So the main job is to make it possible to load those libraries.
<nij->
tbh can't find them online.. hmm..
<nij->
Oh I see
<beach>
Try s-expressionists on GitHub.
<nij->
But they are written in full CL..
<aeth>
you can form natural numbers as something like this: (NIL #1=(NIL) #2=(NIL #1#) #3=(#1# NIL #2#) #4=(#2# NIL #1# #3#) ...)
<Bike>
yeah, because it's actually simpler to just write your CL in CL.
<beach>
nij-: Yes, like I said, my brain is too small to think in terms of subsets.
<Bike>
it's a pretty good programming language
<beach>
Heh.
<nij->
I know it's the best writing cl in cl.. just curious though.
<Bike>
but, really, that's a good example. eclector is a good reader. it's a lot of code. now imagine having to write that code, but without having clos or loop. it would be much more code.
<beach>
nij-: If you don't have the restriction that those operating systems impose, the best choice is to write it in Common Lisp. As Bike says, it's a pretty good language.
<beach>
And, yes, Eclector is excellent!
<Bike>
and that much more code would be harder to write and maintain. we do kind of bootstrap in clasp, so i can tell you from experience, it kind of sucks.
<Bike>
("kind of" in that we haven't tried to minimize the base)
<Bike>
a minimal base would be more useful (in my opinion) as part of defining a formal semantics for the language. but that's a completely different task from making a cl implementation.
<beach>
Bike: As I recall, though, the Clasp reader was completely written in C++, yes?
<beach>
So that's an idea for reducing the size of the base; just write a reader in C++ that can read the Eclector code. Something like that anyway.
triffid has quit [Remote host closed the connection]
lechner has quit [Ping timeout: 256 seconds]
<Bike>
we wouldn't be able to evaluate it right off anyway.
<nij->
Thanks folks :)
<nij->
(gotta go sleep zzZ)
<beach>
Bike: Sure, you still need an evaluator. What I am saying is that if you take Eclector and all the other Common Lisp source code you need, you still probably need only a very small subset of what READ is capable of.
<beach>
And you can probably ignore lots of error situations, because you can assume that the code you read is well formed.
<beach>
So the minimal reader would not be conforming, so it could not be used in the final system, but it could read all the source code, including Eclector.
lechner has joined #commonlisp
Lord_of_Life has quit [Ping timeout: 268 seconds]
Lord_of_Life has joined #commonlisp
jackdaniel has quit [Ping timeout: 252 seconds]
jackdaniel has joined #commonlisp
pdietz has quit [Quit: Client closed]
dipper has quit [Remote host closed the connection]
Oladon has quit [Quit: Leaving.]
mingus has quit [Ping timeout: 260 seconds]
gilberth has quit [Ping timeout: 248 seconds]
dipper has joined #commonlisp
azimut has joined #commonlisp
igemnace has joined #commonlisp
<seok>
is there a font rasterizer library?
<beach>
cl-vectors by Xach.
<jackdaniel>
cl-vectors is by someone else, xach wrote zpb-ttf that may be used with cl-vectors
<jackdaniel>
Fredric Jolliton the author is
<jackdaniel>
vecto is based on cl-vectors (and Xach authored vecto)
<aeth>
unfortunately, there are multiple kinds of TTF and zpb-ttf doesn't support all of them
<aeth>
or even a lot of them
<jackdaniel>
isn't truetype a format?
<jackdaniel>
opentype fonts use ttf but pack information in tables that were not defined for truetype
<jackdaniel>
afair
<seok>
Ah, thanks vecto looks pretty simple
<aeth>
well, the random fonts I'm trying with it now don't error
dipper has quit [Remote host closed the connection]
euouae has joined #commonlisp
dipper has joined #commonlisp
<euouae>
Hello, with import and export I can add packages to the internals/externals
<euouae>
but how can I add a single symbol to the inherited symbols? or is that not possible?
<beach>
IMPORT and EXPORT influence only the package being operated on, so it does not add any packages. You can add symbols to the inherited ones by adding that symbol to the package being used.
* beach
now fully expects to be told he is wrong.
<euouae>
I meant to say 'add symbols'
<euouae>
How do you add a symbol to the inherited ones without use of use-package or :use?
<phoe>
:IMPORT-FROM?
<phoe>
or CL:IMPORT for a functional variant?
<phoe>
so basically what beach said
<euouae>
import makes it internal right?
<euouae>
it doesn't make it inherited
<beach>
euouae: You figure out what package is being used, and you add the symbol to that package. A symbol in inherited because your package uses another package that has that symbol and exports it.
<euouae>
so the inherited symbol property is a package-package property. You can't pick and choose inherited symbols
<beach>
Correct.
<euouae>
alright thanks
<phoe>
yes, you check whether the home package of the symbol is EQ to the package that the symbol is internal in
<euouae>
assuming no strange things have happened
<phoe>
no, I actually think it always holds true
<euouae>
the home package can be modified
<phoe>
if the two are not EQ, the symbol is imported from another package or comes from a used package
<phoe>
yes, but at this point if the home package is modified to be the package in question, then the symbol is no longer imported
<lieven>
or a symbol can have no home package
<euouae>
right
<phoe>
at which point it still is imported, just homeless
<euouae>
the home package seems to be a lisp printer detail
<euouae>
it's not much related to other things
<lieven>
there's an idiot's guide to packages floating around written by ron garrett that is a pretty good read about this stuff
<euouae>
I feel better now about them lieven
<phoe>
the printer is where this will manifest the hardest in practice but it's still a package system concept
<euouae>
I've read that guide
<beach>
I believe if a symbol S with no home package is imported to a package P, then P becomes the home package of S.
<euouae>
It's a package system concept but it's not reliable to deduce from
<euouae>
in particular at least, it's not related to inheritance
<phoe>
yes, but if you first import FOO:S into BAR and then unintern S FOO:S from FOO, you have the pathological case
<phoe>
BAR::S has no home package
<lieven>
beach: the glossary item for apparently uninterned seems to contradict that
<beach>
I knew I should have shut up.
<euouae>
"If any symbol to be imported has no home package (i.e., (symbol-package symbol) => nil), import sets the home package of the symbol to package. "
<euouae>
This supports beach though, from IMPORT
<lieven>
indeed it does
<phoe>
lieven: it doesn't contract him I think, the detail is in the ordering of operations
<lieven>
yes
<phoe>
import → unintern is allowed to cause a NIL home package
<phoe>
unintern → import will reset the home package to the importing package
shka has joined #commonlisp
Krystof has joined #commonlisp
<euouae>
In other words, the home package can be set to anything desired
<phoe>
except for the CL package
<phoe>
this one is holy
<euouae>
or a package that doesn't have it at all I guess
<phoe>
have what at all?
<euouae>
it can't be home to a package that doesn't have it internal/external/inherited
<phoe>
uhhh
<phoe>
but that is what IMPORT does
<euouae>
and then it'd be internal
<phoe>
an uninterned symbol that is then IMPORTed into a package is no longer uninterned
<euouae>
right
<lieven>
phoe: the KEYWORD package is also strongly suggested not to mess too much with
rainthree has quit [Read error: Connection reset by peer]
rainthree has joined #commonlisp
<phoe>
lieven: you can intern stuff into it just fine
<phoe>
don't even unintern stuff from it though
random-nick has joined #commonlisp
waleee has quit [Ping timeout: 256 seconds]
MajorBiscuit has joined #commonlisp
azimut has quit [Ping timeout: 255 seconds]
azimut has joined #commonlisp
<euouae>
ah, and apparently there can be use-package cycles
<euouae>
e.g. FOO and BAR can use each other. I thought maybe it was a DAG
rgherdt has joined #commonlisp
rgherdt has quit [Remote host closed the connection]
rgherdt has joined #commonlisp
rgherdt_ has joined #commonlisp
rgherdt has quit [Ping timeout: 256 seconds]
empwilli has quit [Quit: WeeChat 3.0]
empwilli has joined #commonlisp
<pjb>
mfiano: note: WHEN is NOT specified to return no value when the condition is false. Also, in Common Lisp I can't remember any operator for which the result is left unspecified or specified to be nothing, like eg. in scheme. What I mean, is that all CL operators DO return something that is explicitely specified. Even if it was no (values), it is specified that if you use it you get NIL!
<pjb>
mfiano: therefore I see no point in writing (list (if foo bar nil) (if baz quux nil)) vs. (list (when foo bar) (when baz quux))
<pjb>
Which is not to say that I wouldn't occasionnaly write (if foo bar nil).
<pjb>
Rules are made to be ignored (adequately).
pfd has joined #commonlisp
kaskal has quit [Ping timeout: 268 seconds]
kaskal has joined #commonlisp
<beach>
pjb: The reason is that WHEN and IF send different messages to the person reading the code.
<Alfr>
pjb, ROOM
<beach>
pjb: There are many operators that can be used interchangeably, but they send different messages like that. Otherwise, there would not be both a NOT and a NULL.
<pjb>
beach: I find it dangerous to use too much connotation in programming. The semantics are specified. We have have little reason to program in a metally different programming language.
<beach>
So if it were just a matter of semantics, then, sure, WHEN is fine in a context where the value is needed, and NOT and NULL can be used interchangeably.
<pjb>
Alfr: ROOM is still specified to return an implementation dependent value, which should be documented by the implementation.
<beach>
pjb: I see.
* beach
shuts up.
<phoe>
just (if foo bar (setq))
azimut has quit [Ping timeout: 255 seconds]
<pjb>
Let's say that I agree with these kinds of rules for newbies. This may be helpful there. But advanced programmers may choose to ignore them, and foremost, they should know the exact semantics, not the easy language we may have in our minds. I can see the problem this cause with languages like C.
azimut has joined #commonlisp
Dynom_ has joined #commonlisp
<pjb>
phoe: you should be prepared to that. Not saying it's good style, but there may be a reason to write it like this (notably in generated code).
Dynom_ is now known as Guest7786
<Alfr>
pjb, but they may choose not to.
<pjb>
nij-: there's no answer to the minimum, since the minimum is a single instruction processor (eg. with a Conditional-Move instruction). Anything Turing Machine can be used.
dipper has quit [Remote host closed the connection]
<pjb>
Alfr: if the implementation doesn't document implementation specific stuff, then it is not conforming.
<Alfr>
pjb, implementation dependent is not implementation defined, so that'd be fine.
<pjb>
oh! Right.
<pjb>
I confused both.
sedzcat has joined #commonlisp
<pjb>
That said, my point is that ROOM would still return something. It couldn't eg. return an invalid lisp object.
<pjb>
You can definitely write (print (list (room) (room) (room))) without breaking anything.
<Alfr>
pjb, or nothing, which will turn into nil if as value if called for.
<pjb>
yes.
<Alfr>
pjb, btw. I'm not arguing that anything is horribly broken, only intended to given a counter example.
<pjb>
nij-: you really can choose your own minimal set. For example, you can use just DEFUN and LOOP (is it not more minimal than DEFUN, LET, IF, TAGBODY ?)
<pjb>
(let ((var val) . body) = (loop with var = val repeat 1 do . body) (modulo declarations)
<pjb>
(if <test> <then> <else>) = (loop repeat 1 if <test> do <then> else do <else> end) etc.
<pjb>
aeth: I wouldn't shorten it. If you choose a nice name like archaeopteryx, you should require it to be spelled out in-extension all the time.
<pjb>
nij-: The question of minimal CL to implement CL occurs only if you start with a different programming language. You wouldn't want to write a full CL implementation in assembler or C. Or even in most programming languages. So instead, implement CL in full CL, like sicl does, and skip a whole lot of problems.
<pjb>
nij-: do you want to implement your CL in a different language?
ttree has quit [Ping timeout: 256 seconds]
<pjb>
euouae: to add a symbol to the inherited list of a package, you need to add it to the export list of the used package.
<euouae>
oh nice! then what is the fill pointer about really?
<euouae>
I don't quite follow
<euouae>
isn't (make-array 10 :fill-pointer t) the same as (make-array 10 :fill-pointer 10)
<pjb>
euouae: Yes. But you can set the fill-pointer. Here I initialize it to 0 (empty vector).
<euouae>
I see
<pjb>
euouae: the fill-pointer is the "actual" length of the vector, while the array-total-size is the allocated size.
<mfiano>
the fill pointer is where the effective array ends, and new items will be written to the right of it, and it also moved right
<pjb>
in C, you would write: struct { Entry* elements; size_t allocated; size_t length /* aka fill-pointer */ } Vector;
<euouae>
right
<euouae>
but then (length vector) reports something other than the fill pointer?
<euouae>
or no, you said it's equal
<Alfr>
euouae, if the vector has a fill pointer, otherwise calling fill-pointer on it could be bad.
<Alfr>
euouae, length also works with other sequences, not only vectors.
<mfiano>
Yeah length is the general sequence length. list's have their own too.
perrierjouet has quit [Quit: WeeChat 3.7.1]
mingus has joined #commonlisp
perrierjouet has joined #commonlisp
<euouae>
is with-hash-table-iterator guaranteed the order in two repetitions?
<euouae>
e.g. if I do w-h-t-i twice, do I get the same order of keys?
<pjb>
Probably not.
<pjb>
Notably, if GC occured between the too, or if you added/removed entries.
<euouae>
right
<euouae>
ah... graph algorithms are hard
<pjb>
euouae: well, "Probably not" may be too strong. You may get the same order, or not, depending on the implementation and other stuff occuring in the image. (also, allocation and garbage collection can occur from stuff in parallel threads).
Brucio-61 has quit [Ping timeout: 260 seconds]
scymtym has quit [Ping timeout: 268 seconds]
<euouae>
writing efficient common lisp is tricky
<pjb>
euouae: or since there's no guarantee about that, an implementation could choose a random order each time for the fun.
<euouae>
:CL is a bit bare bones and what may work with an underlying hashtable falls apart when there's more requirements later
<pjb>
euouae: well, the standard gives you some guarantee, and leaves implementations free to optimize as they wish. If you want your own guarantee and optimization dimensions, you need to write your own data structure and code.
<euouae>
yeah
<euouae>
now for something entirely crazy, does common lisp have rust bindings?
<pjb>
I don't know rust.
<pjb>
define rust bindings?
<euouae>
I've never done FFI much but I think it's cool
<euouae>
unfortunately the details are a bit murky right now
<euouae>
but how does it go... you have some (call-from-rust "rust-function-name") thing
<euouae>
and some translation between lisp types and rust
<pjb>
oh, you mean FFI. I don't know any specific library for rust FFI.
<pjb>
In general FFI caters to the lowest common denominator, ie. C.
<pjb>
There are a few libraries to help with Objective-C (which has a dynamic run-time).
<pjb>
I guess you could write some FFI declarations to access to the dynamic run-time of rust, and implement something like (call-from-rust "rust-function-name").
<pjb>
use CFFI for portability.
<euouae>
dynamic runtime? do you mean dlopen()?
<euouae>
rust is a compiled language
<pjb>
No. In the case of Objective-C, there's a C library that let you introspect and retrospect Objective-C stuff (classes, objects, methods, etc).
<pjb>
Objective-C too. But if the runtime is dynamic, it may be supported by a low-level library with C entry points.
<pjb>
euouae: in general, try to avoid FFI. Implement stuff in CL instead. (you may implement the other language in CL, if you need to run a library or some code). If you really need to run something in a different language, you may do it in a different process, with sockets or other IPC to communicate.
<pjb>
unix is optimized to have several processes working together thru IPC.
<euouae>
yeah you're right pjb
<pjb>
Notably for this need of data conversion, at each function call, this becomes costly very soon.
<euouae>
well if you care to look I'll share some graph code that I wrote
<euouae>
it's pretty basic
<euouae>
but I'm getting in trouble with a certain algorithm
<euouae>
It seemed okay, but I got in trouble with the commented-out acyclicp algorithm
<euouae>
maybe I'm just not thinking enough, I'll have a look at it later again.
<euouae>
but I do wonder if the bare-bones directed-graph definition is enough. probably not.
<pjb>
Write tests? That may help debug.
<phoe>
write tests, yes
<euouae>
the problem deep down is that graph algorithms are tricky I guess
<euouae>
for example my vertices are a hashmap vertex -> T. But maybe it's a good idea to have them also as a vector #(v1 v2 v3 ...)
<euouae>
a bit more memory, but there's better speed if the user wants the vector.
<euouae>
but then! more trouble if you remove a lot of vertices, because the vector elements need to be moved around
<euouae>
sigh. despair
<pjb>
It can help for time or space complexity, but in terms of sophisticated algorithm you definitely want some abstraction.
<pjb>
On the other hand, there are graph algorithms that work on different representations. For example, if you have an indicator matrix to represent the graph, your algorithms would use matrix operations.
<pjb>
This kind of representation may be efficient when the graph is dense.
Brucio-61 has joined #commonlisp
<euouae>
okay I think I see what I need to do
<euouae>
I will write all the necessary functions unoptimized, write the algorithms, and then it's a matter of switching the underlying graph implementation
<euouae>
define an empty class graph-fundamentals with empty defmethods that define the graph API
<euouae>
and then inherit for actual implementations (optimized or whatnot)
<euouae>
right?
<euouae>
e.g. (is-vertex? v g) can be part of the graph API but what it does is different in different graph implementations (looks up in array, hash-table, etc)
<pjb>
Yes.
<euouae>
that's pretty cool
<euouae>
I see cesarum has a few new data structures. It might be nice to look at!
<euouae>
pjb, you could include a reference to the algorithm by the way, I think it's the same as mine (Kahn 62)
rendar has quit [Quit: Leaving]
ttree has quit [Read error: Connection reset by peer]
<pjb>
euouae: possibly. I don't remember where I got the algorithm from.
<euouae>
Yup. Alright, thanks again. Have to go now
euouae has quit []
<beach>
Graph algorithms are tough because there is not one best representation for graphs, so the algorithms you plan to use may have a considerable influence on how the graph is represented.
<pjb>
We must have representation conversion functions.
<pjb>
But for big graphs this may be costly. That said, big is relative. I've noticed already several years ago, that graphs with thousands of nodes could be processed with unoptimized code in short time on current hardware.
<pjb>
ie. O(n^2) when n=1000 can still be less than a millisecond on current hardware.
<dirtcastle>
trying to run sbcl on termux. is it possible? how to do it.
<phoe>
in general you want to build an android version of sbcl
<phoe>
might be more or less impossible for you if, quote, "you're noob" though
pfd has quit [Quit: Client closed]
Major_Biscuit has joined #commonlisp
thonkpod has quit [Ping timeout: 260 seconds]
MajorBiscuit has quit [Ping timeout: 256 seconds]
thonkpod has joined #commonlisp
pve has joined #commonlisp
les_ has joined #commonlisp
les has quit [Ping timeout: 246 seconds]
szkl has joined #commonlisp
genpaku has quit [Remote host closed the connection]
genpaku has joined #commonlisp
pdietz has quit [Quit: Client closed]
morganw has joined #commonlisp
attila_lendvai has joined #commonlisp
<mfiano>
Good morning. I woke up this morning and told myself that I will have an OLN (or ELS if it's teleconferenced) demonstration of some Lispy stuff next year (so probably next year for OLN, and the following year for ELS)
<mfiano>
s/OLN/OLM/
pdietz has joined #commonlisp
attila_lendvai has quit [Ping timeout: 256 seconds]
Josh_2 has quit [Ping timeout: 268 seconds]
<phoe>
sure
jeosol has quit [Quit: Client closed]
shka has quit [Quit: Konversation terminated!]
Josh_2 has joined #commonlisp
shka has joined #commonlisp
jmdaemon has quit [Ping timeout: 256 seconds]
mingus1 has joined #commonlisp
mingus has quit [Ping timeout: 260 seconds]
mingus1 is now known as mingus
Bung has joined #commonlisp
Bung has quit [Remote host closed the connection]
tyson2 has joined #commonlisp
causal has quit [Quit: WeeChat 3.7.1]
Bung has joined #commonlisp
dipper has joined #commonlisp
pdietz has quit [Quit: Client closed]
dipper has quit [Remote host closed the connection]
dipper has joined #commonlisp
dnaeon has joined #commonlisp
attila_lendvai has joined #commonlisp
<dnaeon>
Hey Lispers! Looking for a way to create temporary directories. Seems like `uiop` does not provide such function (at least not that I found one). Is there any system out there, which provides what `mktemp -d` on the shell does?
azimut has quit [Ping timeout: 255 seconds]
<phoe>
dnaeon: I assume you could do something with (uiop:temporary-directory)
thuna` has joined #commonlisp
Fare has quit [Ping timeout: 268 seconds]
<_death>
osicat has mkdtemp
euouae has joined #commonlisp
attila_lendvai has quit [Ping timeout: 256 seconds]
attila_lendvai has joined #commonlisp
nij- has quit [Ping timeout: 240 seconds]
thuna` has quit [Quit: restarting]
thuna` has joined #commonlisp
<dnaeon>
thanks @phoe and @_death!
eddof13 has joined #commonlisp
attila_lendvai has quit [Ping timeout: 256 seconds]
ec has quit [Remote host closed the connection]
cosimone has joined #commonlisp
ec has joined #commonlisp
attila_lendvai has joined #commonlisp
aartaka has joined #commonlisp
White_Flame has quit [Remote host closed the connection]
White_Flame has joined #commonlisp
cosimone has quit [Read error: Connection reset by peer]
<Bike>
goofy solution would be to not return them in the rpel, of course. like (progn (returns-expensive-structure) nil). doesn't help if you want to play around with them, of course
aartaka has quit [Ping timeout: 268 seconds]
aartaka has joined #commonlisp
<nij->
Bike that's indeed the issue!
<nij->
And I realize that even if I manually clear the returned hash table + GC full.
<nij->
The memory is still used..
<pjb>
then the next option is to try to find the references to it.
<pjb>
you start with (list-all-packages) and use do-symbol, and walk everything (use a hash-table to walk each object only once), until you find a reference to garbage.
<pjb>
(you'd still miss closures, if you don't have an implementation dependent API to inspect them).
<euouae>
does Windows have any particularities when it comes to Common Lisp implementations?
<euouae>
I'd like to produce a native executable.
Bung has quit [Remote host closed the connection]
azimut has joined #commonlisp
<pjb>
abcl, clisp, ccl and sbcl work on MS-Windows. ecl too, but you need to install the external C compiler with it.
<pjb>
euouae: the idea is to develop your lisp application on a sane system (linux or darwin), and when you have to sell it to ms-windows users, you will just recompile it with an implementation targetting windows.
Bung has joined #commonlisp
<pjb>
euouae: of course, FFI will be different, you will use dlls instead of libraries…
<pjb>
so avoid FFI!
<pjb>
euouae: you have also to be careful with physical pathnames.
<euouae>
got it
<euouae>
Alright thank you. As for the environment, do I use something like roswell?
<euouae>
I could just set it up all myself I guess, that's fine too. emacs/slime, quicklisp, asdf etc
lisp123 has quit [Remote host closed the connection]
lisp123 has joined #commonlisp
azimut has quit [Ping timeout: 255 seconds]
Brucio-61 has quit [Ping timeout: 260 seconds]
scymtym has quit [Ping timeout: 256 seconds]
dnaeon has quit [Ping timeout: 260 seconds]
lisp123 has quit [Remote host closed the connection]
lisp123 has joined #commonlisp
lisp1234 has joined #commonlisp
lisp123 has quit [Read error: Connection reset by peer]
beach` has joined #commonlisp
beach has quit [Ping timeout: 252 seconds]
Brucio-61 has joined #commonlisp
lisp1234 has quit [Read error: Connection reset by peer]
Guest7786 has quit [Quit: WeeChat 3.7.1]
jolby has quit [Quit: Client closed]
Bung has quit [Remote host closed the connection]
cowboy8625 has quit [Quit: WeeChat 3.5]
cage has quit [Quit: rcirc on GNU Emacs 27.1]
attila_lendvai has joined #commonlisp
pdietz has joined #commonlisp
cowboy8625 has joined #commonlisp
pdietz has quit [Quit: Client closed]
pve has quit [Quit: leaving]
<euouae>
is tehre a way to re-export the symbols from a package?
<NotThatRPG>
Having an odd experience with quicklisp. A co-worker was having trouble loading cl-unicode from quicklisp and so I tried doing it. I noticed that I got cl-unicode like this: cl-unicode-20190521-git. Buy my colleague got 20210228-git. I did do ql:update-all-dists, and was told my dists were up-to-date. Shouldn't I be getting the latest and (presumably) greatest? Or do I need to request that libraries be refreshed?
<NotThatRPG>
euouae: If you look at UIOP:define-package it has a bunch of options for doing just that
<euouae>
nice thanks NotThatRPG
<NotThatRPG>
It's a more featureful alternative to cl:defpackage
<Bike>
NotThatRPG: you might need to update the client
<Bike>
(with wl:update-client)
<Bike>
ql
<NotThatRPG>
Bike: Thanks, I will give that a try
<NotThatRPG>
Didn't occur to me that this would have an effect.
<NotThatRPG>
BTW is there a library that does file-globbing for CL? It's surprisingly difficult to do that with cl:directory
<NotThatRPG>
feeling a little envy that python has the `glob` module
<euouae>
oh but wit, I don't want :use-reexport
<euouae>
what I want is to re-export the same set of symbols but for my new package
<euouae>
the idea is that I have an interface.lisp that defines a class 'graph' and defmethods such as 'add-vertex' that are unimplemented and the undirected.lisp file defines 'undirected-graph' inheriting from 'graph' and implementing 'add-vertex'
<euouae>
so I'd like to export 'add-vertex' in undirected.lisp. Can it be done automatically? I'm just copy-pasting export lists from one file to another
<phoe>
methods don't have names
<phoe>
methods belong to generic functions
<phoe>
these have names
<phoe>
in your interface package, do (DEFGENERIC ADD-VERTEX ...) and export ADD-VERTEX
<Bike>
the usual thing to do there would just be using graph:add-vertex everywhere, so undirected-graph doesn't need to export add-vertex.
epony has joined #commonlisp
<phoe>
then, in your implementation packages, (DEFMETHOD INTERFACE:ADD-VERTEX ...)
<pjb>
euouae: have a look at package conduits.
<euouae>
Bike: they're unimplemented because different graph features (undirected, directed, etC) may require different implementations for efficiency
<Bike>
and that method will still be there when you call graph:add-vertex, because it's a generic function
<euouae>
pjb, ah nice. but in light of the defgeneric comments, maybe I should rethink this
<euouae>
I guess I really do want to extend packages
<euouae>
For example 'graph' may have a defgeneric 'neighbors' but a 'digraph' will also have 'outflow' and 'inflow' neighbors, and digraph is an interface inheriting from graph (i.e. both are not implemeting any methods)
<Bike>
usually you would have graph:neighbors and then digraph:inflow. perhaps also (defmethod graph:neighbors ((g digraph) node) (append (inflow g node) (outflow g node)))
<euouae>
so you're saying (defclass my-graph (graph digraph) ... ?
Alfr has quit [Quit: Leaving]
<Bike>
no? i mean, presumably digraph inherits from graph.
<Bike>
but i was just talking about how the functions could be organized anyway
<euouae>
makes sense
shka has quit [Ping timeout: 260 seconds]
<euouae>
Bike, and what about the constructor
<euouae>
graph: doesn't have a make-graph, I can't dispatch on nothing
<euouae>
or is it undirected:make-graph and then proceed to use graph:... generics?
<Bike>
usually you use make-instance. and if you need to do some initialization you can specify shared-initialize and/or initialize-instance.
<Bike>
but it depends. sometimes you might just want a bunch of make-whatever functions that aren't generic at all.
<euouae>
make instnace of what? (make-instance 'undirected:undirected-graph) ?
<Bike>
well if that's the concrete class you're trying to make, yeah.
defaultxr has joined #commonlisp
<euouae>
how is the user supposed to know how to handle this constructor?
<phoe>
what do you mean by "handle"
<euouae>
how does the user know what key arguments to pass?
<phoe>
they'll read the documentation strings and/or user manual
<phoe>
or take a look at the keyword preview in slime/sly minibuffer
<euouae>
does that list private keys?
<euouae>
internal symbols?
<euouae>
slots, rather
<phoe>
there's no slots in questions
<phoe>
question*
<phoe>
just keyword arguments
<euouae>
I have an :initarg for internal use
<euouae>
should I remove it? I don't want it to show up
mister_m has quit [Ping timeout: 256 seconds]
<euouae>
That's what I did. Alright it looks good to me now.
rgherdt_ has quit [Remote host closed the connection]
<euouae>
if I have a primary subsystem A and two subsystems A/B and A/C and load those subsystems with asdf-load, does A get loaded twice?