freenode/#lisp - IRC Chatlog
Search
11:37:49
xificurC
shangul: anyway, foo(1, 2); becomes (foo 1 2) in CL. 1 + 2 becomes (+ 1 2). if (...) {...} {...} becomes (if test then else). It's less effort
11:39:38
xificurC
shangul: you just need to get a well tweaked editor and parens won't be a problem. If you're using stock emacs have a look at paredit (or lispy if you feel more brave0
11:40:49
xificurC
shangul: yes. Paredit is for PAREntheses EDITing. Lispy is a bit more than just that
11:40:55
jackdaniel
I wouldn't concern myself with editor enchancements for now, just try indent lines by myself. but that's just my opinion
11:42:45
xificurC
while I agree there's also a cost involved when one has to manually match the closing braces and see compilation errors when one misses one. Not sure which option takes more effort
11:44:31
jackdaniel
compilator errors require correction which improves language understanding, but as I said, it is just an opinion of mine
11:44:40
xificurC
jackdaniel: "global bindings should be put in earmuffs, like that: *variale* ... it is a convention followed by all CL programmers" <- I was stunned when reading Let Over Lambda :)
11:46:05
shangul
jackdaniel, about that convention, is that just a convention followed by programmers or those "earmuffs" make a variable global?
11:47:15
jackdaniel
*earmuffed-variables* stand out, and it is good, because global bindings are (usually, I'm ignoring sb-ext:defglobal for now) dynamic
11:47:41
jackdaniel
dynamic bindings are very useful, but may be quite fishy when it comes to understanding the code
11:48:26
xificurC
jackdaniel: "Since this convention is almost like having another namespace for dynamic variables, diminishing their duality with lexical variables, this book does not follow it exactly."
11:49:36
jackdaniel
shangul: looks good. I think xificurC had also remark about if (which was valid), except that nothing wrong with the code as far as I can see
11:50:00
jackdaniel
xificurC: interesting. I find having them in the same namespace being one of CL's flaws on the other hand
11:52:57
shangul
a problem: emacs doesn't know how to indent input-string when I want to put in on another line
12:12:17
Myon
I got stuck trying to add a testsuite run in the pgloader build because it has too many tests with different requirements
12:24:08
flip214
Last call: does anyone know about a high-level interface to Ethereum (smart contracts) before I write my own?
12:31:32
flip214
shrdlu68: I don't plan to - just want to use the Ethereum rest API (via the :ethi library) to call smart contracts.
13:25:55
Fare
flip214, I'm developing a very high level interface to Ethereum smart contracts... in OCaml and Coq :-(
14:20:59
Bike
On sbcl, (let ((closures (loop for x below 2 collect (let ((y x)) (lambda () y))))) (setf (documentation (first closures) t) "test") (values (eq (first closures) (second closures)) (documentation (second closures) t))) => NIL, "test"
14:21:17
Bike
in other words the docstring is shared betwen distinct closures with the same underlying function
14:23:07
Ukari
I found that use let makes code nesting, and (let ((x)) (setf x)) would change x again and again
14:25:35
Bike
Me too, but spooky action at a distance is spooky enough that I'm wondering if anyone disagrees
14:28:26
beach
Ukari: That might be possible. But I for one do not understand what it is that you want.
14:29:21
beach
Ukari: Yes, but "is there been exist a function lexical scope stuff which looks like let or defvar?" makes no sense to me.
14:30:23
beach
And LET and DEFVAR don't look anything alike, so I don't know what they have in common.
14:32:52
schweers
Are named function (e.g. created with defun) scoped in the same way as special variables? I’ve always been a little confused about this issue. background: I want to rebind a function for a dynamic extent, and am not sure how to do this in a safe and portable way.
14:34:18
Bike
schweers: flet and labels have lexical scope. there is no operator for dynamic function binding.
14:35:27
beach
Ukari: (let* ((target (lambda*...)) (target1 (funcall target)) (target2 (funcall (iter-next target1)))) (assert...))
14:37:07
beach
asarch: I am a little troubled by your recent questions. It seems like you are collecting random keywords from the specifications of other programming languages, and asking whether those features exist in Common Lisp? What is the point of this exercise?
14:37:38
xificurC
Ukari: there's no such thing. If you really, really want it you can write a macro. You should get used to the nesting though. And if you feel like code is nesting too much then you are already in trouble
14:38:09
beach
Ukari: Can you tell me what it is that you dislike about my solution to your problem?
14:38:19
asarch
Well, the next programming language I would like to learn is Smalltalk. And while I am reading its entry in Wikipedia, I found that in ST "42 factorial" is the way to send messages to the objects
14:40:49
asarch
Common Lisp is a beautiful programming language, sadly I'm infected with C++ "techniques" which I need to forget in order to get the most of Common Lisp
14:41:05
beach
Ukari: If you really care about such things, I recommend you use a different programming language, because that is totally not how Common Lisp works. A form that introduces bindings also introduces scope.
14:42:40
beach
asarch: I totally understand. But the way to go about your quest is to figure out what you want done and ask how it is done in Common Lisp. Not taking some random keyword (virtual functions, for example) and asking whether Common Lisp has the same feature, which may or may not make sense in Common Lisp.
14:44:27
xificurC
beach: and that's totally not how the human mind works. One always tries to compare things to something else they know to be similar. The problem is CL only *seems* similar
14:48:22
Ukari
xificurC, forget unknown cl syntax and use the lambda way, for example use (funcall (lambda (x) (print x)) 1) instead of (let ((x 1)) (print x))
14:50:10
asarch
Conrad Barski in his book says that "The power at your fingertips when writing Lisp code is what makes it so different. Once you “get” Lisp, you’ll be forever changed as a programmer. Even if you end up never writing Lisp code again for the rest of your life, learning Lisp will fundamentally change you as a coder."
14:55:04
edgar-rft
asarch: Many ideas and concepts in lisp are pretty much different than in other programming languages. So even if you later never write lisp code, learning lisp teaches you to see more different perspectives to solve problems, raising chances to get things done. I think that's what C. Barsky means.
14:57:18
schweers
so if I want something like dynamic extent, I’ll have to do it myself? I’ve seen examples which use SETF on SYMBOL-FUNCTION in conjuction with UNWIND-PROTECT. Seemed reasonable, but wasn’t sure if was safe, especially in the presence of threads.
14:57:22
Bike
If you need to have a dynamically bound function you could do like (defun foo (&rest args) (apply *foo* args)), and then do whatever with *foo*
14:58:44
schweers
but it bothers me a little to do it like that, as it means I can’t do it for existing functions without editing every caller
15:01:07
Bike
dynamically binding functions is pretty unusual, by the way. think hard before you do it.
15:04:08
schweers
asarch: learning and “getting” lisp not only changes you as a programmer, it spoils your character.
15:06:57
Bike
contextl does stuff like that and it's kind of neat, but i don't entirely get it either.
15:06:58
Ukari
oh what happend, I use the sbcl context exist since yesterday, (lambda* (x) (print x) (yield (+ x 1))) (funcall * 5) (funcall *), then it prints 2. after i restart sbcl, the same code prints 5
15:12:12
schweers
Bike: I know it is, and I guess it’s normally unusual for good reason. I’m thinking about a testing context.
15:13:07
schweers
I’m not going to run around doing this immediately, but my idea was to find out whether this is useful in order to mock/stub/fake/whatever a function during testing.
15:13:38
schweers
but the more I think of it, the less happy I am as I see more problems with the approach
15:19:13
phoe
use SETF for altering already existing bindings, or, if you are not sure if the binding has been created before, DEFPARAMETER will *always* set the new value.
15:23:06
Ukari
(defvar x 2) (lambda (x) (lambda () (print x))) , and then (funcall * 5) (funcall *). why it print 2 ?
15:25:11
phoe
you should be able to name your lambda parameters in any way you'd like. (except for constants, that's an error.)
15:25:37
Fare
flip214, see https://bbt.legi.cash/ for my slides at LambdaConf 2018 (videos to come in the next few months).
15:26:34
Fare
flip214, our code is using a lot of modules and functors, so in CL you might want to translate that to Interface passing style.
15:29:41
Ukari
would it be a good idea to make lamdba and defvar check their parameter's name to enforce name style?
15:36:08
buffergn0me
That would be really annoying. Especially when porting code from other languages
15:43:28
beach
Ukari: Lambda is perfectly able to use special variables as parameters. What that means is that the special variable gets bound upon entry to the function and unbound upon exit. For example ((lambda (*print-base*) (print 234)) 2)
15:44:52
beach
buffergn0me: It would be especially annoying because a conventionally named special variable could then not be used in a lambda expression.
15:46:23
Bike
It's not a bug. x is a special variable, and once the outer function has returned its binding of x is extinguished, so the inner function uses the global value.
15:48:36
phoe
in SBCL at least, (let ((*foo* 42)) ...) will emit a warning if *foo* is not declared special
15:49:37
beach
phoe: I think Ukari is suggesting that LAMBDA check that there are no earmuffs in the parameters.
15:51:14
phoe
; caught STYLE-WARNING: using the lexical binding of the symbol (COMMON-LISP-USER::*FOO*), not the dynamic binding, even though the name follows the usual naming convention (names like *FOO*) for special variables
15:55:04
Ukari
in (lambda (x) (lambda () (print x))) or (let ((x 5)) (lambda () (print x))), when you funcall the outside lambda or get the let result, it returns you a FUNCTION
15:55:47
phoe
except X is special, so its value is taken from the dynamic environment and not the lexical one.
15:56:46
Ukari
In a CLOSURE, a free variable in bind to its lexcial context, so use (defvar) won't change it.
15:57:09
phoe
it returns a function in my case, and it won't matter anyway if a FUNCTION or a CLOSURE is returned
16:00:05
phoe
TEST still works as it did, the variable used inside it was lexical and does not suddenly become dynamic because of a later DEFVAR.
16:04:27
pierpal
Life must be very exciting for people learning programming languages by experiments
16:08:35
Ukari
why (funcall (lambda () (lambda () (print "foo")))) returns a FUNCTION, it seems should return a CLOSURE
16:08:48
makomo
i think you accidentally had X proclaimed special when you were evaluating that lambda
16:15:34
Ukari
my mistake, what (funcall (lambda (x) (lambda () (print x)))) returns might be a CLOSURE or FUNCTION, it determines by the context
16:16:41
makomo
so yes, it depends on the state of the lisp image, i.e. the specialness of the symbols involved
16:17:03
phoe
depending on whether your symbols are proclaimed special, your variables may be lexical or dynamic
16:32:51
phoe
I don't have the time or patience to register at https://sourceforge.net/p/clisp/bugs/ now
16:44:41
Ukari
makomo, when (funcall *builder* 10) runs, the (funcall *builder* 10)'s result might be a CLOSURE or a FUNCTION, that determined by the context. Since you use (defvar x), x was treated as a global dynamic scope variable so (funcall *builder* 10) returns FUNCTION
17:15:37
makomo
LOAD-ing this lisp file gives 10 10 200, but compiling it and then loading the FASL gives an error: "X is unbound"
17:16:33
jackdaniel
dlowe: you mean in documentation? how is this relevant to green threads? you may implement serve-event without gt (but I wouldn't be suprised if cmucl has them anyway)
17:19:09
jackdaniel
makomo: when you load a file, it is processed sequentially, toplevel form after toplevel form
17:20:06
jackdaniel
but don't think too much about how it (eval-when) works in detail unless you have some time and want a good puzzle
17:47:55
makomo
jackdaniel: i think i understand how EVAL-WHEN works because i've studied it a couple of times
17:48:06
makomo
jackdaniel: what i don't understand is what exactly is different between these two examples
17:50:29
makomo
hmm, does this have to do with the fact that the different stages of processing can be interleaved?
17:57:59
gendl
Hi, is anyone experienced with cl-json? I'm trying to encode a nested plist: (json:encode-json-plist (list :xaxis (list :visible nil)))
17:59:02
gendl
so it looks like it only converts the outer plist into a JSON plist-type thingie. The inner one just becomes a JSON sequence or whatever TF they call it
18:00:06
gendl
I have a feeling I have to call json:encode-json-plist recursively somehow on the inner plists, but I'm not sure how I would make the result come out properly nested..
18:00:55
Bike
and encode-json is documented to make an array for a list, unless you do the explicit encoder
18:02:09
gendl
Oh yes, I see some hints about the explicit encoder here: https://www.cs.northwestern.edu/academics/courses/325/readings/web-tips.php
18:13:09
gendl
Indeed - the docs for method encode-json talk about the guessing-encoder and explicit-encoder. And it looks like using :object as (car S) is the same as using :plist. Anyway thanks for the pointers, this will let me do what I need.
19:00:47
makomo
Bike: am i not supposed to COMPILE-FILE some file and then load it later on within a fresh image?
19:37:39
akkad
ACTION put all the slack/confluence/jira/github interface commands into a CL cli. no longer have to use a browser.</lispy>
19:56:10
makomo
phoe: to conclude the whole discussion from today, the "error" with http://rextester.com/CQFO22548 was to assume that *builder* will refer to a compiled-function, right?
19:57:02
makomo
adding a (compile nil (lambda ...)) does fix the "issue", i.e. the difference in results when the file is loaded vs. when it's compiled and then loaded (using clisp of course, sbcl gives the same results in both cases)
20:09:49
Bike
by other stuff i meant like, keeping an inline definition around, informing the compiler to avoid warnings, blabla
20:10:17
cgay
I'm finding that slime-edit-definition doesn't always work when I already have the target file open in my buffer. i.e., it works the first time, when it has to open the file, but then later if I M-. the same symbol it jumps to the wrong place in the buffer.
20:16:50
knobo
cgay: I think you have to recompile the whole file if you edit parts of it (adding or removing lines).
20:20:14
makomo
phoe: i still don't understand why the value returned by *lambda1* is changed after defvar-ing x though
20:21:00
makomo
phoe: it makes sense that, since *builder* is an interpreted function, it might inspect x every time to check whether it's special or not and either return a closure or a function
20:21:31
Bike
oh, well, yes. the interpreter presumably looks up whether the symbol is special at runtime.
20:21:58
makomo
Bike: this is the original example, not the one i linked to you (when i forgot to recompile the file)
20:22:43
makomo
it makes sense that the result of *builder* might be different depending on the specialness of x
20:23:33
makomo
dlowe: when learning something, one of the worst things you can do is say "meh whatever" and drop it, imo
20:24:02
dlowe
makomo: sometimes the experts will say "you're wasting your time on this trivial detail," and sometimes they're right.
20:24:29
dlowe
makomo: the code is open source and no one here knows the answers to the exacting detail you require
20:25:00
dlowe
so I think your best bet (without any irony) is to actually dive into the compiler code for each to see why there's a difference
20:25:51
Bike
evaluating a (lambda ...) might literally consist of just copying the body into an interpreted function object, and not examining it in any way.
20:25:58
makomo
i guess it makes sense, but i thought that since in the first case a closure is returned, that it would just be "hardcoded" within the function
20:26:11
makomo
but i guess a better model would be that it would evaluate X in its captured lexical environment
20:27:55
Bike
it is sort of an ambiguous case though. i can imagine interpreters that would treat it like a lexical binding.
20:28:46
makomo
mhm. so in the end it's implementation defined? and with compiled functions it is guaranteed that X will be considered either a lexical or a dynamic binding, depending on the specialness of the symbol X, as per the clause you linked, right?
20:31:21
White_Flame
SBCL does at least give warnings when you redefine some assumption that it baked in previously
20:36:21
White_Flame
the compiler does not appear to be mandated to bake in compile-time knowledge of specialness
20:37:48
White_Flame
ah, but in 3.2.2.3: "Special proclamations for dynamic variables must be made in the compilation environment. Any binding for which there is no special declaration or proclamation in the compilation environment is treated by the compiler as a lexical binding."
20:44:19
makomo
does (compile nil (lambda (x) (lambda () x))) ensure that the functions returned by the inner lambda will be compiled too?
20:49:23
makomo
"The consequences are undefined if the lexical environment surrounding the function to be compiled contains any bindings other than those for macros, symbol macros, or declarations."
21:52:11
knobo
Would a function created by def be garbage collected (defmacro def () (let ((n (gensym))) `(defun ,n () (format nil "t"))))
21:53:55
phoe
so it will stay around, even if you have no real means of accessing that function after it's defined.
21:58:16
phoe
Like, if a symbol is no longer accessible, then all functions and variables named after that symbol may be collected.
21:58:47
phoe
But I have no idea if such a thing happens. You could try checking it out yourself by defining a finalizer on the created function object and see if it ever gets triggered.