freenode/lisp - IRC Chatlog
Search
21:55:57
oni-on-ion
slime-highlight-edits is fairly cool. but how do i clear them without toggling the mode ?
21:58:24
Baggers
this might be a goofy question but what would be the suggested way to implement signed modular arithmatic of sized integers in cl? With unsigned integers I can use (ldb (byte ~size~ 0) ~expression~). Bonus points for approaches the implementation can recongnise and reduce to machine instructions (on two's complement machines)
22:08:24
Baggers
phoe: well the bonus part would probably be. But if the main bit is possible within the standard then that would be more interesting
22:13:25
pfdietz
Baggers: what exactly do you mean? Out of the box, Lisp's integer operations are the mathematical ones, so if you can express what you want with ordinary math functions CL can do it. Now, *efficiently*...
22:17:20
Baggers
I've had a touch to drink so 'exact' might not be in my current wheelhouse. What I'm asking is, given as desire to compute the result of (for example) addin two 8 bit signed integers where where the rest is an unsigned integer that wraps on overflow. How would you recommend doing it in cl. I asked assuming there were different ways of doing it and, not being versed in everything in the spec there might have been coo
22:18:01
Baggers
'rest is an unsigned integer that' should have been 'result is an 8 bit unsigned integer that'
22:33:52
aeth
This seems to do it: (defun foo (x y) (declare (type (signed-byte 4) x y)) (- (mod (+ x y (expt 2 3)) (expt 2 4)) (expt 2 3))) (loop :repeat 20 :for i := 0 :then (foo i 1) :do (print i))
22:34:31
aeth
Baggers: what I did looks like 5 instructions instead of 1 in SBCL but looks pretty fast. Obviously, it needs to stay within the fixnum size to stay fast
22:34:32
Baggers
pjb: I expect I'm mucking up the terms. By modular arithmatic I mean the numbers wrap, by signed i was meaning i'm interested in signed integers rather than unsigned ones
22:35:40
pjb
Baggers: you seem to have some misconception about what is a number, and what is a modular number. Notably you don't seem to be quite clear on the difference between a modular number, and a representant of that number.
22:36:46
aeth
alternatively you can convert on either side of the calculations, e.g. (defun ub32-to-sb32 (number) (declare (type (unsigned-byte 32) number)) (multiple-value-bind (quotient remainder) (truncate number (expt 2 31)) (- remainder (* quotient (expt 2 31)))))
22:37:02
aeth
that will be more expensive for one calculation but if you do e.g. 100 that conversion probably will win
22:39:05
aeth
or wait, that's what you're doing anyway, so that's faster than my old conversion function
22:40:38
Baggers
pjb: quite likely. I'm happy for you to restate the problem in a precise way if you fancy
22:42:00
Baggers
pjb: I took the term 'modular arithmatic' from the sbcl manual and I assumed that combining that with something to clarify I was only interested in signed integers would be enough. Clearly not though
22:42:08
pjb
Baggers: well, the question is whether you really want just modular arithmetic (in which case, just use MOD), or if you want to find the representants in some integer interval?
22:42:59
pjb
Baggers: Also, notice that in C, modular arithmetic is only specified for unsigned integers. For signed integers, the behavior is implementation dependent.
22:44:10
Baggers
pjb: indeed, which is why I didnt ask for C's behaviour as that would only confuse things.
22:46:35
pjb
Baggers: so if the question is to find representants in the range (- (expt 2 (/ p 2))) .. (- (expt 2 (/ p 2)) 1): (defun signed-representant (n modulo) (if (<= (expt 2 (- modulo 1)) n) (- n (expt 2 modulo)) n)) (signed-representant 61 6) #| --> -3 |# assuming the modulo you're interested in are powers of 2.
22:47:39
pjb
yes. (defun signed-representant (n p) (if (<= (expt 2 (- p 1)) n) (- n (expt 2 p)) n)) or (defun signed-representant (n modulo) (if (<= (truncate modulo 2) n) (- n modulo) n))
22:50:31
Baggers
pjb: 'just use mod' is a fairly poor answer when the question was about sized integers. You address this in the code it seems. The reason I asked was that maybe there were more cool tricks people knew than the basic shit I knocked together, seeing different approaches can be helpful
22:51:57
pjb
"what would be the suggested way to implement signed modular arithmatic of sized integers in cl"
22:52:22
Baggers
pjb: ok, maybe I should have asked about mimicking x86s add instruction (where wrapping is defined for signed and unsigned)? But in my mind that distracted from the problem
22:53:44
pjb
Baggers: well, that's yet another question. X86 and most processors use 2-complement representation for negative numbers. This is a trick that means the same circuits can be used to process signed integers or unsigned integers.
22:54:52
aeth
Baggers: maybe ask in #sbcl if it's possible to get several of the obvious ways to do the calculation optimized in SBCL
22:54:54
pjb
The only thing is that the processor computes flags that can be used in different combinations when you want to test signed integers or unsigned integer, notably to test the overflow.
22:55:13
Baggers
and there is exactly why I didnt use that example. We are off on an x86 specific distraction
22:55:36
pjb
If you want to simulate the behavior of X86 add instruction, the best is to read the x86 reference manual. They are very precise about it.
22:59:34
pjb
Baggers: now about integer size, one problem is that in CL, integers are all of infinite size. 2-complement is used to represent them, but on an infinite length. Negative integers are prefixed by an infinite number of 1s, and positive integers by an infinite number of 0s.
23:00:52
aeth
pjb: eh, not quite. integers are infinite size, but you can work with subtypes... it's just that you have to stay within the subtype yourself
23:01:18
Baggers
so, let's assume there is some integer thing which wraps at 127 back around to -128. What would me to call that so I can ask a question is a palatable way?
23:02:50
Baggers
aeth: i know, but pjb wants to talk about things a very specific way, so I'm asking what works for them
23:03:00
aeth
pjb: well, yes, and they are probably all represented as fixnums or bignums, unless in something like an array with an element-type, or perhaps a struct with a typed slot
23:03:46
aeth
(and I know that SBCL does a weird thing where (signed-byte 64) and (unsigned-byte 64) aren't necessarily bignums in certain restricted circumstances)
23:04:59
aeth
I think the real issue, though is, "Can we get the compilers to optimize the high level into the low level here?" It would reduce the 5 or so instructions into fewer instructions if it's possible.
23:05:08
pjb
(defun signed-representant (n modulo) (if (<= (truncate modulo 2) n) (- n modulo) n)) (signed-representant (modular+ -100 60 128) 128) #| --> -40 |#
1:31:00
gaze___
hey, super basic question, but how do I fundamentally identify operations that cons? I understand what a cons cell is, where the name comes from... I'm trying to understand what people mean when they talk about "careless consing"
1:32:32
no-defun-allowed
writing a GC-less lisp involves not writing a lisp because it is trivial to create circularity with closures, conses and other data structures
1:33:14
no-defun-allowed
or, since the CL standard technically doesn't require a garbage collector, it involves wasting all your memory very quickly
1:35:48
aeth
gaze___: You can detect consing pretty easily in SBCL through lots of different ways. e.g. you can disassemble and the consing is commented in SBCL. I think the only exception is when it's done in a function call, but the non-inline function calls are also commented.
1:37:02
aeth
You can also sb-profile:profile some functions and then sb-profile:report to see if they allocate anything. Unlike the previous method, this will give you consing even for functions that are called by the function being profiled, unless the function that is being called is also being profiled iirc.
1:38:04
aeth
gaze___: ironically, I think SBCL with carefully used GC will probably provide better real-time performance than that because SBCL is very mature
1:38:24
no-defun-allowed
ACTION thinks of a way to put her opinion towards lisps minus the lisp parts politely
1:39:27
aeth
gaze___: Real-time programming in CL is not about avoiding the GC altogether, it's about controlling when it happens, which means you avoid doing it within the hot loops, but don't avoid allocations altogether. You probably pre-allocate it before the loops begin. Not really good for stuff like microcontrollers, though, because you probably wind up using *more* memory this way.
1:41:37
gaze___
ulisp is really cool. I'm particularly interested in a tethered compiler where you run a compiler on the host system and shoot code over to the microcontroller as you write functions... but it still maintains enough interactivity that you can peek and poke registers and experiment with drivers
1:41:58
no-defun-allowed
can't really guess what board is closest, but it suggests pause times of around 1-3ms usually
1:42:24
oni-on-ion
most langs/runtimes/plats have sexp, its a short hop from that to having custom actual lisp
1:42:40
no-defun-allowed
dunno how the GC is set up, but it would be useful and interesting to use incremental mark-sweep or some other "real-time" GC
1:43:54
aeth
gaze___: This is how I deal with avoiding garbage collection pauses in my real-time CL application (at least in SBCL), but it won't really apply to very weak platforms... e.g. one of the points is to only use 64-bit implementations because then fewer things are heap-allocated. https://gitlab.com/zombie-raptor/zombie-raptor/blob/41e9e6553a83015d67e14aad5b46f60dcf40b862/CONTRIBUTING.md#consing-heap-allocations
1:44:32
oni-on-ion
always forget CL has no tail calls; but i've a feeling its not too tricky with some macro magic
1:45:30
no-defun-allowed
you can use a trampoline system to do tail calls, provided you have some loop that consumes them outside your tail calling functions
1:45:35
aeth
oni-on-ion: It's "easy"... you just return a thunk and call the thunks in a loop. This is called a trampoline.
1:46:22
aeth
I benchmarked it against SBCL's actual TCO (which isn't enabled on all optimization levels) and it doesn't seem to noticably impact performance. I think it might make multiple return values more complicated, though.
1:47:01
aeth
But it's definitely more doable for a mini-language than for adding it on top of CL because you'd probably need to do something like run a code walker if you wanted it to work on arbitrary CL
1:47:43
no-defun-allowed
sorry i got cranky gaze___, people calling things lisps that aren't (and i'm very lenient on that; dynamic typing, late binding, macros and conses are basically all i want) annoys me
1:50:50
oni-on-ion
neat, Carp is written in HS i did not know that. also reminded of how ugly HS can get! =)
1:51:31
no-defun-allowed
i would say "maybe this is more relevant for ##lisp" but maybe this is more relevant for #haskell at this rate
1:51:31
gaze___
I feel like HS can be as readable or as opaque as the author feels like making it... much like lisp
1:52:41
no-defun-allowed
i'll be back in a bit, prolly should have breakfast/lunch and not work myself up
2:49:40
aeth
https://github.com/slime/slime/blob/e6d215d77148079799d2fc3253ef402b5d9ed4d7/contrib/slime-cl-indent.el
3:14:53
aeth
White_Flame: afaik, all of the old standards were basically superseded by SLIME and any other programs should be a reliable clone of that file
3:15:08
aeth
now, of course, that could probably push the question to where SLIME got its exact behavior
3:15:47
White_Flame
it is kind of annoying, though, that the only control over indentation that seems to exist is &body vs &rest
3:16:07
aeth
Without modifying emacs, yes. You do need to be able to if you e.g. want something that indents like FLET
3:16:51
White_Flame
for full DSL sublanguages, where the entire structure is handled as a single list, there's no real way to declare houw it should indent
3:39:50
juliusdeane
I have a decent knowledge of functional programming and don't really like clojure. Which flavor of lisp do you think would be most practical for someone like me to learn?
3:43:34
beach
juliusdeane: This channel is dedicated to Common Lisp, so we are biased in favor of Common Lisp.
3:45:15
beach
juliusdeane: The functional programming style is used in Common Lisp mainly in macro expanders. Modern application code written in Common Lisp uses object-oriented programming (using CLOS generic functions) a lot.
3:53:11
beach
Depends on your needs. Most people here probably use SBCL. Other popular choices are CCL and ECL.
3:56:33
oni-on-ion
White_Flame, hmm using lang modes in certain blocks? if slime/emacs were extendable in this way i am not sure. but it works great and automagically in org-mode files which mix different languages source code blocks
4:39:11
aeth
juliusdeane: In case you're wondering, ##lisp is the Lisp family channel. Most of the other major Lisps are Scheme, so #scheme might also be relevant, if you want to consider your options. As beach said, this is the Common Lisp channel, so we are biased.
4:39:36
aeth
(With Scheme the line between dialect and implementation is a bit blurred, unlike with Common Lisp, where almost all code is portable.)
4:41:43
aeth
juliusdeane: SBCL is the most popular and CCL is the second most popular. SBCL usually produces the fastest code. On the other hand, CCL's compiler is faster (as in, lower compilation times) and it has some macOS integration. ECL is "Embeddable Common Lisp", designed to be embedded in other applications. e.g. it has libecl.so, which could make interfacing with it easier.
4:41:56
gabbiel
hey guys. I have a macro "synonymize-function" which basically defines a new function which does the same as an existing function
4:44:10
beach
gabbiel: Functions don't have any such ability. When you see something that works with SETF, it is either because it is a separate function named (SETF <symbol>) or because that something has a SETF expander.
4:45:27
gabbiel
I tried setfing the fdefinition of (setf new-definition) to the fdefinition of the existing function, but that only works with functions that have "setftability"
4:45:55
gabbiel
beach: I understand, but how else can I communicate when a function also has a setf version
4:47:12
aeth
gabbiel: iirc, setf can have a function or a macro, and the "or a macro" is going to be the hard part.
4:47:39
beach
gabbiel: There is no relation between the function FOO and the function (SETF FOO). You need to manipulate the two separately.
4:49:03
aeth
gabbiel: There doesn't have to be a relation, though. You could create one with a separate API from the corresponding regular function (if there even is one), it will just mess with e.g. SLIME's minibuffer which afaik prints the non-SETF version's API
4:51:05
gabbiel
that's a relation, and also by the fact they work with the same concept. i.e. the car is a place, and to setf a car, means setting that place
4:51:31
beach
gabbiel: Sure, but you can't find the function named (SETF CAR), given the function named CAR.
4:51:51
aeth
gabbiel: well, one's a getter (accessor in CL terms) and one's a setter (writer in CL terms).
4:52:19
gabbiel
it'd make sense that if we're synonimizing a function to another, we should synonymize their setf functions
4:52:26
beach
gabbiel: You need to have the symbol CAR. Then you can find both CAR and (SETF CAR), and as I recall, (SETF CAR) may not exist. It could be a SETF expander instead.
4:54:26
beach
gabbiel: There is no relation between the function FOO and the function (SETF FOO). You need to manipulate the two separately.
4:54:31
beach
gabbiel: You need to have the symbol CAR. Then you can find both CAR and (SETF CAR), and as I recall, (SETF CAR) may not exist. It could be a SETF expander instead.
4:55:50
beach
"In general, the exact macro expansion of a setf form is not guaranteed and can even be implementation-dependent; all that is guaranteed is that the expansion is an update form that works for that particular implementation, that the left-to-right evaluation of subforms is preserved, and that the ultimate result of evaluating setf is the value or values being stored. "
4:55:57
aeth
one thing you might be able to do is (get-setf-expansion `(car x)) as long as you're able to get the function's lambda list and as long as that lambda list matches the setter's (it doesn't have to!)
4:58:14
aeth
gabbiel: if you want the setter to match, you should probably have it as a separate argument imo... e.g. (#'car #'(setf car))
4:59:20
gabbiel
what about the setf expander thing, that seems more complicated, I guess I'll do that separate argument thing
5:04:02
gabbiel
the limited functionality kills me, Ideally, i'd want to be able to handle the expanders as well
5:32:57
gabbiel
I was thinking that too, now all I need is to know how to determine if its a normal setf function, or an expander, of it has none of them
5:35:45
gabbiel
I'd like to define a new function called new-name, which does what old name does, inhertis documentation, args, and the setf function/expander.
5:39:41
gabbiel
a recipe is a list, whose name is the car, now I'd like to calle recipe-name instead of car for readability purposes. and what if I want to change the name of a recipe? I'd rather also call (setf (recipe-name recipe) new-name) than (setf (car recipe) new-name)
5:41:10
LdBeth
gabbiel: then you shouldn’t relay on the global namespace but use something like a hash table
5:43:21
LdBeth
gabbiel: I mean what people usually do is replace the occurrence of recipe-name to new name in the source code
5:44:16
gabbiel
I was thinking of using struct, since I know you can represent them as lists, I'm not sure one can setf the same, but regardless, this macro seems useful to me
5:46:37
gabbiel
that seems a hack, and what if I have (setf (car recipe)), not it wouldn't work because recipe-name has no "setfability"
5:47:43
gabbiel
that's why im trying to get it to inherit everything from car, instead of defining it and its setf function and then doing the textual replacement
5:48:58
gabbiel
I fogot defstructs can be represented as lists, and I stuck with lists because they can easily be printed to a file and retrieved later
5:51:27
LdBeth
gabbiel: usually an accessor could implement checks to see if the argument supplied is a “well formed list”, ie not longer or shorter
5:53:07
no-defun-allowed
gabbiel: these can't be printed obviously: #c(1.0 1.0) #(1 2 3) #2a((1 2) (3 4)) #'foobar #p"/bin/sh"
5:55:28
gabbiel
pretty cool that structs are serializable, I thought they werent cause of that #, but now I know
5:58:27
gabbiel
still though, if I were to use structs in list form, (which defines getters and setters) it'd only do so for the first level of the list/tree. I have stuff like recipe-notes which is defined as the third of the second element in the tree, or the caddadr
6:00:38
gabbiel
I still want the synonymize-macro and synonymize-function macros, I'll have to study up on get-setf-expansion, defsetf, and friends to know what to do
6:32:42
makomo
gabbiel: maybe you could use GET-SETF-EXPANSION to do what you want, i.e. discover whether your place is defined using a SETF expander or a SETF function
6:34:18
makomo
you would first check whether the function (SETF <symbol>) exists. if it does, you're done. otherwise, a SETF expander for it might exist, so you use GET-SETF-EXPANSION to retrieve the expansion of the place
6:34:41
makomo
if that expansion *didn't* expand into a call to the function (SETF <symbol>), then a valid SETF expander was provided
6:36:05
makomo
(GET-SETF-EXPANSION will return an expansion that calls (SETF <sym>) if no SETF expander exists for the place, even if (SETF <sym>) itself doesn't exist)
6:38:39
makomo
gabbiel: also, regarding your synonimization, i think the name you're looking for is "aliasing"
6:40:10
makomo
gabbiel: btw, how to actually check that GET-SETF-EXPANSION didn't return an expansion that calls (SETF <sym>)? i'm not sure
6:44:08
makomo
but also, as people already pointed out, just because a place is of the form (<sym> ...) doesn't mean it has any relation to the function <sym>. it might take totally different parameters or a different number of them as well
6:45:41
makomo
(this would be a problem when trying to call GET-SETF-EXPANSION, because you need to give it a place of the form (<sym> ...))
7:14:46
gabbiel
generally, if (symbol object) is a place, and we want to change it, we use (setf (symbol object) value)
7:17:30
gabbiel
but to cover those cases, I'd do like someone said, to have an optional parameter detailing the setf function, idk what do do in case its a setf expansion though