freenode/#lisp - IRC Chatlog
Search
12:50:31
makomo
nevermind, steps (4) and (5) in the expansion of ,@,@ do differ, but the difference is a single backquote replaced with a quote
17:30:02
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.
17:30:57
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.
17:37:07
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.
17:43:11
jcowan
In what package does the elisp symbol live? Presumably CL-USER. Is that acceptable practice?
17:44:06
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.
17:49:40
jcowan
or if not put in CL-USER, the user must type (load ...) and (elisp:elisp). Uglier yet.
18:15:29
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.
18:15:55
pjb
jcowan: some repl let you define commands that are accessible whatever the current package. You could define such repl command to start elisp.
18:25:06
jcowan
So if use-package (or its defpackage equivalent) is discouraged because name pollution, which is recommended, importing or qualified symbols?
18:27:24
pjb
And neither is use-package really. See for example: https://github.com/informatimago/rc/blob/master/common.lisp#L437
18:28:51
pjb
But indeed, there may be some name collision, hence the carefully currated package list https://github.com/informatimago/rc/blob/master/common.lisp#L302
18:30:01
pjb
jcowan: the point is that the owner of the package gets to decide on the used packages.
18:37:38
jcowan
Yes, however, you take the risk of breaking your code if the used package is updated.
18:39:03
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.
18:42:48
pjb
jcowan: even if you don't use the package, if there's an update, there's potential bitrot.
18:42:50
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
18:45:37
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
18:46:08
fiddlerwoaroof
This is a bit painful in CL because there's no standard way to locally rename a package.
18:46:26
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.
18:47:11
fiddlerwoaroof
some libraries provide something like that: https://github.com/3b/package-local-nicknames
18:47:35
fiddlerwoaroof
Having an extensible reader is something I miss when I write Clojure or Elisp
18:50:06
fiddlerwoaroof
I remember one that used a reader macro to resolve the nicknames in a conforming manner
18:51:12
jcowan
The file https://github.com/3b/package-local-nicknames/blob/master/package-local-nicknames.lisp puzzles me: if loaded, it does nothing, because it consists of a single in-package form. What's it meant for?
18:56:37
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/
19:01:07
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).
19:01:54
void_pointer
But I am not sure how to get something running on the main thread after I create it.
19:09:02
pjb
void_pointer: you cannot do it with bordeaux-threads, but there are implementation specific ways to run stuff on the main thread.
19:09:32
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.
19:11:02
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
19:13:57
fiddlerwoaroof
Anyways, for the specific purpose of running something in the main thread, this works well: https://github.com/Shinmera/trivial-main-thread
20:15:46
jmercouris
this isn't exactly a Lisp question, but a question about how you would use a library
20:16:04
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?
20:16:30
jmercouris
I guess it isn't as simple as just removing JS blocks on the page, as those can be dynamically inserted
20:17:20
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
20:36:41
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
20:37:03
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)
20:40:18
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.
20:40:38
pjb
there are also html and xml parsers, but I'm not sure how complete and uptodate they are.
20:41:18
jmercouris
pjb: most ads these days are served via ajax queries, so it's not as simple as just removing the offending html
20:41:55
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
20:42:26
jmercouris
maybe it would be best to implement an AI, train a model and distribute that model
20:54:07
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.
20:57:25
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...
21:08:50
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?
21:20:44
aeth
in regex it's just (afaik) [Aa] or [Bb] anyway and is only hard when you want to extend it past that
21:21:20
jmercouris
aeth: yes, but would not be quicker to transform my strings to all lowercase instead off branching on every single check?
21:24:51
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
21:25:39
jmercouris
you know, I'm not carving things into a stone tablet here, I think I will go with lowercasing for now
21:26:14
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.
21:26:43
jmercouris
aeth: so what, you generate automata for every type of match you wish to do and store these models?
21:27:20
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.
21:28:19
jmercouris
interesting, I'm not doing the parsing for a DSL, just fuzzy matching user input against a list of candidate
21:29:04
jmercouris
though I could do something like that, I think I'll stick with the single line for now :P
21:34:16
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")
21:35:21
aeth
(position-if if you want to get the position and then look for whitespace separators to get the word that contains that character)
21:36:38
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)
21:40:08
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?
21:40:42
aeth
makomo: My most recent work in string matching was for parsing https://www.chessprogramming.org/UCI
21:42:46
aeth
makomo: Well, my plan is to eventually handle it in a macro just like anything else (XML, JSON, HTML, etc.)
21:47:20
aeth
makomo: (:isready) wouldn't require string matching. Seeing if the other side sent the response "readyok" would require string matching.
21:49:10
jmercouris
however, if you have 3 letters that you want to fuzzy match in a row, it will not work
21:52:19
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
21:52:43
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
21:59:07
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
22:01:14
aeth
The state machine DSL for writing the embedded DSL for handling someone else's external, string-based (and hopefully line-based) DSL
22:02:11
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
22:02:51
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
22:19:24
no-defun-allowed
mine is 10:00:00 since i like in gmt+10 but yes it should be midnight in UTC
22:19:35
aeth
for me: (multiple-value-list (decode-universal-time 0)) => (0 0 19 31 12 1899 6 NIL 5)
22:20:33
aeth
It should basically just be a reversal of ISO-8601's format until the time zone/DST/etc. stuff at the end.
22:21:23
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?
22:22:07
aeth
In fact, values probably uses values-list and the compiler probably optimizes values-list to not cons because of that.
22:23:54
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.
22:24:55
aeth
I mean, multiple return values probably cons at some point, but almost certainly past 4 and possibly past 10-20
22:25:51
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")
22:26:43
aeth
makomo: The line where it becomes inefficient is certainly after 4 in a reasonable implementation
22:27:52
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.
22:28:17
makomo
hm, reading that sentence a couple more times made it have more sense. guess it's a tricky formulation (for me at least)
22:29:51
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.
22:32:22
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
22:33:58
jcowan
Consider subtypep, which returns two values: what it believes and whether it is ignorant.
22:37:10
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)
22:46:54
jcowan
Scheme uses explicit continuations in that case, either just for failure or for failure and success, depending on the library.
22:47:14
jcowan
Lua just says "No nil as a key or value", though nil is not identified with any sort of empty container.
22:49:00
aeth
The thing about not using exceptions is that it's presumably cheaper to use hash-table as a duplicate-spotter.
22:53:42
aeth
easily one of the worst parts of the language's syntax, up there with trying to use lambda/FP
22:54:54
jmercouris
unless you wish to make your own exception type, in which case, the syntax and design leaves a lot to be desired
22:55:12
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.
22:55:27
aeth
Having space as a separator means you get kebab-case which is superior to underscore_case, too.
23:02:07
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
23:08:49
LdBeth
ACTION uploaded an image: 屏幕快照 2018-11-18 下午3.08.29.png (749KB) < https://matrix.org/_matrix/media/v1/download/matrix.org/DNiFMBZoIMSHcridgBBaWVxK >
23:09:27
makomo
also https://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/lang/lisp/code/syntax/infix/infix.cl
23:15:30
aeth
If you're porting software over, turning (x + y) / z into {{x + y} / z} is probably the best decision
23:16:05
aeth
The lack of popularity of an infix package means few people are porting things at the moment, which is bad
23:16:15
fiddlerwoaroof
ACTION the bigest mistake of infix languages is operator precedence, the second biggest mistake is mixed associativity
23:16:39
fiddlerwoaroof
If you're going to do infix, J/APL have it right: all one precedence, always right-associative.
23:18:25
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))
23:18:50
pjb
In practice, you'd just write the code to compute your spaceship position and propulsion in pure lisp anyways.
23:19:18
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.
23:23:09
fiddlerwoaroof
precedence is just confusion, especially once you expand beyond standard mathematical notation
23:25:06
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
23:26:08
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)
23:36:08
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"
23:41:20
jcowan
I like the Kotlin/Ada attitude: overload operators, fine; invent your own, not fine.
23:54:43
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'.
0:02:09
fiddlerwoaroof
The biggest pain-point of my objective-c FFI is that everything crashes when I accidentally send the wrong selector to an objective-c object