freenode/lisp - IRC Chatlog
Search
18:40:51
axion
The only standards body we have is ANSI, so the only correct response is that which I gave.
18:43:26
aeth
Other languages might have a major implementation that is considerably more popular than the rest, and/or they might have a "killer app" framework, and/or heavy involvement from some corporation, or some other way for standards to spread for trivial things through influence.
18:47:01
aeth
If something like that is not present, the answer to bikeshed painting [0] is to make your own bikeshed and paint it what you want, rather than having to come to some consensus on how to paint a bikeshed.
18:48:57
aeth
In other words, a de facto standard for some simple X, Y, or Z could come from whatever the official language implementation does, or the main libraries/frameworks do, or what the main corporate backer does, etc. But Lisp has none of this.
18:49:38
aeth
(Scheme often does have de facto standards because each implementation might as be the official language implementation of a new language, rather than just an implementation of Scheme. But this is a Common Lisp channel.)
19:45:29
krwq
hey, what's the simplest code to read value given a key from list which looks like: '("key1" "sdfsdf" "key2" "fff")
19:53:08
aeth
If you can control the format, use keywords instead of strings, and you can just use (getf the-list :the-key)
19:54:03
krwq
this looks like will work http://stackoverflow.com/questions/9310913/how-to-get-two-elements-from-a-list-each-time-in-common-lisp but i wonder if there is an option to pass :test to getf
19:54:32
aeth
krwq: you can pass test into similar sequence operations like search, find, and position
19:55:15
krwq
aeth: but getf does not have tes and find will not necessarily position on key and may give valuye
19:56:45
aeth
You have a sequence, you can locate the key, and you know the value is one after the key.
19:58:39
aeth
Now, one complication is if there's a string that matches the text of the key as a value that shows up in the sequence before the key. So it isn't trivial.
19:59:09
aeth
Once you get the position, you'd probably have to check that it is even, and if it's not, search the sequence again, starting from that point.
19:59:42
Bike
fuck that, (loop for (key value) on list by #'cddr when (string= key to-find) do (return value))
20:01:54
krwq
Bike: thanks, I just got identical code based on http://stackoverflow.com/questions/9310913/how-to-get-two-elements-from-a-list-each-time-in-common-lisp :D
20:05:22
aeth
(defun getf* (sequence key &optional test) (let ((candidate-position (position key sequence :test test))) (if (evenp candidate-position) (elt sequence (1+ candidate-position)) "This is an exercise for the reader")))
20:06:20
aeth
Works on any sequence, and with any test. Doing it with dotimes instead of position would even get rid of the edge case where the key could be in the value spot
20:06:52
krwq
aeth: this is interesting although i find a loop syntax much easier to read for this thing
20:08:42
aeth
varjag: it's possible that sbcl optimizes it if getf* is inlined and it knows that it's being used on a list instead of a generic sequence
20:09:27
krwq
varjag: looks good and probably as fast as loop - my vector has less than 1k entries so perf is irrelevant
20:10:04
krwq
i like looking at alternative answers as aeth gave because i always remind/learn something new
20:10:21
aeth
i.e. this: (defun bar () (let ((foo (list "foo" "bar" "foo2" "quux"))) (getf* foo "foo2" 'equalp)))
20:14:50
aeth
varjag: You're right, but there was an easier way, and that was to disassemble. The disassembly shows that it calls #'nthcdr, so it doesn't optimize.
20:15:20
krwq
i sometimes wonder what kind of project are you guys doing that you fight for every nanosecond
20:15:58
aeth
varjag: I really need to use this heuristic more: when I think of measuring the behavior of a function, I usually can just disassemble and often a comment in the assembly tells me what I'm looking for.
20:18:05
krwq
does drakma have some pagination handling bultin? im parsing that by hand right now but after i finished im wondering
20:19:54
krwq
btw sorry for asking newbie questions but i.e. for most of the stuff i use one or two functions while for sexps there is like 45 different ones and i keep feeling like im reimplementing stuff
20:39:16
aeth
dxtr: All emptyp (in alexandria) does is check (null sequence) for lists and (zerop (length sequence)) for the rest.
20:39:30
aeth
As I learned earlier, code that's generic for sequences usually has to handle lists specially. <_<
20:39:58
Bike
given that there are only two kinds of sequences, treating one of them specially doesn't seem surprising
20:51:02
hjudt_
do people here use emacs auto-complete or helm? both or only one of those, and in the latter case which one?
20:54:25
hjudt_
i saw a video about slime in which helm or auto-complete are used, but since i do not know either i can't tell which one it is. so first i thought i'd try auto-complete, but then when investigating further it seems helm does provide even more.
20:58:21
axion
auto-complete uses a popup menu to incrementally complete as you type, much like helm, but is usually used for completing language symbols and the like. helm is a menu system for creating interactive emacs buffers, which is usually used for just about anything, such as running commands (like the helm-M-x M-x replacement)
21:00:37
axion
Another difference is that helm is invoked, and then you incrementally type. Whereas in auto-complete, you type, then initiate auto-complete and incrementally type.
21:01:53
hjudt_
i see. so auto-complete is actually a bit more convenient for completing language symbols, right?
21:02:32
axion
auto-complete and company-mode perform the same task. helm and ido perform the same task.
21:05:20
hjudt_
ok. so i'll look a bit more into auto-complete vs company-mode first. maybe helm/ido next.
21:05:44
axion
I don't know. I've never used ido. IIRC though, ido only uses the minibuffer whereas helm creates a new temporary buffer.
21:05:49
hjudt_
for slime/cl interaction, is company mode better than auto-complete or vice-versa or does it even matter?
21:07:18
aeth
Bike: There aren't two kinds of sequences. http://www.lispworks.com/documentation/HyperSpec/Body/t_seq.htm
21:07:21
aeth
"The types vector and the type list are disjoint subtypes of type sequence, but are not necessarily an exhaustive partition of sequence."
21:09:08
Bike
i've tried writing code with extended sequences, if they're not basically arrays you have to do something special if you want any efficiency, no big surprise
21:09:58
aeth
Right. My point isn't that you don't know that, but that all this code that are effectively (if sequence (if list (foo) (bar))) won't necessarily work well.
21:11:26
malice
Hi! I'm using SBCL and I've noticed that when I use (describe #'some-function) I get lambda-list. e.g. (describe #'expt) gives me(amongst other things) Lambda-list: (BASE POWER).
21:13:42
Bike
the standard function function-lambda-expression might also give you something, but usually doesn't
21:18:49
malice
In Haskell afaik you can do something like myfunc = otherfunc. It's useful for defining aliases and there were occasions when I wanted to do that in CL, but afaik there's no simple way
21:19:23
malice
I thought that if I could get the lambda-list, I could define "defalias" that would work similarly, so you could do (defalias my-new-func oldfunc) and the function would be exactly the same
21:47:25
dxtr
What's the most efficient for potentially large lists? Keep adding at the end or pushing to the front and then reverse the list/
21:49:52
dxtr
yeah, well, adding to the end seems cpu inefficient and reversing it seems memory inefficient
22:38:39
malice
dxtr: from my small research it looks like push + nreverse seems like the best idea of the two you suggested
22:39:03
malice
push is O(1), nreverse looks like O(n) or better, and adding to the end will be O(n) and N will be growing
23:03:02
learning
i remember doing a project euler problem where I had to call reverse on a giant list, it took forever regardless if i used nreverse or reverse.
23:11:41
Bike
if you're interested in the history of the pretty printer you should look up, what's it called, XP
0:55:54
aeth
If I make a top level variable without earmuffs and then I use that name that's special elsewhere, is it doing something different than if that doesn't exist at all?
0:58:44
aeth
Does that also mean that if I call a function, and that function uses foo, it'll use the new foo?
1:00:37
aeth
Are there globals that aren't special? It doesn't look like it, except maybe constants.
1:02:04
aeth
I'm trying to reuse Lisp's variable environment for a language that compiles to Lisp. This should work fine for lambdas/functions. I am not sure how I could handle a global lexical environment, though.
1:03:15
aeth
e.g. it would be great if I could just (funcall foo 42) to call foo if foo is defined locally, but still get the global definition of the foo if foo does not exist locally.
1:04:01
aeth
I could perhaps just put it all in one big let, but then I don't think I can add new bindings, which might only be an issue in the REPL of the language.
1:04:51
aeth
I mean, I could probably just (setf bar 99) within the "global" let and hide SBCL's warning, but it might not be a warning on all CLs.
1:06:52
aeth
What I mean is something like this, to fake both global lexical variables *and* Lisp-1: (let ((foo #'car)) (funcall foo (list 1 2 3)))
1:07:52
aeth
oh, that wouldn't work, though, because then none of the defined functions could use a "global" lexical. Hmm.
1:08:19
Bike
i think if whatever you're compiling uses variables very differently from lisp you shouldn't use lisp variables for them. or you could do a little analysis and find references to variables with no corresponding lexical binding.
1:11:51
aeth
Bike: It's only different from Lisp in that there's (1) one namespace, (2) the globals behave differently.
1:13:19
aeth
Hmm... Maybe I could turn every (foo 1 2 3) into (funcall foo 1 2 3) if foo is defined locally and otherwise (funcall (gethash foo *globals*) 1 2 3)
1:23:34
aeth
Is there even a way to check that a variable is bound without keeping track of all variables while compiling to CL?
1:24:22
aeth
A lazy route could be a runtime check, but even that seems impossible because boundp appears to only check for globals: (let ((asdf 1)) (print (boundp 'asdf)) asdf) ; prints NIL
1:33:57
aeth
And I have to go through everything anyway, for continuations. Now I just need to also track the variables defined by lambdas. The hardest part is lambdas-in-lambdas.
1:39:32
aeth
Bike: Yes, because now I need to know where the lambda is, and I cannot just process lambda outside of context.
1:42:19
aeth
Bike: If I am handling (lambda (foo) (+ foo bar)) I now need to know if lambda is contained in another lambda that has bar defined or if bar is in *globals*, whereas if I could find some way without having something like *globals* I don't need any information about bar.
1:44:13
Bike
(defun compile (form env) (cond ((symbolp form) (if (find form env) form `(gethash ',form *globals*))) ((eq (first form) 'lambda) `(lambda ,(second form) ,(compile (third form) (append (second form) env)))) (t `(funcall ,(compile (first form) env) ,@(mapcar (lambda (f) (compile f env)) (rest form))))))))))))))
1:47:08
Bike
and put it in CPS while you're at it. left as an exercise to the reader and all that silliness
2:53:00
beach
This one? : http://www.nbcnews.com/feature/college-game-plan/should-computer-coding-be-considered-foreign-language-school-some-say-n543656
2:53:23
Bike
the channel guidelines mention that logs should be published with care and to inform users if it's happening (which is why it says "logs" in the topic)
2:53:36
beach
Or this one? :https://github.com/TeamSPoon/pfc/blob/master/prolog/pfc2.0/mpred_loader.pl#L404-L413
2:55:02
beach
https://github.com/TeamSPoon/PrologMUD/blob/development/pack/logicmoo_nlu/prolog/e2c/subl-grep.lisp
2:58:58
dmiles
found it https://pdfs.semanticscholar.org/d87e/a800c08616e21e915f5b018150aa10b94231.pdf
2:59:29
loke
Last week, someone recommended a library that allowed one to define binary datatypes (i.e. decoding a binary structure, such as a network packet) into structs. One of them was binary-types, but there was at least one more.
3:01:41
dmiles
hrrm not in ##lisp or #lispcafe or #lispgames (i have enough scroolbakc i was thinking to find it)
3:10:27
dmiles
<eazar001> dmiles: it's against freenode policy unless the channel topic _explicitly states_ that the channel is publicly logged.
3:53:08
SoraFirestorm
and I want to work my assembly emitting code into macro(s) to make it easier to read and write
3:54:15
SoraFirestorm
I'm having trouble figuring out what to do if I want to quasiquote the arguments
3:54:40
SoraFirestorm
Say something like (mov `(:immediate ,foo) (:register :eax)) for the instruction if I want a variable
3:55:34
SoraFirestorm
Maybe I'm in the wrong frame of mind, but I can't really see a way to do it without eval
3:59:21
Bike
you could have something like, have it expand to (emit-out "mov ~a ~a" (decode-value 5) (decode-register :eax)). and then if you had (emit (mov (:immediate foo) (:register :eax))) that could expand to (emit-out "mov ~a ~a" (decode-value foo) (decode-register :eax)), so foo is evaluated normally.
4:00:54
SoraFirestorm
for the most part, decode-instruction-arg calls what is essentially decode-value and decode-register anyways
4:02:37
Bike
well, i mean, if you pass something '((:immediate foo)) at runtime it'll have to eval, which shouldn't be the case.
4:05:29
aeth
Is it possible to add continuation passing style to CLOS? I mean clearly I can just (defmethod foo-bar (continuation (foo foo) (bar bar))) but that doesn't affect the stuff CLOS generates itself like accessors, and things like initialize-instance
4:07:40
Bike
SoraFirestorm: with backquoting i'd do something like (emit '(mov (:immediate 5) (:register :eax))) and (emit `(mov (:immediate ,foo) (:register :eax))) where emit is now a function
4:09:47
aeth
Bike: There are actually two distinct use cases. Using CLOS directly (through a define-class, define-generic, define-method, etc.) within the language that compiles to CL, and using objects, methods, etc., defined from CL from within the language that compiles to CL.
4:11:32
aeth
Calling functions defined from the Scheme will be pretty easy. As are calling CL functions, both directly and through using CL to define built-in procedures (the language is mostly written in CL).
4:11:43
Bike
you can do obvious things like (defun cps:initialize-instance (cont &rest args) (funcall cont (apply #'cl:initialize-instance args)))
4:12:15
SoraFirestorm
Bike: maybe it would be possible to have all instruction args get APPENDed to (list)?
4:14:29
aeth
Bike: yes, that's basically what I do already for the built in functions, with the added conversion of nil to :false where applicable.
4:15:09
aeth
Bike: and then I'll have a scheme-funcall to allow directly calling such functions and a cl-funcall for the opposite direction. I'm just not sure if it's ideal for generic functions
4:15:39
aeth
(And I'll probably have to add to the compiler some sort of inlining system for simple functions like + so performance isn't hurt.)
4:18:11
aeth
Bike: I'd want the accessors to have CPS automatically, since if they're defined from within the CPS system, they'll probably need to be called specially anyway
4:18:53
aeth
e.g. (scheme-funcall 'x point) to use the horrible example of a point that shouldn't be implemented through CLOS
4:19:53
aeth
The most trivial way of handling that would be (x #'identity point) assuming that the continuation is always in the first position, but there will be added complications that make that a bit trickier (e.g. requiring at trampoline because tail recursion cannot be guaranteed, and making sure *globals* is visible)
4:20:52
Bike
you could make CPS accessors with a special defclass macro, or with MOP in some weird way i'm sure
4:26:00
aeth
I should probably make define-class a built-in form that's a thin wrapper over mostly-CL logic, so I don't have to CPS tons of things, only the final interface.
4:28:33
aeth
The reason is because Pseudoscheme is a mostly (not fully complete) r4rs (i.e. ancient) that afaik is not actively maintained.
4:29:32
aeth
I also need to do the hygienic macros, and rewrite the reader that I wrote when I wasn't as good at CL (but I might be able to keep a lot of it)
4:29:50
aeth
But because I worked at the right level of abstraction in defining the built-in procedures, I do have about 2/3 of the language
4:31:09
aeth
e.g. (define-scheme-procedure (sin z) (sin z)) which at the moment creates a %s-sin with two arguments, the first being the continuation (it needs to go first because of functions with optional/rest arguments)
4:31:58
aeth
It's a mostly, but not entirely easy process, that just has to be done lots and lots of times, with careful reading for when the meanings actually differ.
4:47:31
SoraFirestorm
I just realized this approach has made something not-entirely-unrelated kinda difficult
4:47:57
SoraFirestorm
I've been writing in such a way so as to make the assembly emitter somewhat platform agnostic
4:49:21
SoraFirestorm
I want to add ARM as a target, but am developing on x86 as it makes testing faster
4:53:24
SoraFirestorm
that means that eventually I'll have to grow my own assembler and several other facilities that I don't have yet
4:54:03
Bike
i mean: platform independent assembler sounds impossible, but you could have a portable, like, assembler infrastructure
4:56:44
aeth
Personally, I think that all languages should compile to an extended Common Lisp, sharing a runtime. (extended is necessary because e.g. unicode, threads, etc.)
4:57:06
aeth
If you're making a Lisp, you could make it a Common Lisp, and give it some special extentions if necessary for your own Lisp that can compile to that Common Lisp. Then you instantly get tons of libraries.
4:59:43
SoraFirestorm
if I could just strip out the cross-compiler bits, I would just start from there. It'd be loads easier.
4:59:47
BusFactor1
The "Emacs Lisp Programming Environment (ELPE)" now available in the macOS App Store: https://itunes.apple.com/ca/app/emacs-lisp-programming-environment-elpe/id1217644998?mt=12
5:03:04
aeth
I started out working how to represent vectors and cons pairs in the Brainfuck that I wrote the other day so that I could put Lisp on Brainfuck on Lisp (and if I implemented enough Lisp to implement the Brainfuck, I could keep recursively running it until it was too slow to run anymore)
5:03:27
aeth
I still might do that because it sounds so ridiculous, but that got me to go back to my cl-scheme, which is both more useful and easier.
5:04:25
aeth
BusFactor1: Right, but Brainfuck is pretty basic. I think I'd actually have an easier time targeting a simple instruction set like RISC-V.
5:04:41
beach
SoraFirestorm: I mean, you seem to use Common Lisp already for writing the compiler(s). No?
5:07:03
beach
SoraFirestorm: But then you have to dumb down the code for your Common Lisp implementation since you don't have access to the full Common Lisp language.
5:07:26
aeth
beach: I've considered implementing a minimal, lower-level Lisp for CL implementation before... or at least the GC portion of the implementation.
5:08:06
SoraFirestorm
tbh I'll be lucky and amazed if I can actually eventually target the metal with my bootstrap Lisp
5:08:09
beach
SoraFirestorm: Isn't that what your CL implementation will have to do once you finish your bootstrap Lisp?
5:09:56
SoraFirestorm
Just trying to not make the project any more impossible than I've already made it
5:16:45
beach
SoraFirestorm: The way you expressed it ("cross-compile SBCL") sounded like Mezzano was using SBCL code as its source.
5:19:22
beach
The code for SBCL is very much tied to how the SBCL implementation works in great detail, so using SBCL source code for just about anything would just be, well, SBCL.
5:20:11
beach
SoraFirestorm: But SBCL is a very conforming implementation, so using it to run Common Lisp code for some other compiler, such as that of Mezzano, is quite doable.
5:22:16
beach
SoraFirestorm: Sometime in the future, when you think you are through with your learning experience, come back and ask me and Bike about SICL and Cleavir. Cleavir is an implementation-independent compiler framework that is currently used by SICL and Clasp. And jackdaniel has plans to write a compiler for ECL using Cleavir as well.
5:27:31
froggey
SoraFirestorm: mezzano uses sbcl as a cross-compilation host, running the mezzano compiler on it to build the initial lisp environment. once that's built & running, the compiler is loaded and runs natively on mezzano
5:31:11
Bike
all you have to do to be a wizard is sit around in a dingy old tower library for a while
5:37:43
SoraFirestorm
so I suppose then that I'm technically taking the route that Mezzano is, just that my Lisp isn't a CL?
5:43:53
beach
SoraFirestorm: Aside from the language you are using, what kind of compiler optimizations are you considering, if any?
5:46:04
SoraFirestorm
*eventually* (should I get a bare metal target working) I want to do some basic optimizing