<didi>
I think I've never deeply messed with packages, aside from exporting some symbols.
<equwal>
They're important. Just make a package so you wont clobber cl-user and you're good to go.
<didi>
equwal: Ah, yes. I do it like that. I have some packages (and their systems). But I don't think I've played any advanced game yet.
<equwal>
Like no ASDF?
<didi>
equwal: s/systems/ASDF systems
<equwal>
If you are working from in a package you can make it external but not import it so you access it with package-name:intersection leaving the standard alone.
fikka has joined #lisp
<equwal>
Within the package you would probably shadow it.
<equwal>
Try running (defpackage test) (in-package :test) in repl.
<didi>
equwal: Thank you. I just tried a little shadow dance with `+' and it worked. Cool.
fikka has quit [Ping timeout: 252 seconds]
esper0s has quit [Read error: No route to host]
fikka has joined #lisp
fikka has quit [Ping timeout: 240 seconds]
terpri has joined #lisp
meepdeew has quit [Remote host closed the connection]
robotoad has joined #lisp
<equwal>
How can I change a regular character like #\f to a read macro without a dispatch character? This way I can call a read macro as if it were a function (fn...)?
mejja has joined #lisp
<Bike>
set-macro-character
<equwal>
Yes but the problem I have is that I can't do it without breaking the reader.
<Bike>
Breaking?
<Bike>
also i don't know what you mean by the "as if it were a function" bit.
<equwal>
Well the idea is to do something like (brainfuck ++>+)
<Bike>
that doesn't seem like a reader macro
<no-defun-allowed>
don't think you need one
<Bike>
you want to do, like, arbitrary parsing, but also keep parentheses working?
<no-defun-allowed>
only downside of that is it interns the code
<equwal>
I got it working like this: #defmacro/g! name (z) `(let ((,g!y ,z)) (list ,g!y ,g!y))
fikka has joined #lisp
arescorpio has joined #lisp
<equwal>
It does parentheses by just counting until there is an extra one on the right. I am trying to set it up such that it can be called with (defmacro/g!...) making #\d the macro-character. Unfortunately I can't do it without making it impossible to defun declare, etc.
<Bike>
yep.
Mr-Potter has quit [Quit: Leaving]
<equwal>
Just impossible?
<Bike>
putting a reader macro on d means when the reader sees a d, you take over parsing. you can't just do it halfway.
<equwal>
So I need to reimplement the whole reader.
<Bike>
if i were you, i'd use a special reader macro for the body instead.
<equwal>
how so?
<Bike>
so you do something like (defmacro/g! name params #`(... ,g!z ...))
<equwal>
Well I could do that, but I was hoping to get it semantically the same as the book so I could send it to the production code repo.
<equwal>
Which means it needs to be a fake function.
fikka has quit [Ping timeout: 240 seconds]
<equwal>
I wonder if the SBCL reader has hooks I can hack into?
<Bike>
there is no such thing as a fake function. i'm not sure where you got the idea that there was.
<Bike>
the sbcl reader has hooks in the form of reader macros.
<equwal>
I could get it to work if, for example, I set the reader to activate a reader macro if it reads "DEFMACRO/G!"
<Bike>
right, you cannot do that, and sbcl does not have hooks for that.
<Bike>
as an example, if you had '(defmacro/g! ...), with your scheme funny things would happen.
<equwal>
Well it is true you wouldn't be able to define defmacro! on top of it, for example.
d4ryus has quit [Ping timeout: 240 seconds]
<no-defun-allowed>
all i can suggest is to write a macro that takes the code as an argument, takes the SYMBOL-NAME of the symbol and uninterns it
<equwal>
I don't understand.
<equwal>
What symbol gets uninterned?
<no-defun-allowed>
your brainfuck code
<no-defun-allowed>
not a reader macro, just a normal macro which reads in your code as an an argument, eg (brainfuck [+.>])
<equwal>
Oh right yes.
<Bike>
clever, but doesn't seem helpful for the actual g! problem.
<equwal>
I used the brainfuck because I though I was simplifying my question. I don't see why what I want to do should be impossible. I think I can do it if I save the original readtable and access it before reverting and the closing parenthesis.
<Bike>
maybe. that's just, likke, kind of overcomplicated.
<Bike>
you're basically fighting the language here.
<equwal>
W
<no-defun-allowed>
yeah, i don't think that's the right approach
<no-defun-allowed>
if you want to do a readtable thing, #f[code goes here] could work better for syntax i think
<equwal>
ok.
<no-defun-allowed>
i think #f isn't taken...
<equwal>
It isn't I use it.
<no-defun-allowed>
what's it do then? don't remember that one
<equwal>
I mean it isn't taken, I use it for my brainfuck code.
<no-defun-allowed>
ah ok
nicdev has quit [Ping timeout: 240 seconds]
<didi>
I never used a read macro, but luv-slides has one that I might try some day: #L(if (oddp _) (* _ _) 0) -> (lambda (_) (if (oddp _) (* _ _) 0))
fikka has joined #lisp
neosloth has quit [Remote host closed the connection]
fikka has quit [Ping timeout: 252 seconds]
troydm has quit [Quit: What is Hope? That all of your wishes and all of your dreams come true? To turn back time because things were not supposed to happen like that (C) Rau Le Creuset]
troydm has joined #lisp
nicdev has joined #lisp
fikka has joined #lisp
<didi>
Argh. Format's call function directive is not too hot; I've to use colons to call functions from packages, even if it's a symbol interned in the same package I'm in.
fikka has quit [Ping timeout: 245 seconds]
<didi>
Any clever way to turn a cons into a list?
<didi>
Better than (destructuring-bing (a . b) cons (list a b)).
robotoad has quit [Ping timeout: 244 seconds]
arescorpio has quit [Ping timeout: 240 seconds]
<aeth>
didi: That seems like the best way
<aeth>
well, bind. I'm not a big fan of Bing.
<didi>
aeth: ;-)
<didi>
Thank you.
<aeth>
Any list/cons processing should directly or indirectly use destructuring-bind unless there's a built-in to handle it directly imo. Probably slows it down a bit but makes sure it is what you think it is.
<aeth>
Otherwise you can have things like an invalid tail, or an implicit NIL, etc.
<aeth>
(and if you actually don't care about the tail in a destructuring-bind it's not hard to do an ignored &rest rest)
<aeth>
In this particular case, most alternatives would probably work on NIL because (car nil) is NIL and (cdr nil) is NIL.
fikka has joined #lisp
robotoad has joined #lisp
<didi>
Silly format. If I didn't like you so much...
fikka has quit [Ping timeout: 268 seconds]
fikka has joined #lisp
<drmeister>
Is there any way to force the printing of package names with symbols?
robotoad has quit [Quit: robotoad]
fikka has quit [Ping timeout: 245 seconds]
equwal has quit [Remote host closed the connection]
equwal has joined #lisp
<drmeister>
Bind the *package* to (find-package "KEYWORD")
dddddd has quit [Remote host closed the connection]
_whitelogger has joined #lisp
fikka has joined #lisp
orivej has quit [Ping timeout: 240 seconds]
robotoad has joined #lisp
fikka has quit [Ping timeout: 245 seconds]
arescorpio has joined #lisp
arescorpio has quit [Max SendQ exceeded]
reverse_light has quit [Ping timeout: 246 seconds]
arescorpio has joined #lisp
mejja has quit [Quit: mejja]
fikka has joined #lisp
fikka has quit [Ping timeout: 272 seconds]
arescorpio has quit [Remote host closed the connection]
fikka has joined #lisp
<beach>
Good morning everyone!
fikka has quit [Ping timeout: 272 seconds]
fikka has joined #lisp
nicdev has quit [Quit: ERC (IRC client for Emacs 26.1)]
fikka has quit [Ping timeout: 245 seconds]
<fiddlerwoaroof>
morning beach
smokeink has joined #lisp
<fiddlerwoaroof>
elderK, equwal: LoL is a bit problematic because it doesn't restrict its macro definitions to things that are standards-compliant.
<fiddlerwoaroof>
So, in some cases, you might discover that implementations have implemented things in a way that breaks the examples.
nicdev has joined #lisp
<fiddlerwoaroof>
But, I learned the useful trick of expanding to a MACROLET in situations where one might otherwise try to write a codewalker from it.
_whitelogger has joined #lisp
fikka has quit [Ping timeout: 268 seconds]
_whitelogger has joined #lisp
dale has joined #lisp
fikka has joined #lisp
ggole has joined #lisp
fikka has quit [Ping timeout: 244 seconds]
buffergn0me has quit [Ping timeout: 250 seconds]
fikka has joined #lisp
rumbler31 has joined #lisp
rumbler31 has quit [Remote host closed the connection]
rumbler31 has joined #lisp
fikka has quit [Ping timeout: 246 seconds]
irdr has quit [Remote host closed the connection]
irdr has joined #lisp
fikka has joined #lisp
shifty has joined #lisp
equwal has quit [Ping timeout: 268 seconds]
fikka has quit [Ping timeout: 272 seconds]
WhoTookMyName has joined #lisp
<LdBeth>
Weird, seems there are at least three different versions of Flavors
_whitelogger has joined #lisp
fikka has quit [Ping timeout: 244 seconds]
angavrilov has joined #lisp
<holycow>
l
<holycow>
sorry, typo
xkapastel has quit [Quit: Connection closed for inactivity]
fikka has joined #lisp
rippa has joined #lisp
fikka has quit [Ping timeout: 246 seconds]
rumbler31 has quit [Remote host closed the connection]
<LdBeth>
Does anyone know what does defobfun in MCL do?
<makomo>
morning
<LdBeth>
Ah, seems it's a legacy form of defmethod
<LdBeth>
makomo: morning
<beach>
Hello makomo.
sigjuice has quit [Ping timeout: 240 seconds]
sigjuice has joined #lisp
joast has quit [Ping timeout: 240 seconds]
razzy has joined #lisp
orivej has joined #lisp
shka_ has joined #lisp
fikka has joined #lisp
fikka has quit [Ping timeout: 272 seconds]
another-user has joined #lisp
<another-user>
hi
nirved has joined #lisp
<beach>
Hello another-user.
<another-user>
is there some kind of "rule of thumb" for when to use defstruct vs defclass?
<beach>
Yes.
<beach>
Always use DEFCLASS.
<another-user>
beach: got it, thank you!
<beach>
I should moderate that a bit...
<beach>
IF you know what you are doing, IF you have extreme performance requirements, IF you know that your implementation generates faster code for structs, IF your application is know to spend a significant amount of time accessing object slots, and IF you are willing to live with the semantics of structs, then you should use them.
<Inline>
with which implementation is that the case ?
<beach>
Is what the case?
<beach>
That struct access is faster?
<Inline>
yes
<beach>
Most existing implementations.
<beach>
The struct semantics were specified so that no indirection is needed.
<beach>
Not so for standard objects.
<another-user>
beach: i see, this is great explanation
<beach>
Also, slot accessors for structs are ordinary functions, and if your implementation is slower on calling a generic function, that will make structs faster as well.
fikka has joined #lisp
<Inline>
that all sounds like inviting into structs first, try out a few oop with structs and then later on try to switch onto clos....
<beach>
Now, like I said yesterday in #clschool, I often see people using structs for better performance, but then they are totally incompetent when it comes to designing efficient data structures and algorithms. It would be much better to do it the other way around.
<Inline>
hmmmm
<beach>
Inline: Why do you say that? I would think the other way around. Premature optimization and all.
<Inline>
no idea, to get a feel for oop or so
<beach>
Structs really mess up the development process, so you would want them in the end, if at all.
<beach>
Er, what?
<Inline>
oop design i mean
<beach>
Using standard classes is much more OOP than using structs.
<Inline>
that's not what i meant
<another-user>
beach: i have also implemented example you gave me(optimization without breaking interface) and i was really impressed!
<no-defun-allowed>
structs are basically the C structs, they're a bunch of values stuck together
<beach>
another-user: Great.
<beach>
Inline: What did you mean then?
<no-defun-allowed>
a standard-instance has superclasses, subclasses, and all the OOP stuff going for it
graftin` has joined #lisp
<beach>
Inline: By the way, you can't "switch into CLOS" because CLOS is already present. STRUCTURE-OBJECT and STRUCTURE-CLASS are perfectly good classes.
<beach>
Every Common Lisp datum is the instance of some class.
<jcowan>
Henry Baker very much preferred structures to classes (maybe still does, I don't know)
<jackdaniel>
structures conceptually are much simplier, I can imagine why he preferred them in his theoretical works
<beach>
jcowan: Structs are classes too.
fikka has joined #lisp
<jackdaniel>
I'm certain that everyone talking about classes in Common Lisp means standard-class (and not i.e builtin-class or a metaclass of some kind)
<beach>
Yes, and that's a bad idea, because it is not the correct terminology.
<jackdaniel>
s/everyone/everyone in above discussion/ I can imagine someone talking about clases in general of course
<beach>
So I am trying to fix it.
<shka_>
good morning
<no-defun-allowed>
morning shka_
<makomo>
shka_: morning
pjb has joined #lisp
<beach>
Inline: So when you say "that all sounds like inviting into structs first", either you don't buy my advice, or else it means that you initially assume that you know what you are doing, that you have extreme performance requirements, that you know that your implementation generates faster code for structs, that your application will spend a significant amount of time accessing object slots, and that you are willing to live with the
<beach>
semantics of structs.
<beach>
If that's not a very good example of "premature optimization" I don't know what is.
<pjb>
well, one advantage of defstruct is that it's more concise than defclass. (defstruct pt x y) and you're set.
<beach>
Good, let's all convert to DEFSTRUCT. I should go rewrite Cleavir right away.
<jackdaniel>
nb: define-class in ergolib gives you similar concise syntax for standard classes
<pjb>
Nope.
fikka has quit [Ping timeout: 246 seconds]
<pjb>
Use a macro with the simple syntax that expand to defclass etc.
<pjb>
like define-class.
iAmDecim has joined #lisp
<pjb>
The only serious problem you may have with defstruct is that the readers and writers it generates are not (necessarily) generic functions.
<no-defun-allowed>
the #1 draw for defstruct for me is that it's less typing cause of the implicit accessors, which is really stupid come to think of it
<pjb>
But classes have so many advantages. You can use change-class, you can have multiple-inheritance, you can introspect the slots with the MOP, you can add slots at run-time…
<pjb>
But structs can use vector or lists are storage, and you still have inheriting with :include >:-}
<jackdaniel>
no-defun-allowed: while it is OK to be suspicious about macros which define functions on your behalf I don't know how this is stupid - could you elaborate?
<no-defun-allowed>
that the only reason to use defstruct early in development is that it's less typing
<jackdaniel>
less typing also means less reading
<jackdaniel>
more concise syntax carries more information per line for the code reader
<jackdaniel>
that is a desireable quality (and if you ask me - far from stupid)
<jackdaniel>
that's why we abstract many things with new words: you say "computer", not "an electronical circuit with a program which …"
<pjb>
Anyways, in an application, you often will write special macros to define entities of your application, that expand into a defclass and more, so you won't have to write all the verbosity of defclass yourself anyways.
<no-defun-allowed>
yes, maybe a simpler macro that expanded to defclass would be more reasonably
<jackdaniel>
that said I don't think defclass is too verbose
<no-defun-allowed>
it's not awful but it's not short enough for lazy people
<beach>
I submitted this idea in #sicl, but there was no reaction: What if the :TYPE option of a slot that mentions a class could result in a slot writer method that specialized on both its parameters?
<pjb>
beach: :type, not :class.
<beach>
I did write :TYPE.
<pjb>
Furthermoree, that doesn't prevent the existance of other writers with other classes for the value, so you won't get an error. Also you'd get a missing method error, instead of a type error.
<pjb>
Yes, :type let you specify a type, but methods disptch on classes.
<no-defun-allowed>
so if you had a :type of FOO in BAR for the slot BAZ it'd generate the equivalent of (defmethod bar-baz ((bar bar) (baz foo)))?
<beach>
I did write ":TYPE that mentions a class"
<pjb>
Oh, right.
<pjb>
In that case, remains the error you'd get. NO-APPLICABLE-METHOD vs. TYPE-ERROR.
<beach>
no-defun-allowed: That's the idea, yes, except it would be (defmethod (setf BAZ) ((new-value FOO) (object BAR)) ...)
<no-defun-allowed>
oh, of course.
<beach>
pjb: Indeed.
<pjb>
beach: actually, the point is that I feel uneasy with it, because I'm not sure there wouldn't be case where the semantics would change. We could know if we had a formal semantic definition of the language, and check the equations…
<beach>
Would this behavior be conforming?
<no-defun-allowed>
i like it, sounds good, but i think a second one would also be needed to handle type-errors presumably
<beach>
pjb: That's why I am asking, yes.
<no-defun-allowed>
strangely enough, both SBCL and CLISP allow me to create an instance of a class where the slot type requirement is violated
<pjb>
I may have written such setter method by hand, so I'm not entire against the idea. Perhaps it would enter into the generalization category, so it'd be acceptable. It would allow us to write additionnal methods for other classes of value.
<no-defun-allowed>
i did (defclass a () ((b :initarg :value :type integer))) and (make-instance 'a :value :foo) and it still made the instance
<jackdaniel>
no-defun-allowed: standard doesn't say, that implementation has to enforce such type, it is just an annotation
<jackdaniel>
that said, sbcl and ccl check the type on high safety settings
<beach>
no-defun-allowed: If you put high values of DEBUG etc, it will check.
<no-defun-allowed>
i see then
<pjb>
clhs defclass doesn't say anything about the specialization of the method.
<beach>
Interesting.
<no-defun-allowed>
well, go for it beach, i don't see why it wouldn't be a good idea then
<pjb>
Only that it should be unqualified, so no :before :around :after <--.
<beach>
Right.
<jackdaniel>
so in that case bahavior will be different if you supply class name as a type and if you supply another type. I wonder how much it could bite a programmer
<beach>
Good question. That's why I submitted the idea here, so that people could help me think about it.
<jackdaniel>
I don't know how much code out there depends on type-error being signalled on such setf (given standard does not mandate such error)
<jackdaniel>
but if there is such code, then handling of such conditions will break inconsistently
<pjb>
Well, the first difference would be that you'd have a method more specialized than expected. So some program could have other methods, with a more general class, a more specific class or with the same class, that would override the defclass provided method.
<pjb>
You would need to still provide the method on T, so that user supplied method with a more general class could still call-next-method. They'd be shadowed by your method for values of the correct class, but not for values of superclasses.
<pjb>
or different classes.
<beach>
pjb: Very good point.
<pjb>
So the question is how many program include such additionnal methods on writers, and whether we accept to break them, or whether we want to continue support the possibility even if it's (almost) never used.
<beach>
jackdaniel: Also a good point.
<jackdaniel>
pjb: I think that it is a non-brainer here: if you break conforming programs by some change it shouldn't be included. your example is a conforming use of the mechanism.
<pjb>
beach: you may try: grep -RnHi -e 'defmethod.*(setf' ~/quicklisp
<jackdaniel>
so even if no such code exists yet, such change would render sicl being si-not-quite-cl
<beach>
Well, I won't do it. At least not initially. I need more thoughts and more time to think about the consequences.
<pjb>
It's about the only case, from a quick overview.
<beach>
Good to know.
<pjb>
In that case, the slot has only a reader. The writer calls a function that sends message to the remote window managing process.
<beach>
Anyway, I should supply the :TYPE anyway. The purpose of my suggestion was to make satiation more reasonable. If I have an unspecialized parameter, satiation will fill the call history will all classes in the system. I wanted to avoid that. But I can use the :TYPE information just for satiation instead.
<pjb>
(I've not done a (quick-install-all) on this system, so it's only a partial sondage).
<beach>
That should be fun, i.e. rewrite satiation to take into account the :TYPE option of the slots.
<beach>
Satiation is free to do what it wants as long as the semantics are preserved. If it misses something, the only thing that happens is that the generic function will be updated when it is called with a type that satiation missed.
<beach>
The purpose is to avoid that (say) COMPUTE-DISCRIMINATING-FUNCTION is called with itself as an argument. So the call history of that function needs to include an entry for standard generic functions.
<elderK>
Hey all.
<beach>
Hello elderK.
<elderK>
Man, I'm not having much luck figuring out nested-backquoting and stuff :(
<elderK>
I thought I was but noooope.
<beach>
But during bootstrapping, I need to make sure that all the accessors are satiated before I can "tie the knot".
<elderK>
Innermost BQ expanded first, leftmost comma belongs to innermost...
* beach
is suddenly not sure that his last statement is true. Goes to think...
<jackdaniel>
elderK: three steps of enlightnment: novice uses only single backquote, student uses nested backquotes, master uses only single backquote
<jackdaniel>
skip the middle and jump to mastery=
<jackdaniel>
=)
<elderK>
:) Aye. Still, I want to understand :)
<elderK>
I tried to write my own once-only. I failed. I know what I want to do, and what has to be done. Just not how to actually code it.
<elderK>
So, I looked at PCL - but it wasn't very forthcoming with nested stuff.
<elderK>
Have been bouncing between CLHS and CLtL2 now
<makomo>
elderK: yeah, the definition in PCL is really horrible :-)
<makomo>
the one i linked (from Alexandria) is much nicer
cage_ has joined #lisp
<elderK>
makomo: I mean, PCL doesn't even touch on nesting, not realy.
<makomo>
yeah, it doesn't
<jackdaniel>
"On Lisp" by Paul Graham has an insightful description of once-only
<jackdaniel>
(afair)
<makomo>
elderK: one thing -- there's a difference between "expanded" and "evaluated"
<makomo>
when the CLHS says "expanded", it's referring to the process of reading in the backquote and processing it as a reader macro, i.e. "expanding it into some implementation-defined form"
<makomo>
once you read in the nested backquote template, *then* it's time to (iteratively) evaluate it
<makomo>
so when the CLHS says "the innermost backquote should be expanded first", it's referring to the process of converting the reader macro into an implementation-defined form
<makomo>
it's not saying "innermost backquotes are evaluated first"
<makomo>
evaluating proceeds in a top-bottom fashion
<makomo>
evaluation*
<jackdaniel>
I don't understand this description :(
<elderK>
Ah, thank you
<makomo>
(that particular usage of "expand" was the most troublesome thing regarding the CLHS specification of backquote (for me at least), as it's not explained explictily anywhere)
<elderK>
Yeah, that confused the shit out of me.
<makomo>
yup, that one sentence is really horrible :-)
<elderK>
I was thinking like, `(stuff `(more stuff)) that it meant it would go through `(stuff EXPANDED) then FULL_EXPANSION
d4ryus has joined #lisp
<makomo>
jackdaniel: which one?
<elderK>
Also, irccloud seems to treat ` specially.
<makomo>
elderK: another note -- if you ever decide to do the expansion yourself (i.e. follow the formal rules in CLHS by hand), i would suggest you do the expansion "iteratively" (in multiple passes)
<jackdaniel>
makomo: yours, about expanding and evaluating
<makomo>
elderK: the algorithm of course works recursively, but it's really impossible for a human to keep track of the various "stack frames"
<makomo>
so you process the expansion in passes (steps), applying the rules until you get rid of the innermost backquote template
<makomo>
then you start applying them to get rid of the innermost-1 backquote, etc.
<elderK>
Does it expand kind of like... peeling an onion?
<makomo>
jackdaniel: hmm, what's confusing?
<pjb>
Well, or not. You don't need to resolve all the backquotes. Only the one you're currently evaluating.
<jackdaniel>
makomo: erm, description
<makomo>
jackdaniel: i mean, any particular part or? :-)
<jackdaniel>
... so .. then .. but .. so ..
<makomo>
elderK: well kinda, except that the inner layers are peeled before the outer ones :D
<jackdaniel>
whole construction, but nvm, since elderK understood it's fine, I was not an audience anyway
<jackdaniel>
s/it's/it it's/
<makomo>
jackdaniel: i don't mind clarifying. we were referring to this line in CLHS 2.4.6 " If the backquote syntax is nested, the innermost backquoted form should be expanded first. This means that if several commas occur in a row, the leftmost one belongs to the innermost backquote. "
<makomo>
"expanded" here means "processed at read-time". it's not referring to the evaluation of the form
<elderK>
:( Still confused.
<jackdaniel>
I'm aware how backquote works, I've just pointed out that your explanation was confusing to me
<elderK>
You guys are helping but still kind of confused.
<makomo>
jackdaniel: ah, ok
<elderK>
Like, I get that `(...... `(....)) is expanded into some form by CL, maybe it says (quasiquote ..... `(...)) then (quasiquote .... (quasiquote ...))
<elderK>
And then I guess it gets to actually filling the "templates" as it were.
<elderK>
Which, goes from inside-out, right?
<elderK>
So the "nested quasiquote" is... uh, evaluated? (expanded?) first.
<jackdaniel>
backqoute isn't an operator (or at least doesn't have to be)
<makomo>
elderK: the expansion proceeds bottom-top (innermost-to-outermost) which is important because that defines the association between a comma and a backquote -- the rightmost comma corresponds to the outermost backquote
<makomo>
elderK: the filling of the template happens at evaluation. evaluation proceeds top-bottom (outermost-to-innermost)
<makomo>
to evaluate a backquote template means to interpolate/splice in all the results of forms that have been marked with , or ,@ that *correspond to the outermost backquote*
<jackdaniel>
elderK: it goes from the outside so to speak
<elderK>
I guess I'm confused with expansion vs evaluation then
<pjb>
So, the problem is that it's difficult to see it step by step, because since backquote is a reader macro, all the levels of backquoting are resolved and transformed in to list expressions when read.
<pjb>
makomo: honestly, it'd be easier if it was on a single line!
<pjb>
How do you expect us to copy and paste that?
<elderK>
No, it's better on multiple lines.
<makomo>
pjb: eh, yeah :-)
<elderK>
At least for /reading/
<elderK>
Would it return c2?
<pjb>
But the point is not to read, it's to try it out in the repl!
<makomo>
elderK: it would return ```,,,c2
<makomo>
you eval that again!
<makomo>
(but you'll have to manually paste the result into that let and evaluate it again)
<pjb>
Here it returns c2.
<pjb>
and says the other variables are unused.
<elderK>
I get ```,,,c2
<makomo>
i couldn't use (eval (eval (eval (eval '````,,,,c4)))) as i would lose the lexical environment (that's the behavior of EVAL) (i.e. EVAL wouldn't see the lexical bindings of the LET)
<elderK>
So, the "innermost" `, is stripped?
<elderK>
Or rather, `,,,,c1 expands to ,,,c1
<makomo>
the outermost ` and the innermost ,!
<elderK>
Outermost meaning leftmost or rightmost?
<makomo>
outermost ` meaning the leftmost `, and the innermost , meaning the rightmost ,
<elderK>
Okay, so if I want to write it differently, XYZWwzyxc1
<pjb>
all implementations return c2, only sbcl return ```,,,c2
<makomo>
errr, that's a bit confusing, i should keep the two in sync
<makomo>
the outermost backquote/comma pair is stripped!*
<makomo>
which means: the leftmost backquote, the rightmost comma
puchacz has joined #lisp
<puchacz>
hi, for "flattening" list of lists, is this O(n) ?
<puchacz>
(apply #'append '((12 3) (8 17) (3)))
<puchacz>
I know (reduce #'append '((12 3) (8 17) (3))) is not O(n)
<makomo>
elderK: this version will allow you to iteratively do (eval *) at the REPL
<makomo>
(let ((c1 'c2))
<makomo>
`(let ((c2 'c3))
<makomo>
`(let ((c3 'c4))
<makomo>
`(let ((c4 '1))
<makomo>
`,,,,c1))))
<makomo>
which might be a bit more convenient
<no-defun-allowed>
Well, I'd presume O(n^2) cause you have one loop over append which loops.
<puchacz>
no-defun-allowed: so to have O(n) flatten, I guess I need to write it myself, do I?
<no-defun-allowed>
You could condense it onto one like, I don't think the repl will mind.
<no-defun-allowed>
If you can make that O(n) without changing data structures, you're a god amongst programmers.
<makomo>
no-defun-allowed: yeah of course, but it's easier to read (not to copy paste though) :-)
<no-defun-allowed>
If you can get the last cons in O(1) and don't mind destructively modifying the inputs, you can make it O(n).
<makomo>
no-defun-allowed: but it makes it clearer to see what i was trying to say (rather than the person on the other side having to untangle the one liner)
<no-defun-allowed>
makomo: fair enough.
<elderK>
Thank you makomo. I /think/ I'm starting to understand a little. *I think*
<elderK>
no-defun-allowed: The many-lines-of-code thing is for me, because I don't run IRC in Emacs.
<elderK>
Or Emacs at all.
<elderK>
:( I tried to set up Spacemacs but had issues. Not with Spacemacs itself, mind you.
<elderK>
Because I had to make an Emacs port, which requires libraries that refuse to cooperate.
<makomo>
i don't run IRC in Emacs either
<elderK>
But that's an entirely different rant.
<elderK>
What IRC client do you use, makomo?
<makomo>
elderK: are you on BSD or something?
<makomo>
elderK: Weechat
<elderK>
Crux
<elderK>
One problem is that libjpeg-turbo is built using CMake, which of course, doesn't install .la files. Where as libgd is built with autotools, and expects .la for llibjpeg. Which doesn't exist. So it dies.
<makomo>
first time i hear of that distro
<elderK>
Emacs requires m17n-lib, which requires gd. ETc, etc.
<elderK>
Another alternative is to replace the distribution's libgd with my own version, that uses cmake instead of autotools. But then I'm concerned what other packages it will break.
<elderK>
What other things expect say, libgd.la or whatever.
<elderK>
It's a real cluster@!#$. Especially since some projects have /two/ build systems. And they don't install the same stuff.
<elderK>
SDL has this issue, too.
<makomo>
good old software packaging/distribution issues, never to be resolved :-)
<elderK>
I really could rant about this for awhile.
<elderK>
:P
<elderK>
It's like, why not standardize completely around pkg-config? That could help but CMake doesn't want to. And pkg-config is useless on Windows, for the most part.
<elderK>
And yeah, never to be resolved is right :P
<elderK>
makomo: Also, how do you copy individual lines out of Weechat, to your REPL?
<elderK>
My urxvt setup is pretty stock - that may be why things like URIs and stuff aren't properly highlighted. At least, not across multiple terminal lines.
<makomo>
elderK: that's one of the backquote-related SO Q&As i have bookmarked :-), but only for "archiving" purposes (i.e. i didn't want to link it because i forgot what explanation was offered there)
random-nick has joined #lisp
<makomo>
elderK: i use the mouse to select the lines, copy and paste them into emacs and then trim the username/timestamp prefixes
<makomo>
not very efficient, but i'm too lazy to automate it somehow
<elderK>
Paste with middle-mouse?
<makomo>
i use p or ctrl+r
cpt_nemo has quit [Read error: Connection reset by peer]
<makomo>
elderK: that answer is okay i think, but you have to follow the poster's terminology
<makomo>
"... and that for a doubly nested backquote form, I should reinterpret the innermost backquote forms before reinterpreting the outermost backquote form."
<makomo>
"reinterpret" here is our "expand" from before (the "expand" that appears in CLHS)
<makomo>
hm, this is actually a very nice answer i think, i like it.
robdog_ has joined #lisp
<makomo>
(it's only now that i've read it fully)
<elderK>
I'm just trying to "expand" ````,,,,c1
Zaab1t has joined #lisp
<elderK>
`,form is the same as form
<elderK>
`basic == 'basic
<elderK>
hmmm
<elderK>
"The innermost is expanded first", so `,,,,c1 is "expanded"
<elderK>
Which I'm not sure how to do :D
<elderK>
`,,,,c1 is the same as ,,,c1
<elderK>
?
<makomo>
`,,,,c1 is invalid, as you have more commas than there are backquotes
<makomo>
to understand what "to expand" means, try this
<makomo>
(setf *print-pretty* nil)
<makomo>
and type this at the repl '````,,,,c4
<makomo>
you could also use (read-from-string "````,,,,c4")
<makomo>
see how the backquote syntax is expanded into some implementation-defined form? that's what "expansion" is referring to
<makomo>
it's a read-time thing
<elderK>
No effect.
iAmDecim has quit [Quit: WeeChat 1.9]
<elderK>
NM. I thought *print-pretty* was special
<elderK>
Right, so thinking the Schemey way: ````,,,,c1 == (quasiquote (quasiquote (quasiquote (quasiquote (unquote (unquote (unquote (unquote c1)))))))) no?
<makomo>
(let ((*print-pretty nil)) <form>) won't work at the REPL as the printing of the result happens *after* <form> is evaluated (i.e. outside the LET block, somewhere within SLIME/SWANK)
<makomo>
elderK: right
<elderK>
So, then the (unquote c1) is "evaluated?" Which will give us whatever c1 is, right?
<elderK>
In your example, c2
<makomo>
yup
<elderK>
I find the ordering so strange.
<elderK>
Like, you'd think the innermost quasiquote would cancel the outmost unquote.
<elderK>
Rather than c1 being unquoted first
<makomo>
it might seem strange, but it makes sense when you think of it as "ladders" (i've heard the term "ladder algorithm" used somewhere)
<makomo>
every backquote is a level up, every comma is a level down, so to speak
<makomo>
you start at level 0 and only stuff at level 0 gets evaluated
<makomo>
or we could use 1-based indices and s/level 0/level 1/
<pjb>
elderK: why don't you just read the rules in clhs? They're very clear on how to interpret backquote…
<makomo>
elderK: using the SO terminology from that answers, CLHS uses an "equivalency description" -- it describes a possible set of forms that backquote might expand into and derives the evaluation semantics from that
<makomo>
that's all fine, but it's useful to know the "replacement description" as well -- an intuitive way to think about "canceling" the various backquote/comma pairs
<beach>
Do we agree that the :TYPE slot option is not evaluated?
<makomo>
the "replacement description" is simple for simple cases, but needs to be made more complicated (or special cased somewhere) for cases like ,@,@ or ,,@, etc.
<makomo>
the "equivalency description" of course has no problem with those
<pjb>
beach: indeed, you don't quote the type specifier.
<makomo>
pjb: was meant for you ^, not elderK (sorry)
sonologico has joined #lisp
<makomo>
using the terminology from that SO answer*
<pjb>
No way to write (defparameter *my-type* 'integer) (defclass foo ((x :type *my-type*)))
<Bike>
beach: like in defstruct and defclass? it's not evalauted
<elderK>
pjb: I have been. They are not super clear to me yet.
<beach>
Thanks!
<jackdaniel>
elderK: I think that this topic requires silent contemplation with a single source of information (in this case clhs) instead of multiple ones
<jackdaniel>
it is easy to get confused, ie some people put their "intuitive" interpretation into play which may be incorrect (or may not match your mental model)
<elderK>
jackdaniel: I would ordinarily agree. But there were parts in the CLHS spec I was not sure how to... apply. Seeing that post on SO, clarifies that.
<elderK>
My goal now is to get a few nested macros, and expand them, according to CLHs rules.
<elderK>
Perhaps once-only from PCL
<elderK>
Then I guess I'll try and get Emacs running again :)
lavaflow has quit [Read error: No route to host]
<makomo>
jackdaniel: "silent contemplation" is the part i agree with, but i think you really do need multiple source of information (either to see where they went wrong, or to clarify some points)
<makomo>
sources*
lavaflow has joined #lisp
<makomo>
elderK: i have a few expansions i did by hand if you'd like to take a look
<elderK>
I'd definitely appreciate that.
<jackdaniel>
I think that you confuse him instead of helping (and I judge it by the fact, that I was away for more than an hour and you still talk about the same thing)
<elderK>
jackdaniel: That's not fair. makomo is actually helping.
<makomo>
jackdaniel: confusion is a necessary evil :-)
<elderK>
At least, I've found him to be helpful.
<makomo>
:-)
<jackdaniel>
I'm known for being unfair, sometimes it happens though that being unfair doesn't mean "wrong"
<elderK>
:P Also, don't discount the fact that I may be dense.
<elderK>
:P
<elderK>
Maybe this really is something that's simple. Just, it's not clicking for me atm. But, I am definitely closer now.
<jackdaniel>
also being satisfied with help and getting grasp of something are two different things as well
<jackdaniel>
so called ,@,@ "idiom" is incorrect in light of clhs (it relies on some intuition shared by some)
<makomo>
jackdaniel: i proved that incorrect last time we talked about that
<jackdaniel>
no you didn't, one of key arguments is that it is "natural extrapolation" from the spec
<jackdaniel>
and I was not interested in discussing it, just given you resources you may follow
Guest24308 has quit [Ping timeout: 252 seconds]
<makomo>
jackdaniel: it's not an extrapolation, it's ridigly and mechanicaly following the rules
<makomo>
which is why i suggested that elderK read and try to follow the rules by hand
<jackdaniel>
and again, I'm not interested in discussing it. still, it is incorrect "idiom".
<makomo>
ah well...
<makomo>
why even mention it if you're not willing to discuss it fully :/
<pjb>
it's a reference, check the logs.
<jackdaniel>
I'm just trying to prevent you from teaching elderK something incorrect
<makomo>
jackdaniel: when you get the time, take a look at the expansion i did by hand and tell me what step is wrong
<makomo>
right, but you're not providing any proof that it is undefined/incorrect as per the CLHS rules
<jackdaniel>
I have more interesting thigns to do than proving you wrong. I did point you to the references which discuss it
<makomo>
yeah, and i've read that reference, which is actually a bug report
<makomo>
but none of the commenters there use the formal rules to prove that ,@,@ is undefined, which is why i did it by myself
<elderK>
Thank you, makomo.
<jackdaniel>
if this is not enough for you, then please consider practical argument for not spreading this incorrect information: it doesn't work on all CL implementations
<elderK>
This is /super/ helpful.
<elderK>
Thank you for showing the explicit steps.
<makomo>
jackdaniel: that's an implementation's problem, is it not? pjb actually reported to CCL that ,@,@ doesn't work
heisig has joined #lisp
<jackdaniel>
no, this is a community problem that you spread a dubious syntax and you label it "idiomatic"
<jackdaniel>
which results in code which is incorrect/doesn't work
<jackdaniel>
that's all I have to say on this topic
<makomo>
jackdaniel: how is it dubious when it is fully and formally defined by the CLHS?
<jackdaniel>
makomo: let's make a wager: I prove you wrong, you solve one ECL issue I point you to, I'm not able to, I'll solve another CL foss issue you point me to
<jackdaniel>
hm?
<makomo>
jackdaniel: just saying that it's incorrect and leaving isn't helpful... we should sit down and discuss it once and for all some time :-)
<makomo>
jackdaniel: haha, let me think about it
rumbler31 has joined #lisp
<pjb>
Yes, it's a good idea to wage issues to solve…
<makomo>
jackdaniel: hell, why the heck not! (i'd be interested in McCLIM as well)
<makomo>
but a necessary condition for the proof is that it has to be done using the formal rules provided by the CLHS, ok?
<pjb>
Yes.
<makomo>
no bug reports or external discussions are allowed
<pjb>
You can have clhs arguments in but reports or external discussions.
<pjb>
But indeed, it's the clhs that should be the origin of the reasoning.
<makomo>
right, that's what i meant
nicball has joined #lisp
rumbler31 has quit [Ping timeout: 252 seconds]
void_pointer has joined #lisp
<makomo>
jackdaniel: so is it a deal then? :-)
varjag has joined #lisp
nicball has quit [Ping timeout: 252 seconds]
nicball has joined #lisp
crsc has quit [Quit: leaving]
nicball has quit [Remote host closed the connection]
lavaflow has quit [Read error: No route to host]
lavaflow has joined #lisp
<elderK>
makomo: You treat `'something like ''something. I.e The 'something as a "basic object." Would I be incorrect to expand that further into, `(quote something) ?
<elderK>
Wow, irccloud really mutilated that message.
<makomo>
elderK: that would be correct and was something i tried once, but found it too verbose
<makomo>
but yes, that would be the 100% right way to do it
<elderK>
Sweet.
frgo has quit []
<elderK>
So, I take it reader macros are expanded first always, right?
<elderK>
So if I ahve `(..... 'a)
<elderK>
the ` is expanded first.
<elderK>
Then all the othe rthings, eventually, I'll have the usual forms, with '
<elderK>
Then I expand them to (quote ...)
<pjb>
elderK: reader macro read the form!
<void_pointer>
elderK: reader macros are expanded when the file is read into lisp, before being evaluated, compiled, or really anything else for that matter
<pjb>
` is read.
<void_pointer>
elderK: expanded is not really the right term though, so sorry.
<pjb>
elderK: cf chapter 2. The lisp reader reads the character #\` then it looks it up in the *readtable* and find a reader macro for it. It calls the reader macro.
<void_pointer>
elderK: what pjb said, they are used to do the actual reading
<elderK>
Yes, I know.
<makomo>
elderK: the reader would expand 'a somewhere within the algorithm to expand `
scymtym has quit [Ping timeout: 245 seconds]
<makomo>
"expand" meaning "read" really
<pjb>
elderK: the reader-macro for ` will read the following expressions, parsing the , and ,@ and substiting the whole by a lisp form to build the equivalent list.
<pjb>
(let ((bar 42)) '`(foo ,bar)) #| --> (list* 'foo (list bar)) |# <-- This is what is read.
<jackdaniel>
makomo: it mostly is, first we have to point out issues (to avoid situation, where the winner side picks an unreasonable issue)
<pjb>
Notice bar is not evaluated into the read form.
<pjb>
it's evaluated when the form that has been read is evaluated.
<jackdaniel>
I think that fixing it should fit in 20h tops
<makomo>
jackdaniel: well, it's not like either of us is *required* to do what the other says, so it's mostly a matter of pride/honor
<jackdaniel>
I insist that we first agree to designated issues
<makomo>
i was going to trust you to pick out something normal (it's not like i ever worked on either ECL or McCLIM, so it would be a wild ride anyway)
<makomo>
sure, but i'm not sure what i could give you
<jackdaniel>
so please send me your proof that ,@,@ is correct (expansion you have mentioned which follows rules) and the issue you have picked when you have it
<pjb>
That's easy :-)
<makomo>
jackdaniel: i've posted it above on plaster, that's the expansion
<makomo>
since if it turns out to be correct, one would like to see it fixed
frgo has joined #lisp
<jackdaniel>
OK, but I don't promise that I'll solve it before next release, it will be pretty involving change of the reader which is written in most part in C
<makomo>
that's ok :-)
<jackdaniel>
I'll let you know when I get to the doulbe splice (I first need to finish current PR on McCLIM)
<makomo>
jackdaniel: deal! in the meantime i'll double check my expansion
<jackdaniel>
what are the numbers in comments? I gather they are not CLHS rules used?
<makomo>
just the individual steps, i haven't documented which particular rule was used, but the steps are small enough so it should be easy to see
razzy has quit [Ping timeout: 252 seconds]
crsc has joined #lisp
<makomo>
ah, seems like (4) and (5) are accidentally the same thing, c/p error probably
frgo has quit [Ping timeout: 268 seconds]
Inline has quit [Read error: Connection reset by peer]
Inline has joined #lisp
Inline has quit [Read error: Connection reset by peer]
frgo has joined #lisp
igemnace has quit [Quit: WeeChat 2.3]
<elderK>
makomo: How long did it take you before you could follow this process in your head at lightspeed?
<elderK>
Or, over time of expanding things this way, you just began to recognize patterns?
scymtym has joined #lisp
<elderK>
I've been doing the expansions by hand, on my own, then comparing against your notes.
<elderK>
:P I skip the nils a lot
d4ryus has quit [Ping timeout: 252 seconds]
d4ryus has joined #lisp
<makomo>
elderK: i'm not sure, but you *do* start to recognize the patterns, trust me
<makomo>
Steele mentions it in cltl2 as well (and he has a very nice discussion of backquote there -- that's another resource i would suggest)
<makomo>
the rules from the CLHS spec are the ones in cltl2 actually :-)
<makomo>
s/spec//
<makomo>
elderK:
<makomo>
woops
Essadon has joined #lisp
McParen has joined #lisp
dkmueller has joined #lisp
graftin` has quit [Ping timeout: 252 seconds]
Inline has joined #lisp
<makomo>
nevermind, steps (4) and (5) in the expansion of ,@,@ do differ, but the difference is a single backquote replaced with a quote
<makomo>
i just didn't see it the first time
varjag has quit [Ping timeout: 244 seconds]
varjag has joined #lisp
smokeink has quit [Remote host closed the connection]
<robdog_>
serialization question
<robdog_>
i know you can use (read on a filehandle/stream to read an sexp
<robdog_>
how do you write out the sexp on a variable? ie hash
<robdog_>
so i can read it back in with (read
<makomo>
PRINT?
Inline has quit [Read error: Connection reset by peer]
<cage_>
expecially if you want to de/serialize an instance of a class
shifty has quit [Ping timeout: 252 seconds]
<robdog_>
cool..thanks cage_
<cage_>
you're welcome! :)
Guest24308 has joined #lisp
varjag has quit [Ping timeout: 252 seconds]
robdog_ has quit [Remote host closed the connection]
esper0s has joined #lisp
beach has quit [Ping timeout: 252 seconds]
varjag has joined #lisp
beach has joined #lisp
varjag has quit [Remote host closed the connection]
varjagg has joined #lisp
warweasle has joined #lisp
maximjaffe has joined #lisp
_whitelogger has joined #lisp
joast has joined #lisp
rumbler31 has joined #lisp
puchacz has quit [Quit: Konversation terminated!]
rumbler31 has quit [Ping timeout: 272 seconds]
kuwze has joined #lisp
rumbler31 has joined #lisp
Mr-Potter has joined #lisp
[1]ringer1 has quit [Read error: Connection reset by peer]
igemnace has joined #lisp
movl has joined #lisp
varjagg is now known as varjag
dddddd has joined #lisp
rumbler31 has quit [Remote host closed the connection]
warweasle has quit [Quit: rcirc on GNU Emacs 24.4.1]
rumbler31 has joined #lisp
scymtym has quit [Remote host closed the connection]
astalla has quit [Ping timeout: 252 seconds]
scymtym has joined #lisp
msb has quit [Ping timeout: 252 seconds]
heisig has quit [Quit: Leaving]
rumbler31 has quit [Remote host closed the connection]
razzy has quit [Ping timeout: 268 seconds]
elderK has quit [Quit: Connection closed for inactivity]
puchacz has joined #lisp
ryan_vw has joined #lisp
razzy has joined #lisp
space_otter has joined #lisp
terpri has quit [Remote host closed the connection]
bendersteed has joined #lisp
terpri has joined #lisp
esper0s has quit [Read error: No route to host]
<another-user>
bb
<another-user>
thank you!
another-user has quit [Quit: ERC (IRC client for Emacs 26.1)]
<jcowan>
s there any trick to load a system such that the current package is changed after the system is loaded? This would be useful when implementing a different language in CL.
<jcowan>
For example, suppose I write an implementation of Elisp in CL. I define two packages, ELISP (which inherits from CL as usual) and ELISP-USER (which inherits only from ELISP). Then I want to load this and have the user wind up in ELISP-USER, but I don't see any way to do that.
<jcowan>
Well, if the user has to type that at the REPL, it's rather verbose. And if you put it in a file for convenience, it doesn't work. Indeed, at the REPL you might just as well write the two forms separately without progn.
<beach>
You didn't tell us what you expect the user to type.
<beach>
Create a macro for the user then: (elisp)
<beach>
That expands to the above.
<jcowan>
In what package does the elisp symbol live? Presumably CL-USER. Is that acceptable practice?
<jcowan>
So again the user has to type two forms: a load and (elisp). This is some improvement on find-package or in-package, but not optimal.
scymtym has quit [Ping timeout: 252 seconds]
<jcowan>
or if not put in CL-USER, the user must type (load ...) and (elisp:elisp). Uglier yet.
Inline has quit [Read error: Connection reset by peer]
Inline has joined #lisp
<WhoTookMyName>
I think you mean an init file.
WhoTookMyName has left #lisp ["ERC (IRC client for Emacs 25.3.1)"]
Inline has quit [Read error: Connection reset by peer]
equwal has joined #lisp
<equwal>
Like SBCL has the .sbclrc file
<equwal>
d
<jcowan>
I see, so you copy the macro into your Lisp's .rc file. Reasonable.
rozenglass has quit [Remote host closed the connection]
lemoinem has quit [Ping timeout: 272 seconds]
Inline has joined #lisp
anamorphic has joined #lisp
<pjb>
jcowan: note that even if you put elisp in cl-user, the user may change the current package before wanting to call elisp, so he cannot type (elisp) willy nilly.
<jcowan>
right
<pjb>
jcowan: some repl let you define commands that are accessible whatever the current package. You could define such repl command to start elisp.
* jcowan
nods
<pjb>
in the rc file of course, since it's 100% implementation dependent.
vlatkoB has quit [Remote host closed the connection]
<pjb>
jcowan: the point is that the owner of the package gets to decide on the used packages.
Guest24308 has quit [Ping timeout: 252 seconds]
oni-on-ion has joined #lisp
bitmapper has joined #lisp
scymtym has joined #lisp
xkapastel has quit [Quit: Connection closed for inactivity]
<jcowan>
Yes, however, you take the risk of breaking your code if the used package is updated.
<jcowan>
hence the term "pollution"
<jcowan>
If/when I implement ISLisp I am going to add defpackage, in-package, and single-colon qualified symbols to the language definition. The ISLisp notes say that there was an intent to add modularity, but they ran out of time.
random-nick has quit [Read error: Connection reset by peer]
random-nick has joined #lisp
<pjb>
jcowan: even if you don't use the package, if there's an update, there's potential bitrot.
<jcowan>
There is going to be a fair amount of shadowing of CL required because of slightly different semantics: e.g. internal-time-units-per-second is a function, and you can't define it as such without shadowing it
* jcowan
nods
<jcowan>
Semantically, sure.
<fiddlerwoaroof>
Yeah, I don't know that there's a consensus about avoiding :USE, but I generally prefer to qualify my symbols so I know where they come from
<fiddlerwoaroof>
This is a bit painful in CL because there's no standard way to locally rename a package.
<jcowan>
People make a big deal about distinguishing "bug fixes" from "breaking changes", but every bug fix *is* a breaking change if your users have already worked around your bugs.
<jcowan>
fiddlerwoaroof: Even local nicknames would be an improvement
<fiddlerwoaroof>
And then there are things that use ASDF to manipulate the environment a system's source files are loaded in: http://quickdocs.org/package-renaming/
rumbler31 has joined #lisp
rumbler31 has quit [Remote host closed the connection]
random-nick has joined #lisp
<void_pointer>
I have a commonqt/qtools question, if anybody around here uses it.
Roy_Fokker has joined #lisp
<void_pointer>
I am trying to make a window, do some stuff on the main thread, and then close it without user input (if anyone is curious, this program is querying the rendering capabilities and doing some tests before closing).
<void_pointer>
But I am not sure how to get something running on the main thread after I create it.
playful-owl has joined #lisp
<pjb>
void_pointer: you cannot do it with bordeaux-threads, but there are implementation specific ways to run stuff on the main thread.
<pjb>
void_pointer: you can also portably implement your own loop running on the main thread, waiting for messages from the other threads to be evaluated.
xkapastel has joined #lisp
<pjb>
in ccl you can use ccl::call-in-process
<pjb>
or rather ccl::call-in-initial-process for the main thread.
<void_pointer>
pjb: I would like to avoid implementation specific stuff if I can help it but if it is the only choice then that is the way it is
<pjb>
Then implement your own event loop and messaging.
<void_pointer>
pjb: wait, would it be possible to use a signal to trigger a slot?
<pjb>
what kind of signal? What kind of slot?
didi has left #lisp ["O bella ciao bella ciao bella ciao, ciao, ciao."]
<fiddlerwoaroof>
I assume "signal" here means Qt signals?
permagreen has quit [Remote host closed the connection]
robotoad has quit [Quit: robotoad]
zmt00 has joined #lisp
jmercouris has joined #lisp
<jmercouris>
this isn't exactly a Lisp question, but a question about how you would use a library
<jmercouris>
so let's say you are using drakma to get the body of a page, what process, would you use to strip any ads from the page?
anamorphic has quit [Read error: Connection reset by peer]
<jmercouris>
I guess it isn't as simple as just removing JS blocks on the page, as those can be dynamically inserted
<jmercouris>
I am thinking somehow you would need to be able to capture all network requests and determine if they are from a domain that serves Ads or not using a list, and then deny requests to load assets from domains on that lis
<jmercouris>
s/lis/list
<bitmapper>
oh
<bitmapper>
i found a full copy of genera 8.3
resttime has joined #lisp
permagreen has joined #lisp
rippa has quit [Quit: {#`%${%&`+'${`%&NO CARRIER]
<pjb>
jmercouris: depends on the format of the page data.
<pjb>
jmercouris: what Content-Type did drakma report?
<pjb>
(you could learn some HTTP, it would be useful).
robotoad has joined #lisp
pierpal has quit [Quit: Poof]
pierpal has joined #lisp
<jmercouris>
pjb: Well, it is a web-page so the content type would be something like text/html, right, but drakma will just load the body, you would need to traverse the resources to determine whether to load those
random-nick has quit [Ping timeout: 268 seconds]
<jmercouris>
I'm debating whether I want to do the adblocking on common lisp still, or just use the built in webkit content blocking API (which will probably be way way faster)
<pjb>
jmercouris: so once you know it's html, you can read the standard about the html format, and parse it and find the ads in there.
<pjb>
there are also html and xml parsers, but I'm not sure how complete and uptodate they are.
<jmercouris>
pjb: most ads these days are served via ajax queries, so it's not as simple as just removing the offending html
<jmercouris>
sometimes there are place holder divs or something, that get populated with ads, maybe if you remove the placeholder div, then the ad won't even load
<pjb>
Of course, it's "semantic". So the best would be to implement an AI…
<pjb>
You can also filter at the network level.
<jmercouris>
maybe it would be best to implement an AI, train a model and distribute that model
<jmercouris>
I actually have a lot of experience in that domain, I'll think about it
<jmercouris>
maybe for now, webkit native content blocking rules are enough
Guest24308 has joined #lisp
<pjb>
Well, ad-hoc rules are only temporarily effective.
<jmercouris>
I'm not interested in implementation that is future proof, one step at a time
<jmercouris>
the API is at least future proof, the implementation can change
anamorphic has joined #lisp
<LdBeth>
Good morning everyone
Guest24308 has quit [Ping timeout: 252 seconds]
<anamorphic>
Hi LdBeth
<pjb>
jmercouris: well, if you want future proof, shot all the guys on the w3c. They keep issuing new standards! You will have to catch up.
<pjb>
(not counting all the browser writers, and all the web site designers, etc).
<anamorphic>
Hi, I defined a define-setf-expander here https://paste.ofcode.org/ygctgJ6i8KCnDFHgJiuhvG Basically my first attempt at an exapander. Does it seem correct? Checked it for things like double evals. Not sure how else I could have messed up though...
bendersteed has quit [Remote host closed the connection]
<anamorphic>
Oh and the main thing was it uses (setf (canvas-origin ..) (values ..))
razzy has quit [Ping timeout: 240 seconds]
random-nick has joined #lisp
ryan_vw has quit [Ping timeout: 246 seconds]
<jmercouris>
so I can use something like (cl-string-match:match-re ".*a.*b" to do a fuzzy search for anything with a and b in a row, but how could I make that case insensitive?
<jmercouris>
I guess I could upcase or downcase all candidates
<jmercouris>
that would probably be the easiest
josemanuel has joined #lisp
<jmercouris>
is the only way to upcase a string through format?
<jmercouris>
that can't be
<jmercouris>
ah, string-upcase
<jmercouris>
I couldn't remember, I kept search for uppercase-string in clhs
<aeth>
jmercouris: you don't even need to do that
<aeth>
jmercouris: There are case-insensitive versions of the character/string predicates
<jmercouris>
aeth: I know, but I am using cl-string-match which use cl-ppcre I think
<jmercouris>
and I don't know if there is a cl-ppcre flag to match insensitively
<jmercouris>
ah, well, wouldnt' you know it, there is in fact such a flag
dmiles has quit [Ping timeout: 246 seconds]
<jmercouris>
:case-insensitive t!
<aeth>
in regex it's just (afaik) [Aa] or [Bb] anyway and is only hard when you want to extend it past that
<jmercouris>
aeth: yes, but would not be quicker to transform my strings to all lowercase instead off branching on every single check?
<nirved>
with cl-ppcre you could prepend "(?i)" for case insensitive
<jmercouris>
I guess I could time it and find out
<jmercouris>
maybe I should move to cl-ppcre, instead of cl-string match
<jmercouris>
as cl-string-match does not expose a way to set case insensitivity
igemnace has quit [Quit: WeeChat 2.3]
<jmercouris>
and cl-ppcre is way more popular as well
<jmercouris>
then again, using match-re is way more expressive than having a remove-if predicate that has a cl-ppcre regex wrapped within a lambda
yvy has joined #lisp
<jmercouris>
maybe the way to go is to just have both libraries!
<jmercouris>
or just lowercase things, decisions, decisions, decisions
<jmercouris>
you know, I'm not carving things into a stone tablet here, I think I will go with lowercasing for now
<jmercouris>
and if performance sucks, I can change it
<aeth>
Usually I just write my own state machines and either parse character-by-character or substrings in a line-as-string, using only things like string=, char=, etc.
<jmercouris>
aeth: so what, you generate automata for every type of match you wish to do and store these models?
<jmercouris>
seems a little bit excessive for a generic fuzzy list matcher to me :D
<aeth>
Well, no, I do it manually because I have to do it often enough to find the pattern for the DSL, and I haven't done it often enough. Just turns 1 line into 30, though.
<aeth>
It's not as bad as it seems, it's just a bunch of cases/conds
<jmercouris>
I see, so for performance critical applications
<aeth>
Well, no, I just can't not write performance critical anymore ;-p
<jmercouris>
interesting, I'm not doing the parsing for a DSL, just fuzzy matching user input against a list of candidate
dmiles has joined #lisp
<jmercouris>
so our use case are quite different
<jmercouris>
though I could do something like that, I think I'll stick with the single line for now :P
<aeth>
absolutely
<makomo>
aeth: what kind of DSL is it?
<aeth>
jmercouris: I think you could do this, though, assuming you split it into lines or have the :start and :end points and it's in a string (not a stream): (find-if (lambda (c) (or (char-equal #\a c) (char-equal #\b c))) "abc")
<aeth>
(position-if if you want to get the position and then look for whitespace separators to get the word that contains that character)
<aeth>
(if you want more than one match, that's where it gets tricky because you'd have to repeatedly run position-if with modified starting points)
razzy has joined #lisp
<aeth>
makomo: I've written a lot of different (partially complete) DSLs
kajo has quit [Ping timeout: 250 seconds]
<makomo>
aeth: were these emebedded DSLs (within CL)? what did you need string matching for in that case? looking for symbols with special patterns in their names or something?
<aeth>
now, if you want "a...b...c" it gets trickier
<makomo>
aeth: i didn't pay close attention to the page. now i see that it's a protocol. i guess that's a DSL, but i was thinking in the "source code sense" (the usual sense) of the word
<makomo>
(i thought it was a DSL to define chess boards or something)
<aeth>
jmercouris: For a...b...c... you'd have to write three position/position-if tests, with each one informing the :start of the next
josemanuel has quit [Quit: leaving]
<aeth>
jmercouris: which is where writing a DSL would come in handy
<aeth>
It's conceptually simple but too verbose to be good to write manually
ryan_vw has joined #lisp
shka_ has quit [Ping timeout: 240 seconds]
<jmercouris>
aeth: yes, now we are generating state machines :D
<jmercouris>
I'll stick with the single line solution, performance is not an issue, and people after me will also have to read the code, and I don't necessarly need them to be fluent in my automata design :D
<aeth>
Right which is where I got confused about DSL
<aeth>
Because there are two DSLs
<aeth>
Three even
<aeth>
The state machine DSL for writing the embedded DSL for handling someone else's external, string-based (and hopefully line-based) DSL
<jmercouris>
Yes, sorry about tha
<jmercouris>
s/tha/that
<jmercouris>
I wasn't being very specific, often times things are very clear in my head, its just that when the words come out, I forget that you aren't also in my head :D
<jmercouris>
so there are things I often think I've said or included, but on second reflection, I realize I omitted, it is on accident though
random-nick has quit [Read error: Connection reset by peer]
<didi>
=> (32 53 20 31 12 1899 6 NIL 2797/900)
<aeth>
It should basically just be a reversal of ISO-8601's format until the time zone/DST/etc. stuff at the end.
<no-defun-allowed>
exciting time zone
<jmercouris>
how can a form return multiple values?
nly has quit [Ping timeout: 246 seconds]
<aeth>
(values 'a 'b 'c)
<jmercouris>
I'm familiar with multiple-value-bind to extract multiple values returned by a form, but how can I write a defun that returns multiple values?
<jmercouris>
oh I see
<jmercouris>
simple as that!
<aeth>
Also (values-list (list 1 2 3))
<jmercouris>
and why might I do that instead of returning (list 'a 'b 'c)?
<didi>
So I've been neglecting using the time zone. I should reverse that.
<aeth>
In fact, values probably uses values-list and the compiler probably optimizes values-list to not cons because of that.
<aeth>
(Well, (values-list (list ...)))
<aeth>
jmercouris: No consing.
<jmercouris>
and? is this what? a huge performance penalty for a function call?
<aeth>
It's also useful when you want the first value to be more important.
<aeth>
e.g. floor
<aeth>
90% of the time you just want the first value there
<jmercouris>
so that the user doesn't have to do something like (first returned-val)?
<jmercouris>
that is a use case I can understand
<aeth>
jmercouris: If you're doing something in a loop, you have two options in CL: mutate an object or use multiple return values. There is no magic immutable list/tuple that will be optimized away.
astalla has joined #lisp
<aeth>
Depending on how frequent that loop is, you could easily kill performance.
<aeth>
I mean, multiple return values probably cons at some point, but almost certainly past 4 and possibly past 10-20
<makomo>
certainly after 4 but possibly after 10-20?
<aeth>
(values 'a 'b 'c 'd) will, in any reasonable implementation, not cons, so it is effectively free (this has come up before and technically every function call pays a slight price because of this, but... it's already paid whether you use it or not so that makes it "free")
<aeth>
makomo: The line where it becomes inefficient is certainly after 4 in a reasonable implementation
kuwze has quit [Ping timeout: 256 seconds]
<aeth>
jmercouris: There's also a really neat parallel between a defsetf that can take in multiple values and a function that returns multiple values. Composes very nicely imo.
<makomo>
hm, reading that sentence a couple more times made it have more sense. guess it's a tricky formulation (for me at least)
<makomo>
it's a convenience macro to define new setf expanders
<aeth>
jmercouris: It's the middle ground between define (setf foo) and define-setf-expander
<aeth>
Most useful for multiple-value SETFs
<makomo>
define-setf-expander is the real deal :D
<aeth>
If your getter returns multiple values, your setter should use DEFSETF. If you're not writing multiple return value functions it's not surprising that you haven't needed it.
<jmercouris>
aeth: very interesting, I see
<jmercouris>
I don't think I'll use this very often, but handy to know, thanks for sharing
<aeth>
s/define (setf foo)/defining (setf foo)/
<aeth>
jmercouris: So those are the three uses I know of. (1) when one value's more important than the others (e.g. FLOOR), (2) when you don't want to cons but want to return multiple things (imo only really return lists when there's a structure, like building syntax in a macro or returning a plist/alist), and (3) when you want to combine it with a DEFSETF
<jcowan>
Consider subtypep, which returns two values: what it believes and whether it is ignorant.
<aeth>
gethash is another good example, where the second return value is present-p so you can tell if it's a NIL that was stored in the table or a NIL as the default default value (which you can override, btw)
kajo has joined #lisp
* jcowan
nods
<jcowan>
Scheme uses explicit continuations in that case, either just for failure or for failure and success, depending on the library.
<jcowan>
Lua just says "No nil as a key or value", though nil is not identified with any sort of empty container.
<jcowan>
Python raises an exception.
<aeth>
The thing about not using exceptions is that it's presumably cheaper to use hash-table as a duplicate-spotter.
<aeth>
Then you can add something unless (nth-value 1 (gethash something duplicates))
anamorphic has quit [Ping timeout: 240 seconds]
<aeth>
(and that's not much different from the code itself)
<jcowan>
Python exceptions are cheap by design, so they are extensively used.
<aeth>
cheap except syntactically
<aeth>
easily one of the worst parts of the language's syntax, up there with trying to use lambda/FP
<jmercouris>
python's exceptions are terrible
<aeth>
And this is a language trying to sell itself as being executable pseudocode
<jmercouris>
however, their syntax is fantastic
<jmercouris>
and easy to understand
<LdBeth>
GG
<jmercouris>
unless you wish to make your own exception type, in which case, the syntax and design leaves a lot to be desired
<jmercouris>
but that is neither here nor #python
<aeth>
jmercouris: I strongly disagree about Python's syntax. For one, "1+1" is valid. That should be invalid in any language that values readability as its goal. "1 + 1" should be enforced by the language, not by convention.
<aeth>
Having space as a separator means you get kebab-case which is superior to underscore_case, too.
<jmercouris>
well, thats a question of taste
<jmercouris>
anyways, going to sleep for now, goodnight!
jmercouris has quit [Remote host closed the connection]
<LdBeth>
Well that should pretty printers job
<LdBeth>
^be
<LdBeth>
good night
<pjb>
Well, my pretty printer would enforce 1+1 of course.
<didi>
LdBeth: I'm not familiar with Go, but I read it deals with that somehow.
<pjb>
(in languages where spaces are optional)
<aeth>
personally, I'm a fan of {1 + 1} => (+ 1 1)
<aeth>
I'm not sure if that version of it has {1+1} as invalid but the logical way to handle that transformation is to treat it very similarly to an s-expression
<pjb>
There was a macro that would parse sexps and symbol names to decode infix into sexps.
<pjb>
You could write (infix a*x^2+bx+c) -> (+ (* a (expt x 2)) (* b x) c)
<aeth>
yuck
<aeth>
it reminds me of Scheme's complex, though. iirc, 2+4i instead of #C(2 4)
<LdBeth>
There was a lot of them that you could find in CMU AI repository
<pjb>
add an asdf, push to quicklisp !
yvy has quit [Read error: Connection reset by peer]
<makomo>
pjb: source for that macro? :-)
<pjb>
Last time I saw it was more than 15 years ago, so…
<pjb>
Try searching in cll.
<pjb>
but indeed, you might find it in the AILab repo.
<pjb>
CMU AI repository
<makomo>
google is pretty helpful it seems, all's good
<aeth>
If you're porting software over, turning (x + y) / z into {{x + y} / z} is probably the best decision
<aeth>
The lack of popularity of an infix package means few people are porting things at the moment, which is bad
* fiddlerwoaroof
the bigest mistake of infix languages is operator precedence, the second biggest mistake is mixed associativity
<fiddlerwoaroof>
If you're going to do infix, J/APL have it right: all one precedence, always right-associative.
<fiddlerwoaroof>
(that way = works the way you expect)
<pjb>
Yes, this infix.cl was it.
<pjb>
But seriously, you would only need it to copy formulas from a physics textbook…
<aeth>
fiddlerwoaroof: Last time I wrote infix I didn't support mixing. So (infix (x + y - z)) was invalid. You'd have to do (infix ((x + y) - z))
<pjb>
In practice, you'd just write the code to compute your spaceship position and propulsion in pure lisp anyways.
playful-owl has quit [Quit: leaving]
<aeth>
No need to worry about precedence rules if there are none!
<pjb>
For example, if you implemented a GPS system, you could take the formula from the specifications and use an infix model to avoid having to translate them yourself.
varjag has quit [Ping timeout: 252 seconds]
<makomo>
pjb: yeah, that was the main use case i was thinking of as well
rumbler31 has quit [Remote host closed the connection]
<didi>
But a nice property of infix is the precedence. If we take it out, it's less useful.
<didi>
f(x) = b + ax
<fiddlerwoaroof>
precedence is just confusion, especially once you expand beyond standard mathematical notation
<aeth>
Is it nice if no one knows it?
<fiddlerwoaroof>
It's the worst part of custom operators in Scala and Haskell
<aeth>
Once you move past +-*/ you are asking for trouble with precedence rules
<makomo>
but still, the standard math notation is pretty... standard :-)
<didi>
Anyone who deals with mathematics formulas knows it.
resttime_ has joined #lisp
<fiddlerwoaroof>
Only in standard cases
<aeth>
Anyone who deals with math knows +-*/
<no-defun-allowed>
is f(x) f*x or x applied to f?
<didi>
If you are not writing this infix package for them, I don't know who is gonna use it.
<fiddlerwoaroof>
<$> and <*> in haskell aren't part of standard mathematical notation
* didi
shrug
<no-defun-allowed>
also the smalltalk way is a decent compromise, and 2+2*3=12 is funny
<fiddlerwoaroof>
And, I'd argue that order of operations is a misfeature in mathematical notation that's been around long enough that we don't care
<makomo>
i guess that's kinda right
<makomo>
we just got used to it :-)
<aeth>
In math, you can tell from context if the writer made a precedence mistake. Computers aren't that good (and have less context available)
<fiddlerwoaroof>
In J, foo = a $ b % c & d is always equivalent to foo = (a $ (b % (c & d)))
resttime has quit [Ping timeout: 272 seconds]
astalla has quit [Ping timeout: 272 seconds]
matzy_ has joined #lisp
<makomo>
on a related note, i really can't stand Dirac notation :^(
Essadon has quit [Quit: Qutting]
<makomo>
not sure if anyone's familiar with it, but you basically have tricks like "A = |0><0| defines an operator" so that when you apply it to some state |phi> you get A |phi> = |0><0||phi> = |0><0|phi> which is really just |0> <0|phi> where <0|phi> is the scalar product"
Mr-Potter has quit [Ping timeout: 245 seconds]
<makomo>
it's a weird mess of textual substitution and what not
<makomo>
and i don't like it one bit
<jcowan>
The worst part of Scala/Haskell operators is differentiating ==>= from =>==
<pjb>
what's their names?
<jcowan>
or *********** from ************ for that matter, at least in principle
<jcowan>
I like the Kotlin/Ada attitude: overload operators, fine; invent your own, not fine.
<pjb>
nope.
<pjb>
nothing prevents you to use double-right-arrow-equal and ge-equal instead of ==>= =>==
<pjb>
or whatever they mean.
<pjb>
In lisp too you can define such operations.
<pjb>
Just don't be silly, don't.
robdog_ has joined #lisp
<fiddlerwoaroof>
Yeah, the Haskell community tends to prefer them, though
<fiddlerwoaroof>
Or, at least, there are high-profile libraries that expect you to use them
robdog_ has quit [Remote host closed the connection]
resttime_ has quit [Quit: Leaving]
<didi>
Can I write a destructuring lambda list that takes only the N first elements? For example (that doesn't work), (destructuring-bind (a) '(1 2) a), and I'm only interested in the variable `a'.
rumbler31 has joined #lisp
<aeth>
didi: &rest rest
<aeth>
Then (declare (ignore rest))
<didi>
aeth: Thank you.
<aeth>
The declare goes after the list, so after '(1 2)
<didi>
Understood.
<no-defun-allowed>
say what i can make glasses in haskell?
<no-defun-allowed>
"save $100 in glasses with this weird package"
<makomo>
glass makers hate him!
<no-defun-allowed>
never go to an optometrist again!