jackdaniel changed the topic of #lisp to: Common Lisp, the #1=(programmable . #1#) programming language | <http://cliki.net/> <https://irclog.tymoon.eu/freenode/%23lisp> <https://irclog.whitequark.org/lisp> <http://ccl.clozure.com/irc-logs/lisp/> | SBCL 1.5.4, CMUCL 21b, ECL 16.1.3, CCL 1.11.5, ABCL 1.5.0
Oladon has joined #lisp
<DrDuck> what's the emacs plugin that highlights the associated opening paren when you add a closing paren
<Bike> i think it's built in. show-paren-mode
<DrDuck> i don't want automatic parens. very confusing
<Bike> this is independent of paredit.
<DrDuck> yeah i dont need paredit right now
<DrDuck> got rid of it
<DrDuck> i like it out of the box with the highlight match
abhixec has joined #lisp
<DrDuck> what's everyone up to?
abhixec has quit [Client Quit]
makomo has quit [Ping timeout: 245 seconds]
learning_ has joined #lisp
shifty has joined #lisp
learning has quit [Ping timeout: 268 seconds]
sjl has joined #lisp
lmln has quit [Quit: Connection closed for inactivity]
shifty has quit [Ping timeout: 258 seconds]
qop has joined #lisp
poet has quit [Remote host closed the connection]
red-dot has joined #lisp
EvW1 has quit [Ping timeout: 264 seconds]
learning_ has quit [Remote host closed the connection]
_leb has joined #lisp
Kundry_Wag has joined #lisp
Kundry_Wag has quit [Ping timeout: 245 seconds]
orivej has quit [Ping timeout: 244 seconds]
elderK has joined #lisp
<DrDuck> Is there a way to do a quick lookup of what a built-in function does, in SLIME? As in an executive summary of something you would find in the clhs, without having to actually look it up in your browser.
<White_Flame> well, the parameter list should come up by default in the minibuffe
<White_Flame> r
semz has quit [Ping timeout: 264 seconds]
<White_Flame> I don't think anybody has written up a set of shorter summaries of functions for such a purpose
<DrDuck> okay just wondered
<DrDuck> would be quite useful
<White_Flame> I always reach for the CLHS when such a question comes up. At least the complete explanation is included
krid has quit [Ping timeout: 244 seconds]
semz has joined #lisp
shifty has joined #lisp
qop has quit [Quit: q]
Necktwi has quit [Ping timeout: 244 seconds]
karlosz has joined #lisp
<stylewarning> DrDuck: DESCRIBE is often helpful
<stylewarning> (describe 'foo)
<White_Flame> yeah, that's an easy way to access the docstring, I guess
<White_Flame> in my SBCL (which granted I haven't updated in a while), defstruct has a reasonable docstring, but defclass for instance has none
<White_Flame> another simple way is to M-. into the implementation and see its comments (assuming that SLIME is aware of where the implementation's source code is)
<White_Flame> although YMMV depending on the amount of indirection found
Oladon has quit [Quit: Leaving.]
<DrDuck> thanks!
karlosz has quit [Quit: karlosz]
<beach> Good morning everyone!
Insanity_ has quit [Quit: Connection closed for inactivity]
<pjb> DrDuck: M-x common-lisp-hyperspec RET <symbol> RET
pauljb has joined #lisp
ahungry has joined #lisp
karlosz has joined #lisp
pauljb has quit [Ping timeout: 246 seconds]
<DrDuck> pjb: wow
<ck_> DrDuck: that's also built into slime, I thought you knew this already. C-C C-d h
<DrDuck> very nice
Bike has quit [Quit: Lost terminal]
<ck_> maybe you should go read some documentation
ahungry has quit [Remote host closed the connection]
ebrasca has joined #lisp
Oladon has joined #lisp
Lycurgus has joined #lisp
awolven has joined #lisp
karlosz has quit [Quit: karlosz]
ggole has joined #lisp
vlatkoB has joined #lisp
nanoz has joined #lisp
_leb has quit []
qop has joined #lisp
awolven has quit [Ping timeout: 246 seconds]
gravicappa has joined #lisp
nanoz has quit [Read error: Connection timed out]
nanoz has joined #lisp
ahungry has joined #lisp
kamog has joined #lisp
nullman has quit [Ping timeout: 244 seconds]
nullman has joined #lisp
red-dot has quit [Quit: Going offline, see ya! (www.adiirc.com)]
curliesue has joined #lisp
<DrDuck> Is this CL's way of doing some static type checking?
Lycurgus has quit [Quit: Exeunt]
<saturn2> it might do static checking, runtime checking, or no checking, it's up to the implementation
nadare has joined #lisp
jeosol has joined #lisp
pillton has quit [Ping timeout: 264 seconds]
curliesue has quit [Remote host closed the connection]
dddddd has quit [Remote host closed the connection]
sauvin has joined #lisp
abhixec has joined #lisp
Oladon has quit [Quit: Leaving.]
SaganMan has joined #lisp
<White_Flame> DrDuck: often it's a way to tell the implementation _not_ to do type checking, if it believes your assertion
<aeth> White_Flame: that's a commonly repeated assertion, but it appears to be dated in the 1990s
<aeth> White_Flame: The only place where I've seen that happen is SBCL with (safety 0) which is why no one uses (safety 0)
ahungry has quit [Remote host closed the connection]
<aeth> What's far more likely is that one of two things happens: it does checking (static in addition to runtime if possible, otherwise runtime only) or nothing
<aeth> check-type guarantees runtime (and runtime only!) checking, but with the downside that SBCL correctly determines that the value can be any type before the check-type since you can provide the correct value, meaning it doesn't really provide any optimization opportunity before that point
<aeth> That's particularly important for CHECK-TYPE as an alternative to function declarations, not THE, though.
<aeth> tl;dr: if you want types for performance use declarations including THE but be aware that it can rarely assume the type and doesn't have to check at all; if you want types for reliability, use CHECK-TYPE; else, use a macro that selects which one based on the implementation
<aeth> The same thing goes for e.g. types in defstruct/defclass slots, and in fact SBCL happens to ignore them in defclass at the default optimization levels. If you want them to always show up, you have to write your own macros (for defstruct) or MOP metaclass (for defclass)
<jeosol> what do you mean by "always show up", do you mean enforced?
<jeosol> When writing my classes, I usually write type, for documentation. If we change the optimization levels, are they then enforced?
<aeth> yeah, I mean, always enforced
<aeth> jeosol: I think SBCL does it when debug is high but I'm not sure.
<aeth> jeosol: What I'd do is I'd just write a metaclass, it's not very long
<aeth> You have to use ASSERT instead of CHECK-TYPE afaik because the type (afaik) has to be accessed at runtime, and CHECK-TYPE uses an unquoted type.
<aeth> You can use a similar metaclass to check things that cannot be done with the type sytem (well, at least without a SATISFIES type)
<jeosol> aeth: Thanks. The link very interesting. So with your implementation, the types are checked at runtime?
<aeth> yes
Sweedish has joined #lisp
<aeth> You have to runtime check DEFCLASS slots. DEFSTRUCT has (potentially) restricted redefinition so even though it's probably implemented similarly, it can make more assumptions about slot types at compile time.
<aeth> again, afaik.
<aeth> So the primary use of DEFSTRUCT is typed slots, at least ime.
<aeth> e.g. in SBCL if you have a struct slot of a type that has an array of double-floats, then (aref (your-slot your-struct) 42) won't do bounds-checking and will know that your accessed value is a double-float (or an error if your-struct isn't actually of the struct type)
Sweedish has quit [Client Quit]
<aeth> So that sort of thing is sort of the strongest case for using structs. If types are just for documentation, that doesn't matter, though.
<jeosol> I see a :before method that uses assert to check the type before assignment
<aeth> yeah, but it's :before in the MOP, so it's before any slot writing, including setters as well as (the potentially auto-generated) constructors
<aeth> Much more concise than actually trying to put checks before DEFCLASS stuff manually
<aeth> And if it's before any set then as long as it's initialized, then it's of that type (unless you do fancy things like change-class, I guess... but it's easy to break stuff like that, you can just use the debugger if you really wanted to, too, I guess)
<jeosol> yeah more concise. I have to try it out.
<jeosol> do you mean if a slot has type single-float and initialized via initargs with fixnum, the type changes?
<aeth> No, it doesn't coerce automatically.
<jeosol> ok. For this type of issues, I have often had to write defmethod specialized on 'number', not sure it's the best approach,
<aeth> What I meant is that if you did :foo (make-foo) and the change-class'd the foo then it probably would be of an invalid type. Or if you change-class'd an object to one of these objects with checked types, then the slot foo might not be, since the checks are on setting slots. I think. I haven't tested either, and I haven't really used change-class before.
<jeosol> Ok, I see what you mean. Thanks for the clarification
<aeth> Yeah, using a setter method that's specialized in number and then coercing it that way will do the trick.
<aeth> you could probably also do a similar sort of thing as my :checked-type but call it :coerced-type
<aeth> and attempt to do a COERCE in the :before instead of an ASSERT check
<aeth> would only really be useful for numbers and sequences afaik
red-dot has joined #lisp
<jeosol> ok. That will be useful trick. I often write methods for array but some operations return a list and i get issues
<aeth> You'd probably have to provide your own COERCE (with COERCE as the default) because COERCE isn't particularly powerful... I'm not sure if metaclasses are that capable (higher order metaclasses?)
jello_pudding has joined #lisp
<jeosol> oh ok.I am not an mop expert. I will need to understand yours and use it in examples
<jeosol> I normally write my methods to use array, but sometimes, I write other operations, e.g., loop + collect to return a list, and have to convert to an array to be able to call the method or i have to write two defmethods and have the list one call the array one
<jeosol> need to find better ways these kinds of small issues
jeosol has quit [Remote host closed the connection]
<aeth> I'm far from a MOP expert, I rarely use classes.
orivej has joined #lisp
bmansurov has left #lisp ["Later"]
JohnMS has joined #lisp
varjag has joined #lisp
jello_pudding has quit [Remote host closed the connection]
makomo has joined #lisp
__jrjsmrtn__ has joined #lisp
_jrjsmrtn has quit [Ping timeout: 268 seconds]
makomo_ has joined #lisp
makomo has quit [Ping timeout: 244 seconds]
sonologico has joined #lisp
Ven`` has joined #lisp
dale has quit [Quit: My computer has gone to sleep]
maxxcan has joined #lisp
maxxcan has quit [Client Quit]
mindthelion has joined #lisp
techquila has quit [Ping timeout: 276 seconds]
<stylewarning> What does the word threshold mean to people? If you have an X-THRESHOLD, then does a value need to be > or >= to the threshold before something happens?
<beach> Provided it's an upper threshold, I would say >, so that <= is fine.
<beach> In other words, the value of the threshold is an acceptable one.
<no-defun-allowed> CL is typically inclusive (eg `(loop for x from 0 to 100 ...)`) and generally legal stuffs is inclusive (eg drink-driving at 0.050, which is the legal threshold) so I'm tempted to say that.
libertyprime has joined #lisp
<stylewarning> I think I agree with these
<no-defun-allowed> If you can't decide, then `(or (and (= x threshold) (zerop (random 2))) (> x threshold))` is a good compromise
makomo_ is now known as makomo
manualcrank has quit [Quit: WeeChat 1.9.1]
<stylewarning> (logbitp 0 (get-internal-real-time))
libertyprime has quit [Remote host closed the connection]
<thijso> Anyone familiar with usocket on ECL? I'm getting "#<compiled-function USOCKET::MAP-SOCKET-ERROR> is not of type SYMBOL.", but when I search the source, I only find MAP-SOCKET-ERROR in backends sbcl, scl, mocl, and cmucl? Is that the reason for the error? It's not defined in ECL? Or do I need to look elsewhere?
frodef has joined #lisp
<thijso> (And to maybe shortcircuit this question: if anyone has a working example for datagram two-way communication on ECL I would be very interested to have a look...)
<thijso> And btw, why is it so hard to find UDP communications examples? My google-fu is maybe just lacking...
Ven`` has quit [Read error: Connection reset by peer]
<thijso> Hmm, looking at the usocket.asd it looks like ecl uses the sbcl.lisp backend...
<thijso> Yeah, sbcl.lisp is filled with #+ecl etc stuff... Looks like I'm gonna be digging for a while.
<beach> I have two questions about multiple values. We know that MULTIPLE-VALUE-PROG1 needs to save the values computed by the evaluation of the first form (in some unknown place) until the remaining forms have been evaluated.
<beach> First question: Is it possible that a Common Lisp program can have two such active secret places simultaneously, and if so, what would such a program look like.
<beach> Second question: Is it possible for the dynamic environment to be different when some multiple values are saved and when those values are needed? I.e., can there be an additional binding of a dynamic variable in one place, or can one place be inside a BLOCK, and one place not?
<beach> I am thinking "no" and "no", but I sometimes overlook things.
<beach> Actually, the answer to my first question is probably "yes", but I meant to ask it differently.
<beach> I meant to ask whether saved multiple values are always used in a LIFO order. And I think the answer is "yes".
catchme has joined #lisp
<beach> So in (multiple-value-prog1 <form1> (f (multiple-values-list (multiple-value-prog1 <form2> <form3)))), clearly the values computed by the evaluation of <form1> and those computed by the evaluation of <form2> are simultaneously live when <form3> is evaluated.
<ggole> Isn't it just like prog1, but with more than one saved value?
<beach> It is. But prog1 is a macro and it can be turned into a LET.
<beach> Not so with multiple-value-prog1, because we don't know how many places to reserve. Unless we allocate memory, of course.
<ggole> Right, unless you use a list or something
<thijso> hmmm... There's a (declare (type symbol usock-error)) in there, which if I remove it, I get UNKNOWN_ERROR instead with the much more helpfull message: The condition Socket error in "send": 89 (Destination address required) occurred with errno: 0.
Lord_of_Life has quit [Ping timeout: 245 seconds]
Lord_of_Life has joined #lisp
<beach> ggole: But I think you answered my question, because a valid (but wasteful) "expansion" of (multiple-value-prog1 <form1> <form>*) would be (let ((<gensym> (multiple-value-list <form1>))) <form>* (apply #'values <gensym>))
<beach> And it is clear that the same dynamic environment is present when the <gensym> is defined as when it is used.
<ggole> That's what I was thinking, yes
kamog has quit [Read error: Connection reset by peer]
<beach> Thanks for your help.
<ggole> But I thought that you were probably looking for a more efficient alternative
<beach> Well, I can't quite apply this solution, because I already have a program in high-level intermediate representation that has explicit representations for locations with multiple values.
<beach> And I need to turn that representation into Common Lisp code for execution in a host Common Lisp system.
<beach> So, for this particular usage, efficiency is not a problem.
<ggole> I see.
<beach> But it's to late to consider multiple-value-prog1 as a macro, because it has already been turned into intermediate code.
<beach> But I do keep an explicit dynamic environment, so I should be able to push a special type of entry on it, indicating saved multiple values, and when I need those values, I should be able to assert that this entry is the top one in that environment.
<thijso> Oh, that's really great. ECL implements sb-bsd-sockets, but not really. socket-receive only returns buffer and length and not the rest (i.e. remote-host and remote-port).
<ggole> Is there some obstacle to using a regular binding?
<beach> I guess not.
<beach> If all this is true, then there is a simple implementation of multiple-value-prog1. Just push all the values on the control stack (including a number indicating how many there are), and pop them off when they are needed.
<ggole> If you are happy with variable sized activation frames, yeah
<beach> I am.
<beach> The plan is to access lexical data using the base pointer.
<ggole> If the number of values can be huge you might have some issues
jello_pudding has joined #lisp
<beach> I am happy to set a safe (but high-ish) limit as the Common Lisp HyperSpec allows.
<ggole> Right, seems reasonable to me.
<beach> Or, not. I could just punish the programmer who uses a huge number by giving him or her inefficient code. :)
<ck_> weren't you just punished like that by sbcl?
<beach> Really? Am I using that many multiple values?
<ck_> I meant in the more general sense, inefficient behaviour for 'large' inputs
<beach> Ah, yes, that.
<beach> I am not planning such a general punishment scheme if I can avoid it.
<ck_> :)
random-nick has joined #lisp
asdf_asdf_asdf has joined #lisp
vms14 has joined #lisp
<vms14> I made what you said, using write instead of format and collect instead of formatting to arrays
<vms14> do you have more hints?
<vms14> there is something wrong, or a way to improve it?
<vms14> I rewrote all, so I'm testing it, but it seems to work fine
<vms14> (oneliner "print get('http://example.com')" :modules "LWP::Simple")
hiroaki has quit [Ping timeout: 245 seconds]
<beach> vms14: Your indentation is off. Either you are not using the slime-indentation contribution, or the paste service doesn't handle TABs very well, or perhaps both.
<beach> vms14: LOOP clauses should be aligned so that the clause keywords start in the same column.
<beach> You may not get that without slime-indentation.
<vms14> it's not the service fault
<beach> Also, it is not good style to use non-Booleans as Booleans. It "violates the expectations" of the reader as page 13 of the LUV slides indicates.
<vms14> beach: how to make emacs auto indent all the buffer?
<beach> C-x h then C-M-\
<beach> So when you write WHILE LINE and WHILE BYTE you violate these expectations.
<vms14> it changed nothing
<beach> Then you are not using the slime-indentation contribution.
<vms14> isn't it with slime fancy?
<beach> I don't remember.
<beach> Same thing with (WHEN MODULES.
<vms14> it said indenting region and I tend to use M-q to indent sexp
<vms14> then how I should do it?
<ck_> slime-indentation is not with slime-fancy.
<beach> It should work as I said if you are using slime-indentation.
<ck_> add it to your .emacs: (slime-setup '(... slime-indentation))
<vms14> beach: why unless null instead of just if?
<beach> Let me look again.
<thijso> Am I wrong in thinking the usual process with UDP communications is: RECEIVE -> optionally REPLY to the sending host:port with something? That implies you need to get the sending host:port, but the implementation of SOCKET-RECEIVE in ECL ignores those values. Is it that nobody has yet tried to use UDP sockets with ECL, or am I missing something?
<beach> ck_: If is used when the value is needed, and then both branches should have expressions in them.
<beach> vms14: If is used when the value is needed, and then both branches should have expressions in them.
<beach> Sorry ck_.
<beach> vms14: WHEN and UNLESS are used in a context where the value is not needed.
<beach> vms14: Instead of your DOLIST, you could use a combination of APPEND, SETF, and REVERSE.
<beach> vms14: There is a distinction between using NIL and using '() in a LET binding. NIL means a Boolean false value or a default value, and '() means the empty list.
<|3b|> vms14: does it return what you expect with :binary-output t :output-as-list nil ?
* |3b| thinks it wouldn't be what i expect at least
<beach> vms14: 'NIL means the symbol NIL, and no initialization form means that you intend to assign to the variable before using it.
jello_pudding has quit [Remote host closed the connection]
<|3b|> also, reading by bytes is probably inefficient, not sure how much you care about handling large amounts output well though, so might not be worth more complex code
<vms14> |3b|: I've tried with hunchentoot
<beach> vms14: You can say (let ((argument-list (append arguments (reverse files)))) rather than initializing to the empty list and then looping
<vms14> the binary-output works fine with hunchentoot when you use output-as-list too
<vms14> but without nope
<beach> vms14: You should probably rename output-as-list to output-as-list-p to make sure it is interpreted as a Boolean value.
<vms14> right
<vms14> same with binary-output
varjag has quit [Remote host closed the connection]
<beach> OK, that's a dozen or so remarks that you can work on if you like.
varjag has joined #lisp
gxt has quit [Ping timeout: 260 seconds]
<vms14> I've changed while for until and the when of modules by unless
<vms14> but I don't see the point in doing it
<beach> That's because you are thinking that your code is meant for the compiler.
<beach> Yet you are submitting it for humans (us) to read.
* |3b| as a reader prefers (WHEN X ...) to (UNLESS (NULL X) ...)
<vms14> that's why
<vms14> when something isn't it clearer than unless not something?
<beach> vms14: And I highly recommend the LUV slides by Norvig and Pitman who are way more experienced in this kind of situation than I am.
<beach> vms14: WHEN and UNLESS take Boolean values as the first form.
* |3b| parses it as "WHEN X [is not NIL]" and "UNLESS ( [I need to think about this]"
<beach> vms14: MODULES is not a Boolean value.
<beach> vms14: It is a list of modules.
<|3b|> they take generalized boolean values :)
abhixec has quit [Ping timeout: 245 seconds]
<beach> |3b|: Now you are talking about the semantics. I am talking about the expectations of the person reading the code.
<|3b|> beach: i'm talking about the expectations of the person when the person is me :)
<vms14> XD
<beach> Yes, but I am reading the code by vms14 and I am not you.
<vms14> my code is shit, this is why I tend to ask
<|3b|> right, which is why i started with saying /i/ prefer
varjag has quit [Ping timeout: 246 seconds]
abhixec has joined #lisp
<beach> So I am referring to Norvig and Pitman who are neither you nor me, but both are much more experienced.
<vms14> but I'm happy that works
<vms14> until I test it more or add stuff
* |3b| is providing another perspective, not saying you are wrong
<beach> vms14: I am not expressing myself very clearly, apparently.
<|3b|> i'd accept a request to change it if working on your code, but i'd prefer WHEN X in my code :)
<beach> vms14: You are submitting your code for other to read, so you are *not* just happy that it works.
<vms14> not really, I want to learn how to design programs
<vms14> so I'll remember every hint or advice I'll get
<beach> vms14: You are apparently expecting others to read it, so then it is a very very good idea to respect conventions established by highly experienced Common Lisp programmers such as Norvig and Pitman.
<vms14> you gave me a good link some time ago
<vms14> but I've lost it, do you have it?
<beach> Google for LUV slides and Norvig and Pitman
<vms14> ty
* |3b| notes that those slides also say to sign and date your comments :)
<ck_> I always wonder how they got presented -- on transparencies?
<beach> Possibly.
<beach> Signing and dating comments was probably way more useful before we had as reasonable source control as we do now.
<beach> But I think it might still be a good idea.
<vms14> just create one emacs command that puts some name and the current date
<vms14> it seems a good idea
<beach> Yeah, I think it is.
* |3b| thinks that is a tool problem that we shouldn't need to do manually, but agrees that the tools are still lacking
<Shinmera> Or just use git-blame to get the comment author and date
<|3b|> yeah, more transparent version of git blame is what i was thinking of
<vms14> thanks for your hints, I'll take a look at this pdf and think about what it says
<vms14> see you
vms14 has quit [Remote host closed the connection]
<Shinmera> Running magit-blame in a buffer will show you which sections were last modified when and by whom. Easy enough to use when it is important to know.
<ck_> I believe it is also part of standard emacs, C-x v g
Lord_of_Life has quit [Read error: Connection reset by peer]
Lord_of_Life has joined #lisp
cosimone has joined #lisp
Bike has joined #lisp
red-dot has quit [Quit: Going offline, see ya! (www.adiirc.com)]
namosca has joined #lisp
superkumasan has quit [Ping timeout: 246 seconds]
cl-arthur has joined #lisp
random-nick has quit [Ping timeout: 258 seconds]
<no-defun-allowed> Anyone ever seen a parser for ASCII-art guitar tablature?
alexanderbarbosa has joined #lisp
<no-defun-allowed> Or, I guess, any parsers that can work with two-dimensional input of some kind?
<ck_> mondrian comes to mind, I don't think it has an ascii form of expression though
sonologico has quit [Remote host closed the connection]
<no-defun-allowed> Is there a website for Mondrian?
<ck_> it's called by his first name: http://www.dangermouse.net/esoteric/piet.html
sonologico has joined #lisp
papachan has joined #lisp
<no-defun-allowed> HAH! Good point.
cosimone has quit [Quit: Leaving]
<stepnem> *grumble* why does MAX / MIN not have :key? Also LOOP :maximize etc...
EvW has joined #lisp
<no-defun-allowed> So, (stepnem:max '((1 . 2) (3 . 4) (5 . 1)) :key #'cdr) ↦ (3 . 4)?
<stepnem> Yeah.
<no-defun-allowed> I forgot max has a lambda-list (&rest numbers), maybe adding keyword argument parsing to that would be awkward
lnh^ has joined #lisp
<no-defun-allowed> Tomorrow I guess I'll take a peep at making a 2d monadic-ish parser, since I'm only familiar with making monadic-ish parsers for 1 dimensional inputs.
<stepnem> Maybe. It's hard to believe other people never go "is there no better way?" when doing something like (car (sort stuff #'> :key #'cdr)), though...
namosca has quit [Ping timeout: 245 seconds]
<flip214> stepnem: yeah, everybody knows it should be (first (sort ...)) ;)
<stepnem> heh
<no-defun-allowed> ck_: http://www.dangermouse.net/esoteric/piet/piet_pi.png cracks me up every time, though.
<ck_> yes, the language has much potential for amusing self references
random-nick has joined #lisp
sonologico_ has joined #lisp
sonologico has quit [Ping timeout: 252 seconds]
shifty has quit [Ping timeout: 246 seconds]
Inline__ has joined #lisp
wxie has joined #lisp
<semz> > If you know type information, declare it.
<semz> I want to agree with this point, but how would you do this without landing in funland when a declaration is wrong, like you would with DECLARE?
<semz> explicit CHECK-TYPEs seem clunky
Inline has quit [Ping timeout: 264 seconds]
<semz> e.g. CCL will generate "bogus objects" if you try to add two strings that are declared as fixnums, even at the default security level
Ekho has quit [Quit: An alternate universe was just created where I didn't leave. But here, I left you. I'm sorry.]
<beach> If the declaration is wrong, you obviously don't know the type information.
frodef has quit [Ping timeout: 246 seconds]
lucasb has joined #lisp
Ekho has joined #lisp
cosimone has joined #lisp
<semz> What if the declaration is correct but the call is wrong? My problem with this is mostly that it seems to open the door for corruption issues.
<semz> Like I hinted at before, (defun test (x y) (declare (type fixnum x y)) (+ x y)) (type-of (test "hello" "world")) causes at least CCL to yell about potential implementation bugs.
<semz> Obviously you could always use a custom macro wrapping DEFUN but maybe there's a better solution that's already here
<cl-arthur> You could use a convenience macro to automatically generate asserts on types, and then later change it to generate type declarations instead, once sure enough that the calls are correct.
frodef has joined #lisp
<beach> semz: The declaration means that you guarantee that all calls provide the right type, so if there is a call with the wrong type, then the declaration is wrong.
<beach> semz: Just don't declare the type. Why do you insist?
<semz> I don't insist, the style guide above does!
<beach> semz: Yes, but you obviously don't know the type, so the premises of the style guide are not applicable in your case.
<beach> You know what the type OUGHT TO BE, but that's not what the style guide says.
EvW has quit [Ping timeout: 264 seconds]
lalitmee has joined #lisp
sonologico_ has quit [Quit: Leaving]
<semz> I guess the section can be read this way, though I certainly would have never done that.
<beach> I declare types only in code that needs to be very fast, so it also has other declarations. Mostly I program with generic functions and methods, so the type is determined by generic dispatch, and the method specializer shows the type for documentation as well.
asdf_asdf_asdf has quit [Quit: asdf_asdf_asdf]
EvW1 has joined #lisp
Inline__ has quit [Quit: Leaving]
qop has quit [Ping timeout: 252 seconds]
vms14 has joined #lisp
cosimone_ has joined #lisp
<pjb> DrDuck: THE is the opposite of "static typing". THE is the programmer telling the compiler: you are an idiot, you don't know what type this expression is, let me tell you!
<pjb> DrDuck: basically, THE will be banned as soon as SJW will start doing CL.
JohnMS has quit [Quit: Konversation terminated!]
cosimone has quit [Ping timeout: 250 seconds]
cosimone__ has joined #lisp
<edgar-rft> semz: "If you know type information, declare it." to me also reads as "If you don't know type information for sure, don't declare it".
<pjb> DrDuck: the only case where you can use THE, is something like: (defun foo (s) (if (some-complex-predicate-p s) 42 "foo")) (list (the 'fixnum (foo 0)) (the 'string (foo t)))
<pjb> DrDuck: ie. when you know your compiler is dumb enough not to be able to infer the type of the expression foo, because this would involve solving the termination problem, then you can tell it, but as you can see, this works only if YOU are able to prove it!
<pjb> DrDuck: it's much better not to use THE, and let the compiler deal with all types of results.
SaganMan has quit [Quit: WeeChat 1.6]
<semz> edgar-rft: maybe it's because i originally came from statically typed languages
cosimone_ has quit [Ping timeout: 246 seconds]
<semz> where "don't let the type be inferred, declare it for ease of the reader" is a thing
EvW1 has quit [Ping timeout: 276 seconds]
<pjb> aeth: good point about change-class. Normally, one would change-class amongst subclasses of a common superclass, so a type would always be the superclass. But we could also have fun: assume library A expecting TA and library B expecting TB with no other common superclass than T. Then you could start with a subclass of TA, process it with library A, and change-class it to a subclass of TB to continue process it with TB.
kajo has quit [Ping timeout: 250 seconds]
wxie has quit [Ping timeout: 250 seconds]
<edgar-rft> semz: in contrast to most other languages, in Lisp the *value* itself carries the type information, not the variable (except if you declare it as having a type). For example (type-of 10) => INTEGER, where it's the 10 itself that tells "I'm an integer".
<pjb> aeth: now, question: is the Hindley–Milner type inference algorithm able to deal with time?
<pjb> edgar-rft: declaring the type of a variable only declares that you will only bind values of that type to that variable.
<semz> edgar-rft: I know. Lisp is pretty much the only language where I accept this sort of thing because you actually get something in return for it.
ravenous_ has joined #lisp
<edgar-rft> pjb: thanks for overly pedantic nitpicking, but as usual you're right :-)
<pjb> beach: you can have several multiple-value-prog1 forms active at the same time with threads and even possibly with coroutines.
<pjb> (multiple-value-prog1 (multiple-value-call (function values) 1 (multiple-value-prog1 (values 2 3 4) (print 'hi)) 5) (print 'done)) #|
<pjb> hi
<pjb> done --> 1 ; 2 ; 3 ; 4 ; 5 |#
<pjb> and even without, if you optimize out this multiple-value-call: 1 needs to be stored somewhere at the same time as 2 3 and 4.
<pjb> Same if values is open-coded: (multiple-value-prog1 (values 1 (multiple-value-prog1 2 (print 'hi)) 3) (print 'done))
<pjb> beach: it seems to be that it's a problem of data flow optimization. If you open code multiple-values, you can even avoid storing those that are not used.
kamog has joined #lisp
learning has joined #lisp
manualcrank has joined #lisp
elderK has quit [Quit: WeeChat 1.9]
elderK has joined #lisp
elderK has quit [Client Quit]
<beach> pjb: Yes, several can be active, but for a particular process, they are LIFO.
<beach> pjb: Thanks for the additional insight.
kajo has joined #lisp
papachan has quit [Ping timeout: 244 seconds]
kajo has quit [Read error: Connection reset by peer]
cosimone__ has quit [Quit: Leaving]
vms14 has quit [Remote host closed the connection]
bmansurov has joined #lisp
red-dot has joined #lisp
cosimone has joined #lisp
frodef has quit [Ping timeout: 258 seconds]
EvW has joined #lisp
Oladon has joined #lisp
alexanderbarbosa has quit [Ping timeout: 252 seconds]
lalitmee has quit [Remote host closed the connection]
lalitmee has joined #lisp
carloss has joined #lisp
carloss has quit [Quit: Leaving]
dddddd has joined #lisp
salinasc has joined #lisp
ravenou__ has joined #lisp
ravenous_ has quit [Ping timeout: 252 seconds]
salinasc has quit [Client Quit]
carloss has joined #lisp
carloss has quit [Read error: Connection reset by peer]
salinasc has joined #lisp
varjag has joined #lisp
alexanderbarbosa has joined #lisp
learning has quit [Remote host closed the connection]
learning has joined #lisp
nanoz has quit [Ping timeout: 245 seconds]
<DrDuck> pjb: PG gives an example of code and says it is what fast CL code looks like. He just notes that CL can be sped up by aiming for tail-call optimization and shares a snippet or two.
<DrDuck> Here is one:
<DrDuck> maybe compilers were not as mature back then
knicklux has quit [Remote host closed the connection]
<pjb> DrDuck: fast CL code depends on the implementation.
<DrDuck> okydoke
<DrDuck> using abcl atm
<pjb> Don't worry about speed. Worry about correctness, and about using algorithms that are not too complex (in the O(f(n)) sense) for your data sizes.
<beach> DrDuck: High performance code depends more on the use of good algorithms and data structures. It is often a mistake to attempt low-level optimizations at an early stage.
<beach> Many times, if there is a problem at all, it can be isolated to just a small portion of code.
<beach> Then that small portion can be optimized. But you won't know which portion it is until you measured without optimization.
<DrDuck> If calling compile on the same function twice is unspecified in the language specification, how can you get to the point where you're able to continuously update a program without killing and restarting it?
lalitmee has quit [Remote host closed the connection]
<beach> DrDuck: You might not have the same idea as the standard about what it means to "compile the same function twice".
<|3b|> COMPILE works on compiled functions
<|3b|> it isn't specified to do nothing, but it is specified to work
<DrDuck> "
<beach> DrDuck: Most frequently, COMPILE is not called on a function, but on a lambda expression. And most often COMPILE is not called at all, and instead COMPILE-FILE is called.
<|3b|> and binding new (global) functions to a name is well defined too
<|3b|> possibly "changing the global function binding for a name" is a more precise way to say what i meant??
<DrDuck> "There are two sorts of functions which you can't give as an argument to compile. According to CLTL2 (p. 677), you can't compile a function 'defined interpretively in a non-null lexical envoronment.' [. . .] You also can't call compile on a function which is already compiled. In this situation, CLTL2 hints darkly that 'the consequences. . .are unspecified.'"
<DrDuck> This is directly from 'On Lisp'.
<DrDuck> O_o
<beach> DrDuck: Consult the standard for conforming behavior.
Inline has joined #lisp
<DrDuck> Is CLTL2 the latest standard?
<beach> DrDuck: CLtL2 is not the standard.
<beach> Never was.
<|3b|> right, you still can't pass a closure to COMPILE in ANSI CL, and the latter apparently changed between cltl2 and ansi
<DrDuck> O_o
<beach> Never will be.
<beach> clhs compile
<beach> "If the definition is already a compiled function, compile eitehr produces that function itself, ... or an equivalent function.
<beach> "
<|3b|> actually i guess it is a bit more general than "closure", but probably "closure" in practice
<pjb> DrDuck: the thing is that the implementation specific parts of the behavior are actually small and known.
<pjb> DrDuck: the question is actually that of the compilation-unit.
<|3b|> but using COMPILE directly on arbitrary functions is fairly uncommon
<pjb> DrDuck: if you compile part of a compilation-unit, you may get surprising and non-conforming results.
<|3b|> (using it directly at all is fairly uncommon for that matter)
<pjb> DrDuck: but if you compile with the same compilation-units, it will be fine.
<|3b|> the most popular CL implementations compile everything by default anyway
<pjb> DrDuck: inside a compilation unit, an implementation is permitted to inline any function that is not declared notinline.
<pjb> DrDuck: therefore if you recompile outside of the compilation unit, a function that has been inlined in another, you will get two different functions, which can be a problem for the logic of your program if the semantic of your function has changed.
<DrDuck> |3b|: If it's so uncommon how do people make programs that they can update continuously without restarting said program in CL. Sorry for the dumb question, since I'm pretty early in the book.
<DrDuck> pjb: that helps a bit
<pjb> DrDuck: if you want to do that, you can just declare the function notinline.
Oladon has quit [Quit: Leaving.]
<|3b|> DrDuck: you don't (compile 'foo (fdefinition foo)), which is what would have problems
<pjb> DrDuck: but you still have to be smart: recompiling a function or a whole compilation unit won't replace the functions that are active, being evaluated. You have to deal it yourself.
<|3b|> (compile 'foo '(lambda () ...)) is perfectly fine and well defined
<|3b|> but usually we would just evaluate (defun foo ()...)
<|3b|> either in repl or with some shortcut in an editor that knows how to send the definition to the running lisp (C-c C-c in emacs with slime for example)
<pjb> (compile (compile (compile 'foo '(lambda () \...)))) works too: #| --> foo ; nil ; nil |#
Insanity_ has joined #lisp
<|3b|> or reload the entire file (possibly compiling the whole file with compile-file first if we know the implementation doesn't compile by default)
<pjb> (defun foo () 42) (compile 'foo) (compile 'foo)
<DrDuck> can you reload an entire file programmatically?
<|3b|> explicit use of COMPILE these days is pretty much only useful for runtime code generation on the more popular implementations
<DrDuck> at runtime
<|3b|> (LOAD "file")
<DrDuck> oh lulz
<pjb> |3b|: LOAD defines a compilation unit but you must be careful: the system may use other compilation units than the file! So just reloading/recompiling a file may still be in the implementation specific domain.
<pjb> |3b|: you need to load or compile the compilation-units!
<|3b|> or (load (compile-file "file"))
<DrDuck> yeah that's what i wanna do. generate code at runtime
<DrDuck> eventually
<pjb> (with-compilation-unit () (dolist (file '("file1" "file2" "file3")) (load (compile-file file))))
<|3b|> the case the book was talking about is if you do (defun foo ()...) in an implementation that doesn't compile by default, then wanted to do (compile 'foo) to turn an interpreted function into a compiled function
<|3b|> calling (compile 'foo) twice was apparently unspecified in cltl2, but is well defined in ansi cl
<|3b|> the other case is that (let ((x 1)) (defun foo ()...)), (compile 'foo) is undefined even in ansi CL
<DrDuck> Well as beach quoted, "If the definition is already a compiled function, compile either produces that function itself (i.e., is an identity operation) or an equivalent function. "
<|3b|> right, well defined in ANSI CL :)
<DrDuck> That is still a tad ambiguous. Looks like it gives implementers some wiggle room to not change behavior at some point if they feel like it.
<beach> DrDuck: Yes, but you still don't seem to understand the situation where a function would be compiled twice.
<DrDuck> but it's better than undefined
<|3b|> it might do extra work, but the result is a compiled function that behaves as expected
<beach> DrDuck: In your opinion, what would be such a typical use case?
<|3b|> and again, you don't usually do that anymore :)
<|3b|> evaluating (defun foo () ...) multiple times, possibly with different ..., isn't affected by any of those problems
<beach> DrDuck: Can you please indicate what typical actions on the part of a developer would result in a function that is already compiled being compiled again?
<|3b|> or calling (compile 'foo '(lambda ...)) multiple times, or calling compile-file on a file containing (defun foo ...)
Inline has quit [Quit: Leaving]
* |3b| apologizes if i'm repeating too much, trying to be precise since details like that can be confusing later if you miss it
<beach> I think DrDuck still has the wrong idea of what it means for a function to be compiled more than once.
<DrDuck> beach: idk yet. maybe if i have a collection of nodes that are using the same function to do some operation and some of the nodes re-define the function for whatever reason to help them get better answers
<beach> So I think DrDuck is under the impression that such a situation is more common than it really is.
<|3b|> yeah, other reason for the extra repetitions :)
<DrDuck> i don't wanna do common CL programming. i wanna take it to the limit xD
<DrDuck> common CL programming
<DrDuck> lol
<DrDuck> xD
ebrasca has quit [Remote host closed the connection]
<DrDuck> i guess redefining is different from recompiling
<beach> DrDuck: Redefining a function is not compiling it twice. If you redefine it, a new lambda expression (which is not a function) is created, and that lambda expression is then compiled into a function. The function thus generated replaces the old one.
<|3b|> right
Inline has joined #lisp
<|3b|> COMPILE turns an interpreted function or a lambda form into a compiled function, it is useless to call it on compiled functions
<|3b|> so you only want to call it if you have interpreted functions (which is uncommon, since popular implementations compile them to start with), or if you are generating lambda forms in code
salinasc has quit [Ping timeout: 245 seconds]
<DrDuck> yeah i guess i don't have a use case right now lol
<|3b|> both of those are well specified (aside from interpreted closure functions)
khisanth_ has quit [Ping timeout: 245 seconds]
<beach> DrDuck: Perhaps when you see the phrase "compile a function", you think it means "compile code, thereby turning it into a function". But that's not what it meant. It literally means taking an existing object that happens to be a function and applying COMPILE to it.
<beach> not what it means
<DrDuck> yeah i was confused
leb has joined #lisp
<beach> There is a very good glossary in the Common Lisp HyperSpec. I suggest you look up the word "compile" there.
abhixec has quit [Ping timeout: 244 seconds]
<DrDuck> bookmarked it
<DrDuck> one last silly question
<DrDuck> a quote from the book
<DrDuck> "In some earlier dialects of Lisp, functions were represented as lists. This gave Lisp programs the remarkable ability to write and execute their own Lisp programs. In CL, functions are no longer mode of lists -- good implementations compile them into native machine code. But you can still write programs that write programs, because lists are the input to the compiler."
<DrDuck> did the old style of lisp give more power since functions were always represented as lists, or have i just misunderstood the statement?
<|3b|> not really any power you would really want (or be able to rely on)
khisanth_ has joined #lisp
<|3b|> if you are interpreting a list directly, you could theoretically have a function that destructively modified the list defining itself
<|3b|> but then you can't compile it, or expect that program to work portably even on other implementations that interpret lists directly, etc
<|3b|> code in the form of lists is still as easy to modify/generate/etc while it isn't running as it was with the older style
ravenous_ has joined #lisp
<DrDuck> okay :p
<|3b|> and instead we get fast compiled code :)
ravenou__ has quit [Ping timeout: 264 seconds]
<|3b|> note that CL semantics are defined in terms of evaluating lists, symbols, etc, not in terms of program text
<|3b|> and turning program text into those lists, symbols, etc is a separately defined process (READ, etc), independent from compilation/evaluation
leb has quit []
<|3b|> though CL doesn't enforce any boundaries between the various steps, so READ is configurable (with reader macros)and can run arbitrary code, COMPILE is configurable (with macros, etc) and can run arbitrary code, and both READ and COMPILE are generally always available, so you can READ or COMPILE from arbitrary code :)
<|3b|> (possibly not common to take advantage of those abilities, but there if you want it, for DSLs or whatever)
<|3b|> or you can use something other than READ, and parse files yourself to generate input for COMPILE, or just generate it directly
<|3b|> or you can call READ and pass it to your own compiler, for example generating JavaScript or GPU shaders or whatever
ravenou__ has joined #lisp
learning has quit [Remote host closed the connection]
ravenous_ has quit [Ping timeout: 252 seconds]
catchme has quit [Quit: Connection closed for inactivity]
vaporatorius has quit [Read error: Connection reset by peer]
vaporatorius has joined #lisp
vaporatorius has quit [Read error: Connection reset by peer]
jeosol has joined #lisp
X-Scale has quit [Quit: HydraIRC -> http://www.hydrairc.com <- Organize your IRC]
X-Scale has joined #lisp
mathrick has quit [Ping timeout: 276 seconds]
cosimone has quit [Quit: Leaving]
learning has joined #lisp
vaporatorius has joined #lisp
vaporatorius has joined #lisp
vaporatorius has quit [Changing host]
lalitmee has joined #lisp
aautcsh has joined #lisp
nanoz has joined #lisp
EvW has quit [Ping timeout: 250 seconds]
yoeljacobsen has joined #lisp
EvW1 has joined #lisp
lalitmee has quit [Remote host closed the connection]
makomo has quit [Quit: WeeChat 2.4]
shifty has joined #lisp
semz has quit [Ping timeout: 264 seconds]
bradfonseca has joined #lisp
dale has joined #lisp
yoja has joined #lisp
Lord_of_Life has quit [Ping timeout: 244 seconds]
yoeljacobsen has quit [Ping timeout: 246 seconds]
notzmv has joined #lisp
semz has joined #lisp
semz has quit [Changing host]
semz has joined #lisp
Necktwi has joined #lisp
lalitmee has joined #lisp
superkumasan has joined #lisp
karlosz has joined #lisp
Necktwi has quit [Ping timeout: 245 seconds]
SN_ has joined #lisp
red-dot has quit [Read error: Connection reset by peer]
SN_ is now known as red-dot
learning has quit [Remote host closed the connection]
Oladon has joined #lisp
mathrick has joined #lisp
learning has joined #lisp
yoja has quit [Ping timeout: 246 seconds]
renzhi has joined #lisp
namosca has joined #lisp
<mrcode_> is it possible in CLOS to 'upgrade' a base class to one of its derived classes ?
<Bike> clhs change-class
<Bike> maybe?
Lord_of_Life has joined #lisp
<|3b|> yeah, you can change it to completely unrelated classes if you want
<mrcode_> hmmm... looks like it will work. thx Bike
<pjb> change-class doesn't change a class, it changes an instance. It changes the class of an instance.
<pjb> mrcode_: you can add slots to a class until it looks like one of its subclasses. An you can add methods to generic functions until they all have the same methods as its subclass…
dmiles has quit [Ping timeout: 246 seconds]
pfdietz has joined #lisp
akoana has joined #lisp
dmiles has joined #lisp
aautcsh has quit [Ping timeout: 252 seconds]
hiroaki has joined #lisp
ggole has quit [Quit: Leaving]
lalitmee has quit [Remote host closed the connection]
frodef has joined #lisp
ravenou__ has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
gravicappa has quit [Ping timeout: 245 seconds]
t58 has joined #lisp
makomo has joined #lisp
vlatkoB has quit [Remote host closed the connection]
Bike has quit [Quit: Lost terminal]
renzhi has quit [Ping timeout: 246 seconds]
<equwalp> exit
<edgar-rft> equwalp: try (exit)
lnh^ has quit []
<verisimilitude> What are you wanting, equwalp?
<equwalp> I missed a slash
<equwalp> so /exit, sorry
<equwalp> (exit)
Lord_of_Life_ has joined #lisp
<edgar-rft> error: there is no exit
<equwalp> there is with ERC
Lord_of_Life has quit [Ping timeout: 246 seconds]
<edgar-rft> Oh, sorry, if I had known that you're using Elisp I had given an obscue an non-understandable error message.
<edgar-rft> Debugger entered--Lisp error: (void-function exit)
Lord_of_Life_ is now known as Lord_of_Life
bradfonseca has quit [Quit: Konversation terminated!]
namosca has quit [Ping timeout: 246 seconds]
<pjb> equwalp: or /quit if you want to exit from irc.
<pjb> equwalp: you can also add a good bye message: /quit Good Bye Friends! See you soon!
<pjb> equwalp: or: /quit Good Bye, Cruel World! ; depending on the mood.
nanoz has quit [Ping timeout: 244 seconds]
<aeth> pjb: The only type system I know is CL's.
<pjb> ;-)
<aeth> The other languages I know are purely dynamic without an emphasis on types, unlike CL (e.g. JS only has "number" and even Scheme usually only has one floating point type) or where the type is basically just related to the hardware (like C). I guess there's the third category, elaborate class hierarchies, but no one *knows* those.
EvW1 has quit [Ping timeout: 264 seconds]
xkapastel has joined #lisp
leb has joined #lisp
<aeth> It's interesting just how different even Scheme is, where the emphasis of types is things that satisfy a predicate, not stuff like CL's (or (integer -37 -4) (integer 4 37))
learning has quit [Remote host closed the connection]
learning has joined #lisp
Volt_ has joined #lisp
Oladon has quit [Quit: Leaving.]
random-nick has quit [Ping timeout: 244 seconds]
nydel has quit [Ping timeout: 245 seconds]
vms14 has joined #lisp
namosca has joined #lisp
qop has joined #lisp
Oladon has joined #lisp
namosca has quit [Ping timeout: 244 seconds]
vms14 has quit [Remote host closed the connection]
learning has quit [Remote host closed the connection]
learning has joined #lisp
renzhi has joined #lisp
qop is now known as Nomenclatura
akoana has left #lisp ["Leaving"]
leb has quit []
t58 has quit [Remote host closed the connection]
t58 has joined #lisp
frodef has quit [Ping timeout: 244 seconds]
varjag has quit [Ping timeout: 245 seconds]
shifty has quit [Ping timeout: 258 seconds]
notzmv has quit [Ping timeout: 246 seconds]
Nomenclatura has quit [Quit: q]
renzhi has quit [Ping timeout: 245 seconds]
Oladon has quit [Quit: Leaving.]
leb has joined #lisp
makomo has quit [Ping timeout: 245 seconds]
impulse has joined #lisp
makomo has joined #lisp
awolven has joined #lisp
lucasb has quit [Quit: Connection closed for inactivity]
Nomenclatura has joined #lisp
techquila has joined #lisp
mindthelion has quit [Ping timeout: 244 seconds]
FennecCode has joined #lisp
akoana_ has joined #lisp
akoana_ has quit [Client Quit]
akoana has joined #lisp