freenode/lisp - IRC Chatlog
Search
6:16:44
Shinmera
fiddlerwoaroof: parse-namestring is hairy due to wild pathnames. So stuff like [], *, and others (implementation dependent!!) may need escaping.
6:20:08
Shinmera
implementing an analog to uiop's parse-native-namestring is on my todo for pathname-utils (and has been for years)
6:20:24
fiddlerwoaroof
I think it'd be useful to take the CLOSER-MOP approach with pathnames, really
6:21:10
fiddlerwoaroof
Specify the edge cases of the standard, and provide a package that implements that specification and a package that shadows the appropriate CL names
7:00:53
pjb
fiddlerwoaroof: or, having identified the edge cases, and specified them, patch the open source implementations so they behave the same on the same platform, and push so that commercial vendors implement the same.
7:01:22
pjb
fiddlerwoaroof: we have a strong position here given there are more free implementations than commercial ones.
7:01:52
pjb
fiddlerwoaroof: but remember: pathnames depend on the platform and the file systems that are mounted (depending on how the platform deals with them, check the mount options!)
7:07:10
pjb
fiddlerwoaroof: for logical-pathnames, see https://github.com/informatimago/check-pathname/blob/master/check-pathnames.lisp
7:09:30
pjb
fiddlerwoaroof: in general the problem is not so much that CL leaves things up to the implementations (there are a variety of platforms), but that there have not been defined a set of substandards specifying things for specific platforms. eg. how to deal with pathnames on MacOS, on Unix, on MS-DOS, on MS-Windows, on VMS, on Multics, etc.
7:13:26
Nilby
fiddlerwoaroof: The outputs of check-pathname for the various systems is very detailed answer to your original question.
7:17:46
Nilby
Now we just have to pipe the output from check-pathname on all systems to the automatic implementation fixer and we're nearly done.
7:20:13
Nilby
But my opinion is that the CL pathname stuff is written for a world which doesn't exist anymore, if it ever did, and there is a much simpler protocol that will cover all filesystems currently in use.
7:23:04
pjb
Nilby: granted. But AFAIR, only for soft specifications items. Eg. the specification mentions the customary case, but this customary case doesn't depend on the platform but also on the file system mounted, and platforms that can mount different file systems can (or could) deal with different customary case. In the same pathname! (ie, per component).
7:23:41
pjb
Nilby: but for hard features, such as the structure of paths in components, the hierarchic directory structure, etc, it's about good.
7:24:36
Alfr
I don't think pathnames support forks. (Not that it's a good idea to use them in the first place.)
7:24:38
pjb
Nilby: eg. the distinction between directory and file pathnames, even if it's not so clear-cut in POSIX pathnames, is still enforced in POSIX (eg. opendir vs open, or rmdir vs rm for files).
7:26:14
pjb
Well it's unrelated to pathnames. It'd be a parameter for OPEN. Since OPEN takes key arguments, it's already ready for an extension to specify what fork you want to open.
7:28:09
pjb
Alfr: the only place where it could be visible in pathnames, is when you map file systems with forks on unix (thru a mount), and they're translated in the path /mnt/fs-with-forks/example-file/data-fork when example-file is a file with fork, not a directory.
7:28:52
Alfr
Hm ... that'd be a solution, but conceptually I'd still think it rather belongs to pathnames.
7:29:30
pjb
Alfr: but in practice mounting Apple file systems on unix can use the apple-double or apple-triple format, which use alternate files with extensions: /mnt/apple-triple/example-file{.data,.rsrc,.info} /mnt/apple-double/example-file{,.rsrc}
7:30:11
pjb
This can be dealt with relatively easily with CL pathnames (the only thing to specify is how to deal with multiple dots in the file name.
7:32:41
pjb
But in reality, aren't files with forks exactly that: directories? Like "file packages" on NeXTstep/OpenStep/Cocoa/macOS/iOS ?
7:33:19
pjb
So again, but depending on the target filesystem and platform, this can be dealt with by CL pathname without difficulty.
7:37:20
Nilby
splittist: Yes, there's already a lot of CloudFS things, an they seem to usually use URLs or even more complicated things. I personally dread having URLs a file names. But there seems to be an opportunity for a more encompassing "resrouce locator"/filename library.
7:39:01
Nilby
pjbj: I'm pretty sure old MCL (and probably ccl now) could open resource forks, even on pre-unix MacOS.
7:44:27
Nilby
I think ms-windows is an example of how the more complexity you put into file names, the more problems you'll have.
7:44:48
Alfr
pjb, hm ... maybe name and type being :unspecific? I don't think there's anything in 19. prohibiting this.
7:47:47
flip214
At a first glance, I'd guess a subclass of PATHNAME that includes eg. a SCHEME (like :HTTPS) and a PORT (443) might be a reasonable approximation for many uses....
7:49:06
flip214
Though, as soon as LOAD can OPEN such beasts directly, we're back at square one (security-wise - see https://www.php.net/manual/en/wrappers.php)
7:55:43
pjb
flip214: granted, we have enough places to run code in lisp, not to add one in file names…
7:58:07
Nilby
Yes, internet file names seems quite scary and insecure. I would wish it would be something that the operating system could manage in a more secure way.
7:59:24
engblom
In the first chapter of Practical Common Lisp there is a simple database made out of lists. In it remove-if-not is used for quering the database. If you know there will always be only one occurence, it seems to be a bit wasteful to filter the whole list instead of just finding the first (and only) occurence. What could I use instead?
8:08:22
pjb
engblom: also, sometimes you will want position (position-if vs find-if), so that you may mutate the slot.
8:12:19
engblom
In my case I have a list of lists. Each sublist is a keyed list like this: (:ip x.x.x.x :port xx :user x :password x). Given an ip I need to find the rest of the settings.
8:15:20
engblom
jdz: I will getf for getting each of the settings out, but to find the right plist I still have to use find?
8:15:46
pjb
(let ((entry (find ip lol :key (lambda (entry) (getf entry :ip)) :test (function ip-equal-p)))) (getf entry :password))
8:20:09
engblom
jdz: I was thinking to use string=, but as you put there ip-equal-p I was just wondering if a such function actually already exists.
8:20:50
jdz
engblom: I've started writing an IP address library, but it lacks IPv6 support, and I'm undecided about many implementation aspects: https://github.com/jdz/ip.
8:22:12
jdz
engblom: You should define IP-EQUAL-P as (declaim (inline ip-equal-p)) (defun ip-equal-p (a b) (string= a b)) until you have something better.
8:22:27
no-defun-allowed
contrapunctus: I should admit to not having read the question, and I had assumed Shinmera typed find into the wrong buffer. Maybe "found it!" would have been a more direct response.
8:22:46
engblom
In this case I am sure the string= is enough thou, because the ip that is looked for is actually originally from the same plist, so there will never be cases where I need to handle comparing 192.168.1.1 to 192.168.001.001
8:27:46
flip214
well, IMO any IP comparision has to be done in the binary (or integer) representation, and should take optional netmasks anyway.
8:32:18
pjb
IP address comparison may be complexified by the fact that there exist 2 kinds of IP addresses (IPv4 and IPv6) and several representation variations. So it's better to abstract it away with a function.
8:33:15
pjb
engblom: In some programs too, domain names can be used interchangeably with IP addresses (DNS resolution being performed automatically).
8:33:51
pjb
But since a domain name may correspond to several addresses, the comparison is not a mere =, but rather a set intersection…
8:46:49
phoe
pjb: I think that DNS lookups and comparisons are a slightly different topic; munging IPs on their own is easy because they can be treated as ub8 vectors, and mapping between IPs and domain names already sounds like something that a DNS library would do
8:48:55
phoe
if a program accepts domain names, then I guess that it should call into a DNS library, which can then in turn accept actual domain names and bare IP addresses alike and do the necessary munging before passing the resultant IP addresses into the IP layer
9:42:31
pjb
phoe: granted. It depends on the layer of this data structure. I mentionned domain name, because at the user level (eg. configuration file) we will often accept domain names as well as IP addresses. But you may want to retain the domain name internally. The question is when you want the resolution to occur.
9:57:47
flip214
there are S3 client libraries for CL... has someone written or started a minimal S3 server that uses the filesystem as backend?
10:11:35
engblom
I wish to run an external command and as the command is generating lines after lines I want to use them, rather than waiting for the program to terminate before using the output. Could someone help me with this?
11:03:44
engblom
I have been also playing a bit with uiop:run-program. When called with :output :string it will return all the output, except for when the process is killed. Is it possible to get it to return everything (output + error messages) in a single string regardless of how the process ended?
11:05:49
engblom
And then when I run in a terminal "pkill ping" I do not get anything returned, instead I end up in the debugger
11:08:09
flip214
pjb: no, there are quite a few S3 servers - even open-source. but nothing that "just" uses an existing local filesystem.
11:08:58
phoe
engblom: (handler-bind ((uiop:subprocess-error (lambda (c) (invoke-restart (find-restart 'continue c))))) (uiop:run-program "ping 1.1.1.1" :force-shell t :output :string))
11:11:51
phoe
no-defun-allowed: it would, but I'm nitpickish in the code above and want to only select continue restarts that are visible for the condition
11:11:58
jackdaniel
(defmacro foolhardy (() &body body) `(handler-bind ((serious-condition #'continue)) ,@body))
11:14:43
flip214
oh, "On Error Resume Next" https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/on-error-statement
11:16:41
no-defun-allowed
I assume someone made a joke like (deftype silly-condition () '(and condition (not serious-condition)))
11:17:05
engblom
I am trying to understand what the conscencus is from the question I answered. How would you write the full line in this example?
11:22:20
scymtym
btw, one has to be careful with CONTINUE in SBCL since the restart for trying again to call an undefined function is called CONTINUE instead of RETRY for historic(?) reasons
11:24:48
sabra
jackdaniel: I have a question on ecl and octets (different behavior from ccl and sbcl)
11:31:26
no-defun-allowed
All of the padding of the new vector isn't initialized to anything. And COUNTING X INTO Y is a funny way of saying FROM Y FROM 0
11:32:05
jackdaniel
(sbcl and ccl take their time to initialize them when they know how to initialize a specific type)
11:33:53
no-defun-allowed
It can also be written much nicer with REPLACE: https://plaster.tymoon.eu/view/2406
11:34:55
no-defun-allowed
What should PAD-OCTET-ARRAY do if the input vector is longer than the given length? And it would not work on any array, only vectors.
11:39:41
no-defun-allowed
Sure, I had expected to write a longer else-form. But REPLACE returns its first argument, so it could even be written without a LET. One moment...
11:42:56
flip214
no-defun-allowed: now it _sometimes_ returns the original data, and sometimes a newly allocated copy... that might make a difference if the vector is mutated later on.
11:43:30
no-defun-allowed
Still I don't like to nest e.g. LET in IF. I don't know why, it just does not look nice to me.
11:44:02
flip214
and (- length (length vector)) could only be calculated once, and used with PLUSP or so in the IF
11:45:25
flip214
jackdaniel: (IF (MINUSP padding-entries) (COPY-SEQ input) (REPLACE ... :START1 padding-entries))
11:45:39
mfiano
What makes it jarring to me is the arguments are split up oddly. I would move the :start1 keyword arguments to a new line.
11:46:17
flip214
or perhaps better (PLUSP ...) so if (ZEROP padding-entries) the original (or a copy) is returned
11:46:43
no-defun-allowed
Okay, you all keep working on this slightly-better-than-before code I wrote, and I'll head to bed.
11:47:55
sabra
Shinmera: Just restarted that project. I need to look at the reporting objects and figure out how to output successful test results and failures to files.
11:48:50
Shinmera
if it's useful outside of the comparison project I could be convinced to add the functionality directly into it.
11:54:26
sabra
Someone wants to blame someone 6 months later. You can pull a file proving the data and test results worked at time A. So any failure now is from subsequent development.
11:55:59
Shinmera
Ah, I see. Hmm. Makes me wonder whether having metadata in git would be useful for that.
11:58:23
Shinmera
I suppose one could make a file report with all the detail that parachute captures being output to file.
12:00:06
sabra
I expect that to be relatively straight forward. I just want the success and failures to be separate files.
12:00:43
sabra
Of course, I just thought I could make an array and forgot to initialize it in public ;)
12:07:00
engblom
Is there any tool for tidying up lisp source code that does a bit more than just indention? With a bit more I mean splitting long lines and such.
12:08:04
Shinmera
engblom: Not to my knowledge. The syntax rules for forms are complicated and often even need user input, for indentation alone.
12:14:47
Nilby
Since I've been trying using the pretty-printer to indent code in an editor, without a level of tweaking that I haven't yet achived, as you may know, it's sometimes better than nothing, but usually not.
12:18:15
jackdaniel
once when I've used the pretty printer it complained about a syntax error, so I've called it a petty printer
12:19:33
sabra
I think there are now 29 testing frameworks in quicklisp, not counting 2am or various helper libraries.
12:21:21
jackdaniel
ACTION has a local wrapper around 5am written in clim- the directory has a proud name 7am ;) but I'm not going to spoil you by publishing it!
12:25:23
flip214
jackdaniel: so there'll be a few 7am libraries, all with incompatible extensions...
12:31:26
flip214
jackdaniel: well, how are you gonna stop me from doing my own 7am? (1+ (1+ 5am)), a.k.a. 5am++
12:31:59
pjb
engblom: (let ((*print-right-margin* 72)) (loop for sexp = (read source nil source) until (eq sexp source) do (pprint sexp))) ;-) but you lose comments, and some () will be printed as NIL.
12:35:46
pjb
sabra: perhaps you want (<= size length) instead of (= size length) ; depends on whether you want an error on (> (length vector) size) or not.
12:39:39
pjb
sabra: errors such as Array index -8 out of bounds for #(0 … 0) . may be cryptic. Better provide a condition with an error message such: vector too long for pad-octet-vector.
13:16:46
pyc
I am going to form a large string by appending to an existing string iteratively inside a loop. Is this a good approach from performance perspective? In other languages, I normally append to a StringBuffer or a list and then convert it to a string in the end. Do we need to do something similar in CL too?
13:17:33
flip214
pyc: you can use (with-output-to-string () ...) and allocate a big(-enough) string beforehand.
13:17:38
pjb
pyc: not really. You can use with-output-to-string that'd be the equivalent of a StringBuffer.
13:18:19
pjb
pyc: an alterlative, is to manage it yourself: collect your string in a list, then compute the total length, and copy them in a newly allocated string of the right size.
13:18:46
pyc
Shinmera, flip214, pjb: Thanks! Is with-output-to-string definitely a better approach than concatenating iteratively to a string or it does not matter whether I concatenate or use with-output-to-string?
13:21:58
pjb
pyc: note that it is dependent on the implementation too. You may want to benchmark and see what works better for your (application cl-implementation) pair.
13:23:39
pjb
pyc: notably, asymptotic behavior doesn't say anything about the constants, and that's just expectation we have on implementations. Sometimes we may have surprises… (for example, on an unrelated note, reader macros are put in a sequential list in ccl, so when you have a lot of them (say on each unicode character) it becomes very slow to read stuff).
13:24:33
pjb
pyc: have a look at: https://github.com/informatimago/lisp/blob/master/common-lisp/cesarum/string.lisp#L159
13:36:44
pjb
(dolist (x '(1 2 3 4 5 6)) (block continue (if (oddp x) (return-from continue)) (prin1 x))) #| 246 --> nil |#
13:36:53
Colleen
Bike: drmeister said 1 hour, 9 minutes ago: I'm getting a cascade of errors when generating backtrace...
13:36:53
Colleen
Bike: drmeister said 59 minutes, 50 seconds ago: Are you making an assumption about what the output from backtrace_symbols looks like?
13:37:15
heisig
pyc: The body of dolist is like a tagbody, so you can simply introduce labels and go to them.
13:37:45
pjb
(dolist (x '(1 2 3 4 5 6)) (if (oddp x) (go continue)) (prin1 x) continue) #| 246 --> nil |#
14:46:34
engblom
I made a tool for tidying lisp files based upon (pprint (read)). I run it on itself and here is the result: https://pastebin.com/16QCHEw0
14:48:58
phoe
also, (loop ... do (pprint form) (terpri)) - unnecessary progn, and an explicit newline operator
14:49:16
theseb
In SICP, authors implement eval and make a point of saying to actually INVOKE functions, you need a special form called "apply". However, in Paul Graham's "Roots of Lisp" which I've always liked he does NOT make a point of saying you need a special extra operator like apply to implement eval...why?
14:49:19
phoe
also (read in nil) is going to be buggy if the file contains a literal () (which is possible)
14:50:51
heisig
engblom: You should use some library for handling command line options, at least once your programs grow larger. Something like https://github.com/didierverna/clon
14:51:20
phoe
theseb: likely because the syntax of RoL's lisp allows for ((lambda ...) ...) style which is an implicit APPLY
14:52:02
heisig
engblom: Apart from that and the use of SETQ, that's a neat little program. Welcome to Lisp, try not to get too addicted :)
14:54:49
Bike
i think mostly roots of lisp is a sloppy (or, more charitably, simplified) article that shouldn't be relied on for details
14:54:52
phoe
and, if a list '((lambda ...) ...) is your function call, then evaling it is the implicit APPLY I meant
14:56:14
theseb
Bike: i suspect RoL made a lot if Lisp fans...I've personally been more fascinated with the RoL than I'd care to admit
14:56:15
pjb
Bike: "article" you're generous. Nothing like that. It's a mere "memo", two dactylographed pages to let know fellow searchers of the AI Lab what John was up to. Namely, AIM-8: http://informatimago.com/develop/lisp/com/informatimago/small-cl-pgms/aim-8/index.html
14:56:46
jcowan
You can write aa simple APPLY-EVAL pair that constitute a classical Lisp interpreter. Needless to say, few Lisps around today actually provide this.
14:56:47
phoe
eval. accepts the form to be evaluated and the environment - do we have access to it inside RoL itself?
14:57:59
phoe
and since it's just Lisp data, I guess we can make a special form that returns the current environment that can then be passed to eval. again
14:58:38
engblom
I did not go for the libary for parsing arguments at this point, as this tool will probably never grow. I fixed the rest: https://pastebin.com/TuZrmfn2
15:01:28
phoe
also SYNTAX-ERROR is a slight misnomer because it does not really signal a CL error; maybe name it PRINT-HELP-DIALOG instead?
15:01:46
phoe
theseb: actually when you have stuff like ((1 . 2) . 3) I'd be scared to use first/rest on it
15:02:49
pjb
theseb: APPLY is not a special operator, it's a primitive function. FUNCALL can be implemented calling APPLY but the reverse cannot be.
15:03:47
pjb
engblom: and yes, since they are global variables, you don't want to mess with the code in the other threads, or to mutate them for the rest of the REPL session. So use LET.
15:03:58
theseb
pjb: wow....i was assuming primitive function == special form == special operator....didn't know people here distinguished between those terms
15:06:44
phoe
but, yeah, the fact that some CL operators are functions does not mean that they can be expressed in terms of anything else
15:06:49
pjb
theseb: (if (= a b) 'yep 'nope) is a special form. IF is the special operator. APPLY is a "primitive" function in that it cannot be implemented in lisp without using metalinguistic abstraction. In the case of Common Lisp, all the functions in CL can be open-coded, which means they could be considered like special operators in a way. But special operators are a more specific set of 37 operators in CL. Note that macros in CL ca
15:06:49
pjb
implemented as special operators technically, but the implementation still has to provide an equivalent macro for users of MACROEXPAND.
15:08:06
Bike
"special operator" means an operator with special evaluation semantics. apply has the same evaluation semantics as any other function: in (apply a b), a and b are forms to be evaluated. so it's not special.
15:08:06
pjb
in any case, that doesn't mean that you cannot implement everything in CL. It's just that there's one level of metalinguistic abstraction required (ie. a compiler or an interpreter).
15:20:46
_death
(let ((c 0)) (do-external-symbols (sym "CL") (when (special-operator-p sym) (incf c))) c) => 25
15:21:01
pjb
(let ((n 0)) (do-symbols (s "CL" n) (when (special-operator-p s) (incf n)))) #| --> 25 |#
16:56:40
Josh_2
I'm sat here thinking I wonder if there is a destructuring-plist, turns out you can just destructure a plist using &key ...
17:01:40
Bike
http://ix.io/3cvy here is how i would do a roots of lisp thing. makes the difference between a special operator and built in function clearer. would be more involved to make it self hosting, though