freenode/#lisp - IRC Chatlog
Search
16:17:13
jmercouris
we are using trivia in our project, and I really don't like the 'trivial-x' libraries or the "_" as OTHERWISE
16:30:49
jmercouris
galdor: A variable-pattern matches any value and binds the value to the variable. "_" and "otherwise" are special variable-patterns (a.k.a wildcard-pattern) which match any value but don't bind.
16:37:51
galdor
I personnally do not like OTHERWISE in general, looks too much like "we did not have a better solution so let's introduce a special symbol"
16:45:40
remexre
is there a standard macro for "set this value in this place if the place's current value is nil"?
16:55:20
Bike
(defmacro supercalifragilisticexpialidocious (place value) `(unless ,place (setf ,place ,value)))
17:26:00
phoe
eeeeeta: I could probably write a macro to programmatically generate 80% of German speech
17:36:20
asdf_asdf_asdf
'(1 2 3) collecting i => (1 2 3) '(1 2 3) by #'skip-arg-1 collecting i => (1 3).
17:37:18
beach
asdf_asdf_asdf: (loop for element in '(1 2 3) for i from 0 unless (= i 1) collect element)
17:38:22
HiRE
It seems to repeat whatever is after the collecting part in the list you're looping over
17:38:49
beach
It takes the argument and sticks it in a list, which is then returned at the end of the loop.
17:39:13
Xach
asdf_asdf_asdf: (loop for i in '(1 2 3 4 5) by (first-then #'cddr #'cdr) collect i) is one option
17:42:53
Xach
one possibility: (defun first-then (&rest funs) (let ((fun (pop funs))) (lambda (obj) (prog1 (funcall fun obj) (setf fun (or (pop funs) fun))))))
17:44:43
beach
How does that help if the argument to BY is evaluated only at the beginning of the loop?
17:45:50
beach
(first-then #'cddr #'cdr) is evaluated only once, at the beginning of the loop, so how can this implementation of it solve the problem that asdf_asdf_asdf has?
17:45:55
Bike
the returned closure has the effect of cddr the first time and cdr subsequent times. there is only one closure but it maintains its own state, so the loop doesn't need to evaluate the function more than once. makes sense to me.
17:49:27
eeeeeta
Xach: and, thankfully, Lisp is a language where you can get away with not knowing that sort of thing? :p
17:50:52
eeeeeta
ACTION suggests Xach turn in the source code of quicklisp instead and leave it at that :D
17:51:24
Xach
oh god, that would earn me a very poor grade - the fact that people find it useful counts for nothing
18:01:16
HiRE
ah yes, monads are quite simple. They are just monoids in the category of endofunctors
18:04:49
asdf_asdf_asdf
Thank You Beach, Xach. I want Xach's example. How pop n item from list using keyword "by"?
18:09:08
ck_
ACTION puts "by implementing the desired semantics" into the book of phrases for a rainy day
18:09:41
asdf_asdf_asdf
(loop for i in '(1 2 3 4 5) by (nth 3 :default-list) collect i) => '(1 2 3 5)
18:16:21
phoe
https://stackoverflow.com/questions/4093845/is-there-a-common-lisp-macro-for-popping-the-nth-element-from-a-list
18:21:57
asdf_asdf_asdf
phoe, thanks. I want example above, but with (nth x y), not always second item.
18:24:12
phoe
asdf_asdf_asdf: that implementation of CDNTH and (SETF CDNTH) in the above answer seems correct though
19:02:38
pjb
beach: I can't even find where in clhs the semantics of for in by and for on by is defined. It's present in 3 loop clauses; by is described for 6.1.2.1.1 The for-as-arithmetic subclause, but doesn't say if the form is evaluated once or each time (but the example are as if evaluated once).
19:12:30
Xach
asdf_asdf_asdf: you could use (first-then #'cdr #'cdr #'cdr #'cddr #'cddr)! but that is ugly.
19:31:02
no-defun-allowed
cl-base64 has a helper function to convert a base64 string into a string, but I believe it's broken for non-ASCII characters.
19:32:45
no-defun-allowed
So, to use either library with text, you will also need to use the Babel library to convert an array of octets to a string and back.
19:44:05
galdor
iirc base64 operates on octets, not on characters, so having a base64 encoding functions taking a string as parameter is surprising
19:44:39
Xach
galdor: i can understand it as a convenience to skip a step (as long as it works properly)
19:44:41
galdor
of course the library could automatically decode the string, but it requires an encoding parameter (and probably a system such as babel)
19:45:23
galdor
yep, but people are rarely aware of the encoding aspect, they are used to the "everything is utf-8" approach of many "modern" languages
19:46:25
galdor
I was thinking today it's too bad there is no standard mechanism to configure external formats
19:47:13
galdor
you always end up relying on babel because it's impossible to use :external-format on e.g. OPEN in a portable way
20:10:46
karlosz
anyone know a good reference for load-time-value and eval-when outside of the spec? there are some trickier examples that i've wondered if someone already compiled a list of ambiguous situations
20:12:49
Bike
if there is one i haven't seen it. the most substantial writing i remember on eval-when is fare's blog post saying it sucks. what tricks are you looking at?
20:22:35
karlosz
specifically i'm looking at what order toplevel clauses have to be evaluated with respect to load-time-value. i guess to give context i just added block compilation to sbcl and wondering whether im running afoul of certain ansi specified load-time vs compile time distinctions
20:23:36
Bike
in clhs load-time-value: "It is guaranteed that the evaluation of form will take place only once when the file is loaded, but the order of evaluation with respect to the evaluation of top level forms in the file is implementation-dependent."
20:24:17
karlosz
for example, on CMUCL block-compiling a struct (say, foo) and defun f () (load-time-value (make-foo)) gives a load time error in cmucl
20:24:29
pfdietz
" the order of evaluation with respect to the evaluation of top level forms in the file is implementation-dependent."
20:24:35
pjb
Now of course, if you write: (defparameter *foo* (load-time-value (+ 1 1)) You can assume that (+ 1 1) is evaluated before the load-time effects of defparameter *foo* can occur!
20:25:08
karlosz
and i'm pretty sure it's illegal but not sure what language in the spec specifically forbids that
20:32:35
karlosz
i mean i'm asking from the perspective of an implementor what will run me afoul of the spec i guess
20:33:23
Bike
the spec doesn't define an order, so you can't run afoul of it in this aspect. go where your heart calls
20:33:30
karlosz
especially because CMUCL was the only other implementation that abused compile time name resolution as aggressively as it did
21:50:09
HiRE
hmm, upon defining a class (defclass blankaccount () (customer-name balance)) and loading it into SLIME
21:50:15
pjb
vms14: right. I would have used OO. All those functions are just methods of the same generic function generate taking arguments php-node
21:53:37
pjb
When I type (make-instsance 'ba it completes alone, I just type TAB to finish it without typo.
21:55:18
pjb
Sorry, wrong file; go to: https://github.com/informatimago/lisp/blob/master/languages/linc/c-syntax.lisp#L202
21:56:27
pjb
So of course, you need to define classes for the syntactic elements: https://github.com/informatimago/lisp/blob/master/languages/linc/c-syntax.lisp#L173
21:57:06
pjb
And write a parser or macros to convert a sexp into a tree of instances of those classes.
21:58:23
pjb
(generate (parse '(defun foo (x y) (+ y x)))) -> <php?>number foo(x:number,y:number){return y+x;}</php> or whatever the php syntax is.
22:04:25
vms14
It seems much better way than how I'm doing, but I have to think now, I have no idea about where to start
22:05:37
pjb
You could start from the php grammar, if you want to implement a complete syntax. (This can be useful if you want to be able to parse php back to sexps).
22:06:25
pjb
Or you can just choose a sane subset. For example, for C or C++, it would be crazy to use the actual language grammar. Instead, you can define the grammar for a subset language as is used by human programers.
22:07:35
pjb
Similarly, the sexps syntax you will define can be able to express only a subset of the whole syntax (the subset you would use as a human programmer, or you need to generate), it doesn't necessarily have to cover the whole syntax.
22:09:09
pjb
You can also implement a php-parser and generate the sexp from it: php-source -> ast-objects -> sexp.
22:09:28
pjb
So you can parse php, get a sane sexp, edit or transform it automatically, and generate back the php.
22:09:57
vms14
would be nice, but also more complicated to write both, and I don't know if I'll need that
22:38:21
pjb
vms14: it's easy. In the case of lisp sexps, eg. if: (if <test> <then> [<else>]) -> (defclass lisp-if (lisp-expression) ((<test> :initarg :test :reader if-test) (<then> :initarg :then :reader if-then) (<else> :initarg :else :initform nil :reader if-else)))
22:39:06
pjb
vms14: then: (defmacro my-sexpified-language:if (<test> <then> &optional <else>) (make-instance 'lisp-if :test <test> :then <then> :else <else>))
22:40:24
pjb
Having classes has the big advantage that you can write generic functions dispatching on them, to do all kind of stuff on the programs thus represented. You can generate them in different languages, compile them to lisp or native code, pretty print them, transform them, etc.
22:41:03
White_Flame
I find it often yields smaller, more manageable code to do the same thing with plain data structures and manual functions
22:43:01
White_Flame
but yeah, it's still a tool in the toolbox. Just don't go all Java "OO = Object Obsessed" ;)
22:44:46
vms14
I don't see many advantadges using CLOS instead of just functions transpiling directly to what I want
22:45:53
pjb
vms14: the advantage is instead of having a procedural style, you can have a data driven style, where you have an internal representation of the program you want to generate. So you can manipulate it.
22:49:10
pjb
Instead of hardcoding stuff such as: (php-if (php-equal (php-var "a") (php-integer 0)) (php-function-call (php-function "foo") (php-var "b") (php-integer 42))), you can have some data |# (let ((php-code '(if (= a 0) (foo b 42)))) #| and process it: |# (generate (parse-php-sexp php-code)))
22:50:47
vms14
I had this (defun php-if (test &rest statements) (format nil "if(~a){~{~a~}}" test statements))
22:52:37
vms14
I'll think about writing an AST, because I'd like to learn more about compilers and metaprogramming
22:53:09
pjb
(case (first sexp) ((if) (format …)) ((= /= + - * / …) (format …)) (else #|mustbe funcall|# (format …)))
22:54:47
pjb
Or, you could (defgeneric (op &rest args) (:method ((op (eql if)) &optional then else) …) …)
22:58:11
vms14
the heredocs are because I wanted "" for the html and variable interpolation, but they make the code even uglier
23:22:55
HiRE
could someone provide me a few links of github repos or whatever with really well written modern CL code?
23:23:57
mason
HiRE: There are books worth reading. Here, for example: http://www.gigamonkeys.com/book/
23:24:40
HiRE
thanks Xach. Reason I ask is I'd like to take on a project to write a simple DNS server in CL for my own use.
23:28:01
HiRE
Xach, I'd love to take a look. One thing I was beginning to look at was even how to get started reading/writing packets in CL
23:28:37
pjb
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjU-KCOn4TnAhWRERQKHcS8Ad0QFjAAegQIAxAB&url=https%3A%2F%2Fgithub.com%2Ffjames86%2Fdragons&usg=AOvVaw15yBgmePwcAl1LunaxgUGy
23:28:38
pjb
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&cad=rja&uact=8&ved=2ahUKEwjU-KCOn4TnAhWRERQKHcS8Ad0QFjABegQIBxAB&url=https%3A%2F%2Fgithub.com%2Fhanshuebner%2Fans&usg=AOvVaw3Foqv4BPm4Ihcr1iFJB68t
23:28:50
HiRE
mason, that was my initial idea but I'd like to keep it pure CL if possible. I really like CL and FFI seems like a last ditch effort for me.
23:30:12
Xach
*.asd files are input to a program that can compile and load multiple files in the right order
23:31:41
Xach
for typical lisp development you start with a running intractive system and then teach it new things to do
23:32:23
HiRE
oh I see. So instead of having to load a buffer complete in say SLIME you use *.asd to help suggest it stuff?
23:33:15
Xach
HiRE: no. more like someone says "i have a library that does X" and you get that library, the system can use the *.asd file to load that library
23:33:44
Xach
and if that library needs a library that does Y, the *.asd files arranges to load that first too
23:34:32
Xach
quicklisp is a program that handles that error and downloads libraries to make them available to load
23:35:36
HiRE
oh sweet, yeah found the website. Seems like a package manager similar to NPM or something
23:42:06
Xach
i wrote that dns client because i had a web service that fetched images from the web, and i wanted things arranged so that things wouldn't get hung up by DNS or TCP timeouts
23:43:34
HiRE
Xach, I want to write one to help get around the DNS hijacking going on by my ISP lol.
23:44:43
Xach
maybe these things drift offtopic...we can discuss it via private messages if you're inclined.
23:45:19
Xach
i used to work at an ISP, and i know a little about networking, so it is interesting to me.
2:36:46
no-defun-allowed
A lot of things in Common Lisp can have documentation strings, so you probably should be reminded by them in other languages.
2:37:19
no-defun-allowed
To generate a document with all the documentation strings, Staple <https://github.com/Shinmera/staple> could be used.
2:41:33
White_Flame
what's the proper term for a symbol's value binding outside of any dynamic binding scopes? global value, toplevel value, etc?
3:20:37
pjb
"eternal" would be a dynamic (time) notion, but it implies some level of immutability, so it would do only for defconstant…
3:20:51
White_Flame
The length of time is a scope with a definite beginning and usually definite ending
3:21:17
White_Flame
"global" means many things, and the binding in question is the shared one that everybody sees without a local private override
3:21:34
no-defun-allowed
SBCL has a macro named DEFGLOBAL, so there is some precedent to calling it a global value.
3:22:31
pjb
White_Flame: defining a variable with defparameter or defvar doesn't propagate its definition in the past. Therefore it cannot be a "global temporal" scope.
3:23:37
White_Flame
the scope is the distinction between this one and private bindings that other threads of execution create
3:27:29
White_Flame
but I did default to "global" as well, just couldn't find any specific basis for it
3:28:01
HiRE
I think its just the names of the scope. The process is intuitive but "dynamic" goofs me up for some reason.
3:28:32
Bike
the clhs entry for defvar/defparameter calls it the "value cell" but that's kinda bad for other reasons
3:28:37
pjb
If you use the same word for the two orthogonal notion, you are bound to be confused, and to confuse everybody.
3:29:03
White_Flame
and does the "value cell" point to a private location when another dynamic binding is in effect?
3:36:59
White_Flame
" A dynamic variable can be referenced outside the dynamic extent of a form that binds it. Such a variable is sometimes called a ``global variable'' but is still in all respects just a dynamic variable whose binding happens to exist in the global environment rather than in some dynamic environment. "
3:44:22
White_Flame
well, specific to the comment I'm writing, "global value" would imply the value held in symbol's said "global binding", even if there are other dynamic bindings flying around
3:48:22
White_Flame
oh, and "global variable" is in the glossary as well: "global variable n. a dynamic variable or a constant variable."