freenode/#lisp - IRC Chatlog
Search
4:00:56
White_Flame
mister_m: if your inferior-lisp gets dropped into ldb, you probably blew the heap, or the stack twice
4:03:35
dieggsy
asarch: melpa has been odd recently. I don't use it as my package repo but I search their website sometimes and it's been extremely slow
5:09:30
White_Flame
the lack of interchangeability of different communications stream styles is a general problem, across many domains
5:11:52
White_Flame
I don't know enough for it to be a definite "no", but such situations hit me too often between other stream interfaces
6:12:26
beach
pbaille: #lisp is not really for trivial questions, but such questions are tolerated, especially if traffic is low. If trivial questions become too annoying, you may get redirected to #clschool which is meant for such questions.
6:13:21
beach
pbaille: On the other hand, some newbie questions are not trivial, and the answers to them are often worth repeating here, like for instance the semantics of function calls and argument passing.
6:18:25
pyc
Does https://plaster.tymoon.eu/edit not work anymore? I tried it many times but it does not return me a link I can share. The input just disappears after posting my snippet.
6:20:23
pbaille
I was curious about code equivalence those days. Is there any known works around that. for instance determining the equivalence of those 4 expressions:
6:21:05
beach
pbaille: That would be an undecidable problem in general, so I think you are out of luck.
6:21:07
pbaille
sorry I'm discovering IRC... the four expressions posted where intended to be after my question. all my apologies.
6:21:11
no-defun-allowed
You may reduce the first three to the fourth using substitution in this case, but generally equivalence is equivalent to the halting problem.
6:21:21
pyc
no-defun-allowed: thanks! I can see your post. I wonder why it does not work for me. When I click post, it goes back to the https://plaster.tymoon.eu/edit and the input disappears. I don't get any link I can share.
6:22:04
pyc
no-defun-allowed: are you logged into https://plaster.tymoon.eu/edit ? or did you use it without logging in? I am not logged in.
6:22:19
flip214
pbaille: you could try to use macro expansion to rewrite all expressions to a minimal subset - eg. replace LET by a LAMBDA form.
6:22:56
flip214
but then you'd still need quite a few manually defined rules - eg. the order of variables in LET can be different.
6:24:12
flip214
and you might need an expression simplifier to see that (* (- a b) (+ a b)) equals (- (* a a) (* b b)) and so on.
6:24:37
flip214
so you can arbitrarily far, depending on how much time/effort you're willing to spend...
6:24:52
pbaille
but maybe bindings can be ordered using kind of an hash of the value they are bind to
6:25:07
flip214
OTOH, I can also see an alternative way -- compile the expressions, and try to prove that the machine code gives identical results.
6:25:27
Nilby
As you may know, there are many undecidable in general problems which are quite worthwile and solvable in specific.
6:25:31
flip214
Ie. like decompiling back to C or so... that would get rid of many small differences in the sources
6:25:34
moon-child
that throws away information. It is likely to be harder to prove interesting facts about machine code than about lisp code
6:26:33
flip214
moon-child: not necessarily... at least that's a well-defined set of basic instructions.
6:26:34
moon-child
those 'small differences' are things you need to be able to handle anyway. Many of them will result from compiler optimizations, the sorts of analysis underlying which you will need to replicate if you would like to automatically prove things about code
6:27:51
Nilby
pbaille: You're welcome. I think too many time people are discorged from finding useful solutions to undecidable in general problems.
6:28:57
pyc
got some clue about the pastebin issue. When I submit in the browser's network tab I see a POST being made to this URL: https://plaster.tymoon.eu/?error=You%20did%20not%20enter%20the%20captcha%20correctly.
6:31:59
pbaille
flip214: thank you for your suggestions. I've worked on those kind of things a few months ago (in clojure), I will try discuss it with you guys a bit later. thank you
6:40:06
beach
saganman: It just barely started. I need to download some screen-recording program to my new desktop computer and record my ELS talk. What about you?
7:17:02
pyc
Is this a good coding style: https://pastebin.ubuntu.com/p/Y7Y35fwjRW/ ? What I am doing here is computing everything in (let* ...) and returning what I need as a separate expression in the end. Does it look odd to experienced Lisp programmers?
7:22:06
jdz
And I think the function should accept a string, and reading file contents into a string should be done somewhere up the call chain.
7:22:17
pyc
jdz: in that case this code will fail with error. I can definitely improve the error handling. however is my style of doing all computation in (let* ...) and then returning just that one thing I need to return in the end proper coding style? Coming from other languages, it felt odd to me, so wanted the opinion of experienced programmers here.
7:23:09
beach
pyc: Again, you can probably leave out the last binding, because the name of the function should be enough to tell what the result of it would be.
7:23:17
jdz
You could make this into a generic function, with methods on specializing on STRING and PATHNAME.
7:25:11
pyc
jdz: yes, I was considering that alternative too. Certainly the whole thing can be written without let binding. so can I assume that experienced Lisp programmers avoid LET binding whenever possible? Or is it just another alternative and both alternatives (LET or no LET) are equally valid and good?
7:29:08
moon-child
in this case, though, for the purposes of efficiency I might keep track of the position of the {{{, to avoid needing to look over so much of the string for the }}}
7:30:33
pyc
moon-child: great point! in fact I do need to ensure that I search for }}} *after* {{{ and ignore any }}} before {{{. so I do need to keep track of its position.
7:31:19
jdz
pyc: I do not favor _fewer_ bindings, but introducing them unnecessarily just create more clutter and more work for brain.
7:33:03
moon-child
naming things is difficult. The wrong name is worse than no name at all; the former may mislead, where the latter is self-evident in its use
7:33:17
jdz
flip214: Sure. But that's the thing about commenting—there's no point commenting trivial code.
7:34:02
moon-child
(self-evidence may be insufficient when the thing being evinced is sufficiently complex. But.)
7:34:11
flip214
jdz: "trivial" depends on the consumer ;) and a few weeks later the author herself might be glad about one more name
7:40:33
Nilby
When coding in a forth-like language I frequently had to comment almost every line with the presumed state of the stack.
7:42:18
pyc
an off-topic question. Can forth operators act on arbitrary number of arguments. For example, Lisp can do (+ 1 2 3) where + takes any number of arguments. It is of course possible because we can delimit the call with ). Is such a thing possible in Forth?
7:44:58
pyc
Nilby: how would the operator know how many arguments the programmer wants to add for example when there are no delimiters to specify that?
7:45:09
Nilby
A common thing with varibale arguments is to have a count or a fencepost on the arglist.
7:45:32
pyc
Nilby: say, I make a Forth operator op, and I write 1 2 3 4 5 op. How would it know if I want op to consume 2 arguments or 3 arguments or 4 arguments?
7:46:00
pyc
Nilby: by fencepost, you mean, some sort of special value I keep on the stack to mark the end of list of arguments?
7:46:59
pyc
Nilby: okay, understood. so the responsibility for that falls on the programmer unlike Lisp where the paren-based syntax itself takes care of it.
7:48:52
pyc
Oh right! That gives me ideas! Write Lispy code in Forth by using ( and ) fenceposts and defining operators to work on them. :-D
7:50:00
jdz
Nilby: How are those "fenceposts"? Aren't they just numbers (ASCII codes for the characters)?
7:50:54
pyc
yes, they will just be numbers (ASCII code for the characters) although there is syntax to specify them as literal characters while the compiler still puts their ASCII codes on the stack.
7:51:28
jdz
pyc: The case when the number of arguments is lexically apparent in the code is not very interesting, is it?
7:52:08
Nilby
Interestingly if you do object oriented forth, the order seems revered to prefix, so you say: object message message ...
7:57:15
moon-child
jdz: yes, but they can still have local variables. E.G. examining the python bytecode for 'lambda x, y: x*x+y' reveals LOAD_FAST instructions referring to the parameters
8:03:04
Nilby
jdz: forth has "words" which are equivalent to lisp symbols which are looked up a dictionary. Like lisp, some symbols evalualte to themselves, like T, so can be used for fenceposts.
8:09:09
jdz
Nilby: Yes, I know that much. But you're talking about compile-time fenceposts, not runtime, right?
8:11:43
Nilby
jdz: I don't think there's as big distinction in forth. It's still just a word on the stack. I suppose in an optimizing forth compiler could optimize the fencepost out in a compiled procedure.
8:15:28
Nilby
I think you're right, in pure forth. I guess what I used wan't pure forth, so it did have tagged objects and garbage collection.
8:20:52
Nilby
The most pure forth coding I did was in a bootloader and I can't remember if it had tagged objects or not. The forth-like language I used most was https://en.wikipedia.org/wiki/NeWS
8:25:27
no-defun-allowed
Most Lisp, Python, Smalltalk, Java, etc VMs look like the SECD machine more precisely, which has an explicated environment of some sort.
9:33:38
pyc
what is wrong with this code? https://pastebin.ubuntu.com/p/NRWXCB87tk/ - From my reading of http://clhs.lisp.se/Body/m_w_out_.htm , I should be able to specify a variable name that is not defined yet. What am I doing wrong here?
9:34:33
pyc
ohh! big typo. I meant with-output-to-string but I typed with-output-to-stream. let me fix that and try again
9:35:10
loke[m]
Thus, it's first trying to call a function called STREAM before calling a function called with-output-to-stream
9:53:34
beach
phoe: http://metamodular.com/SICL/call-site-optimization-talk.mkv is my talk. It is a bit more than 20 minutes long. There is a typo on one of the slides that I have since fixed, but I am not going to re-record the talk.
10:42:19
pyc
If I have a key name as a string, e.g., "a", can I convert it to :a so that I can use it with functions like getf to look up a plist?
10:44:12
pyc
pyc: Here is an example that describes my question in detail: https://pastebin.ubuntu.com/p/2HJD8QDjFW/
10:51:29
engblom
If I pass an object to a function, is it a reference to the object or a copy of the object that is passed?
10:53:48
engblom
I mean, if I have (defun foo (obj) ...) and I call it with (foo my-obj), is a copy of my-obj passed or a reference?
10:54:26
Nilby
engblom: It's not exactly either. It's a lisp object which can be a reference or a value. E.g. 1 is a value, *readtable* is a reference.
10:55:11
daphnis
if a class's slot symbols are package-specific, how does one export a function that uses the class? i get "When attempting to set the slot's value to ... the slot .... is missing from the object .... It has a slot pac1::slt, while pac2::slt is requested.
10:55:16
pjb
engblom: (while technically numbers and characters may be passed by value when they're small enough, since they're not mutable, there's no difference).
10:55:57
pjb
daphnis: one cannot export functions from package. packages only deal with symbols. You can export a symbol from a package.
10:56:27
phoe
and that you likely should not use it, and instead should use accessor functions whose names are actually by the package in question
10:56:47
phoe
if you absolutely need to set it and bypass this, then use the fully qualified name: (setf (slot-value foo 'pac1::slt) ...)
10:57:30
pjb
daphnis: the reason why is because accessors are methods, code, they can manage the consistency of the object. Perhaps setting a slot implies modifying another sslot, or sending a messasge to another object? If you use slot-value, this cannot occur. If you use an accessor that is overriden, the class can manage it.
10:58:40
pjb
The only values that may not be references are as I mentionned numbers and characters, which are not mutable, and therefore makes no difference if they're passed as value (copied) instead of reference.
10:59:07
pjb
_death: but even in that case, most numbers and most characters may still be passed by reference, because they're big (bignums, complex, ratio, etc).
10:59:40
phoe
in C++, you can assign a refrence and have the referent modified, which is like mutating a place from inside a function in Lisp
11:00:03
_death
pjb: right, but saying lisp uses pass by reference is misleading.. the values (which may be references) are copied
11:00:29
pjb
pyc: (prog1 one-is-the-result and not the rest) (prog2 nope two-is-the-result and not the rest) (progn not this not that but the nth-is-the-result)
11:02:30
pjb
_death: granted, saying that lisp uses pass by reference may be misleading, because in C++, references are references to the variable passed, while in lisp I mean that the value bound to a variable is a reference that is passed. So sorry. lisp is pass by value, but all values are references. (apart a few possible immutable exceptions).
11:04:38
phoe
the issue is that there is C++ pass-by-value and C++ pass-by-reference, and the only good answer to "is Lisp pass by value or pass by reference?" is "neither"
11:05:28
engblom
If I change my question a bit: would passing an object to a function which then modifies the object change the original object?
11:06:51
Nilby
I know both pjb and _death know exactly what lisp object is, so it's amusing that thare can be ontological debate about it.
11:07:40
pjb
engblom: the reference to the object is copied from the argument to the parameter variable.
11:08:01
pjb
engblom: hence pass-by-value, but since the value is a reference, it's pass-by-identity.
11:09:27
phoe
since it's the nth time I've seen this discussion and it would be good to store a compressed version of it somewhere
11:10:56
pjb
phoe: or just a little drawing, of objects in a heap, with arrows from variables to them and between them.
11:11:39
phoe
pjb: lemme quickly write down a sketch of what I am thinking about and I'll post it here for review
11:18:07
_death
phoe: in C (and C++) you can also pass references by value.. if you have an int a, you can pass &a, which is a pointer (a reference).. the pointer is copied and may be dereferenced
11:19:18
Odin-
ACTION got the impression from the Lisp 1.5 manual that conceptually all Lisp objects are references.
11:20:24
_death
phoe: in C++, you can pass the int by reference.. the callee states that a reference to int should be passed, by taking an int & parameter..
11:21:22
codecaveman
I want to write an iterative recursive factorial function which does work backwards: I mean my fact(a b) = { (a=0)->b; fact(a-1, a*b) } function multiplies numbers downwards n*n-1*n-2..3*2*1 can I write one which does 1*2*3*...(n-1)*n using only two variables?
11:25:10
pjb
(defun fact (n r) (if (zerop n) r (fact (1- n) (* n r)))) (fact 10 1) #| --> 3628800 |#
11:26:02
pjb
(defun fact (n i r) (if (= i n) (* n r) (fact n (1+ i) (* i r)))) (fact 10 1 1) #| --> 3628800 |#
11:27:14
no-defun-allowed
I would think you could with a cons or a closure to put two values in one argument, but that is following the letter and not spirit of what you asked.
11:27:20
pjb
codecaveman: but you would wrap any recursive function with accumulator into a normal function: (defun ! (n) (fact n 1 1)) #| --> ! |# (! 10) #| --> 3628800 |#
11:28:25
pjb
codecaveman: (defun fact (n) (loop for i from 1 to n for r = i then (* i r) finally (return r))) (fact 10) #| --> 3628800 |#
11:28:51
pjb
The recursive function with accumulator is equivalent to this loop anyways. The compiler can generate exactly the same code for both!
11:29:04
phoe
unless you have a clever trick of sorts to encode three numbers inside two numbers, probably not
11:31:43
daphnis
i'm trying to use accessor functions instead of slot-value, but since what slot to access is to depend on arguments, i'm trying (setf (funcall . . . and that doesn't seem to work: "The function (setf funcall) is undefined . . ."
11:33:52
phoe
if the accessor looks like (foo bar baz quux), then you should be able to (setf (foo bar baz quux) new-value)
11:34:12
_death
hmmm.. but yeah, the answer should likely be that you should pass (setf foo) to funcall
11:34:33
daphnis
yeah, but i want to give the name of the accessor function as an argument to the function that sets it
11:35:36
engblom
When being in repl, is there anything I can write to see the source or description of something. For example if I want to know what arguments map is taking, can I check it from repl?
11:35:43
pjb
daphnis: (defun function-that-sets (writer object) (let ((new-value 42)) (funcall writer new-value object))) (function-that-sets (function (setf answer)) question)
11:36:38
pjb
(defclass question () ((answer :accessor answer))) (let ((q (make-instance 'question))) (function-that-sets (function (setf answer)) q) (answer q)) #| --> 42 |#
11:39:10
_death
if you're using slime, I saw this recently: https://github.com/mmontone/slime-doc-contribs
11:39:48
pjb
daphnis: with setf apply you need to put (function accessor) literally in the apply place: (let ((q (make-instance 'question)) (a (function answer))) (setf (apply a (list q)) 42)) #| ERROR: Setf of Apply is only defined for function args of form #'symbol. |#
11:40:13
pjb
(let ((q (make-instance 'question))) (setf (apply (function answer) (list q)) 42) (answer q)) #| --> 42 |#
11:41:14
pjb
engblom: you can also know what argument an operator take, just by typing (map spc in a lisp/slime buffer. Then slime will query the lisp image, and display the required arguments in the minibuffer.
11:43:24
daphnis
so i probably need to use slot-value then? and then it seems that i need to export each slot symbol in order to use the function in a new package. maybe i just put more into one package.
11:43:27
pjb
daphnis: perhaps you're doing meta protocol stuff, and using the slots directly with slot-value is the right thing in your case. It depends on what you are doing. What are you doing?
11:45:14
pjb
But again, it depends on what you're trying to do, but this seems to be a state secret.
11:45:59
engblom
Is there something that is between let and setf, so the scope is limited to the whole function rather than either having a limited scope as in let or then a global variable as in setf?
11:47:12
engblom
I am asking because I would want to write some code that would require a lot of nested let, and making the variables scope to be the whole fucntion would be handy in this case.
11:47:22
pjb
engblom: you can also define function local variables with &aux in the lambda-list, but we usually reserve this for macro expansions, since it let you add local variables without having to deal with docstrins and declarations.
11:47:48
pjb
(defun foo (… &aux x y z) (setf x 1 y 2 z 3) (list x y z)) (foo 42) #| --> (1 2 3) |#
11:48:29
pjb
but we prefer the (defun foo (…) (let ((x 1) (y 2) (z 3)) (list x y z))) style (foo 33) #| --> (1 2 3) |#
11:48:58
pjb
engblom: also, note how nice LET is, since it lets you bind values to the variables. So you don't need setf.
11:49:58
daphnis
i have an object representing a letter and the slots represents various features, like case, accent, name, etc. the method changes one of those features. e.g. (furnish ltr :acute) should lead to the accent slot's being set to :acute
11:50:09
engblom
no-defun-allowed: Because I would need to do (let ((some thing)) (do-something else) (let((more things)) (do-again-something-else))
11:53:46
pjb
(defun furnish (letter trait value) (ecase trait (:case (setf (casse letter) value)) (:accent (setf (accent letter) value)) (:name (setf (name letter) value))))
11:54:20
pjb
daphnis: perhaps instead of writing (furnish letter :accent 'grave) you could just write (setf (accent letter) 'grave) ?
11:55:57
pjb
daphnis: where do the trait and value come from? If that comes from a data file, it's an external source, and it should be validated. This is what ECASE does: if we get a bad trait, it signals an error. And you cannot set slots that are not in the list of cases.
11:56:45
engblom
What do you think about me using (let ((x nil) (y nil) (z nil)) (some code) (setf x something) (some code) (setf y something) ... )? That would make local variables, but not requiring a lot of nested let.
11:57:12
pjb
daphnis: now, if there was a lot of cases, or if they were "dynamic" because you'd have different classes, perhaps not know at compilation time, we could have a data structure to map trait keywords to accessors, but we would still go thru this validation and control.
11:59:14
pjb
engblom: (let* ((x (compute-x)) (y (compute-y x)) (z (compute-z x y))) (do-something x y z)) so you can have some code between the binding of the variables with let*.
11:59:57
pjb
engblom: (let* ((x (progn (something) (compute-x))) (y (progn (something) (compute-y x))) (z (progn (something) (compute-z x y)))) (do-something x y z))
12:00:22
daphnis
the traits don't come from an external source. one other thing the furnish method does is that it determines the trait based on the value (if only one trait can have that value)
12:00:23
engblom
pjb: In this case each definition of let will have a side effect: it will place a form element on a site and the reference to the element is assigned to the variable. Because of that I need to add some code between (spacers, layout, text, etc) between each assignment with let.
12:00:34
pjb
engblom: typically, when you have to initialize some complex objects, you have to use some mutation. then you can do:
12:02:26
pjb
engblom: (let ((rt (let ((rt (copy-readtable))) (set-macro-character #\a (lambda (s c) (char-upcase c)) rt) rt))) (let ((*readtable* rt)) (read-from-string "abc"))) #| --> abc ; 3 |#
12:03:11
pjb
daphnis: note that even if furnish needs to do something more, this is something you can also do by writing eg. :after or :before methods on the accessors.
12:03:40
engblom
pjb: So (let ((olt (create-select ....))) ....) would create a dropdown list on the site, and I can read the value by doiing (value olt). But to create a real layout on the site I need to add some more stuff between the form elements, so I am not able to add everything inside of a single let without some tricks.
12:04:11
pjb
daphnis: eg. (defmethod (setf accent) :before (new-accent letter) (incf *accent-count*)) (defmethod accent :after (letter) (print 'yay))
12:06:22
pjb
engblom: now the thing is that the rule of evaluations in CL are very precise. macros and special operator explicitely specify in what order, and in what scope each subexpression is evaluated, and for function calls, the arguments are evaluated from left to right. Therefore you can wrap any subexpression in a prog1/prog2/progn to add side effects before and/or after computing the subexpression.
12:07:17
pjb
And some functions are specified to return their argument on purpose so you can write stuff as : (let ((x 42) (y 33)) (print (+ (print (* (print x) 4)) (print y)))) #| 42
12:07:53
pjb
engblom: print is used like that routinely when debugging. But you can use prog1/prog2/progn and add any side effect.
12:09:45
pjb
(let ((x 42) (y 33)) (+ (* (let ((x/2 (/ x 2))) (+ (expt x/2 2) (expt x/2 1/2))) 4) y)) #| --> 1815.3303 |#
12:10:49
pjb
engblom: and vice versa. If you have an expression too complex, you can always put (defun sub (x) …) around a subexpression and replace it with (sub x)
12:11:14
pjb
(defun sub (x) (let ((x/2 (/ x 2))) (+ (expt x/2 2) (expt x/2 1/2)))) (let ((x 42) (y 33)) (+ (* (sub x) 4) y)) #| --> 1815.3303 |#
12:12:06
pjb
engblom: sexps are very easy to manipulate in the editor, and since lisp operators are very orthogonal, the code (which is actually data) is very maleable.
12:13:03
pjb
engblom: there are only expressions, and and very little syntax in macros and special operators (eg. you cannot put an expression instead of the name of a variable in a LET; but apart from those few exception, you can put any expression in place of any subexpression.
12:14:23
pjb
engblom: (if (< delta 0) (- b (sqrt (- delta))) (- b (sqrt delta))) --> (- b (sqrt (if (< delta 0) (- delta) delta))) or even --> (- b (sqrt (funcall (if (< delta 0) (function -) (function +)) delta)))
12:14:25
engblom
pjb: Thank you! Now I would only need an easy way to send stuff from vim to repl. Now testing stuff has been taking time because every time I made a change I have been (ql:quickload :my-project) in order to update repl, and I have not been able to test any function that is not external.
12:26:44
engblom
pjb: I wonder if using some vim emulation in Emacs would cause any shortcut conflicts if using Slime?
12:30:45
engblom
Is this still valid, as it is from 2016? https://fouric.github.io/posts/2016-05-20-getting-set-up-with-emacs.html
12:40:41
edgar-rft
Common Lisp is more than 25 years old and Emacs is more than 40 years old, so 2016 is like yesterday in other programming languages :-)
13:03:08
engblom
I got emacs installed. In vim I would use :set background=dark to automatically change the colors of highlightning to be readable on a dark background. Is there something similar that can quickly be done in Emacs. Right now I can not read the code with my poor eyes (when running emacs -nw).
13:08:08
_death
engblom: well, apparently color-theme is the old, deprecated, obsolete, ex-parrot way nowadays.
13:08:45
beach
engblom: I am sorry my fellow #lisp participants probably confused the hell out of you.
13:14:43
beach
It means that you don't evaluate the argument, and instead you pass a reference to a place (or an l-value).
13:15:50
jackdaniel
this is simply part of the common lisp evaluation rules, not something "natural" or obvious
13:15:59
cer-0
IIRC there are some cases when you don't apply this behaviour, take cond for example if you write incorrect code after a valid clause they won't be evaluated.
13:16:17
jackdaniel
it is related, because you present it as some natural consequence of some unspecified rule of the universe
13:16:42
jackdaniel
ACTION will back down to not confuse people hell out and leave the explanation to beach and jmercouris
13:16:52
beach
jmercouris: So, C and C++, when you call a function with an "object" will copy the object by default.
13:17:54
beach
So if you call a function with an object, the object will be copied before it is passed to the callee.
13:18:20
jmercouris
I've never been programming Lisp and thought "Man, if only I had pointers that way"
13:18:56
beach
So they have to copy in order to make sure that the number of references to an object is always 1.
13:20:32
Bike
imagine a struct that's small enough to fit in two registers. if you pass it to a function, it's passed in registers without memory being touched. if that function alters a field, it just alters a register. when the function returns, the caller registers are restored from the stack, so the struct in the caller is what it was before the call. ergo, the object is "copied"
13:21:10
Bike
C++ then adds copy constructors and move constructors and prvalues and xvalues and my god it just keeps going
13:21:23
beach
So, as Bike says, the other consequence of "copy semantics" is that a function can't modify an object that you pass to it, because it is always copied.
13:21:53
Bike
the concept of a "move constructor" is basically what beach is talking about with the number of references only being one. if you "move" an object instead of "copying" it, the old thing referring to it no longer does
13:22:09
Bike
the semantics are pretty confusing, but that's what you need to do to keep this stuff up efficiently, i guess
13:22:40
beach
Yes, it is necessarily confusing because of the lack of automatic memory management and all the consequences that follow from that decision.
13:23:26
beach
So, to me, the only sane programming model is "call-by-value" and "uniform references semantics" which is what Common Lisp uses, no matter what other people here might say.
13:24:29
beach
Granted, most modern languages do the same thing, perhaps with a few exceptional cases like Java that handles machine integers differently, or it used to.
13:25:20
beach
It is quite amazing to me the snowball effect that lack of automatic memory management creates.
13:29:55
beach
Nilby, pbj: In my opinion, it is pedagogically unhelpful to bring up the performance hack that immediate objects such as fixnums and characters use, since those objects are immutable. The semantics would still be "uniform reference semantics". At least, it is unhelpful to someone who has no clue. You can bring it up when they start asking about references to small objects like characters.
13:35:25
pjb
jmercouris: (qrt) could be not evaluated in a lazy language; or if it was a place, and if lisp used pass-by-reference (of places).
13:36:06
Nilby
Yes, but I'm not sure saying "uniform reference semantics" or just saying "pass by value" will help someone familiar with C++. I think the problem with explaining is Lisp is defined by semantics, while C is defined by memory contents and addresses. The closest I can think of to relate to C is that lisp objects are tagged unions with internal pointers which are passed by value, but may have a bunch of built-in access methods
13:36:42
pjb
jmercouris: the pass-by-reference is normally used for output or in/out parameters. In languages like pascal, modula-2 modula-3, ada, etc.
13:37:08
jmercouris
my biggest mistake in the beginning was taking concepts from other programming languages and attempting to apply them
13:37:20
pjb
in lisp since we have multiple-value results (or we can easily return lists like in emacs lisp), in/out or output parameter are not needed.
13:37:55
jmercouris
but it is not always possible to translate every word or concept from one language to another
13:38:15
jmercouris
the biggest problem is that so many programmers, myself included are monolingual (I was, at least)
13:38:26
jmercouris
perhaps we know 5, 10 languages, but they are all different flavors of the same algol dialect
13:38:37
pjb
jmercouris: in C, we use pointers to the variables to do that, so it's explicit (but also confusing is that a pointer to a variable for an output parameter, an in/out parameter, or is that just a pointer as input parameter?). So C++ has & references to distinguish it from input pointers.\
13:38:40
jmercouris
I used many languages before Lisp, and they were all the different, but the same
13:39:23
pjb
jmercouris: but of course, C++ and C++ programmers also complexify things up with copy semantics and stuff like that so that references are also used in more "subtil" ways.
13:39:38
beach
Nilby: It is hard to help people who don't bother to learn standard terminology in the field.
13:40:10
beach
Nilby: The only way I can see how to do that, is to start by teaching them such terminology.
13:42:59
Nilby
beach: Also, the first link when searching for "uniform reference semantics" is written by you.
13:43:24
pjb
phoe: well, in C copied values are limited to words pushed to the stack, so usually only numbers characters and pointers are copied. But more recently, small structures too (and returned). But in C++ whole objects and structures can be copied. And with the funny thing that if you pass an instance of a subclass, only the slot of the superclass (declared for the parameter) are copied! So you can have half objects!
13:43:58
pjb
This is all silly, and the only reasonable way to program in C or C++ is to use pointers for everything, and start greenspunning.
13:44:00
phoe
beach: yes, that's the part that is troublesome - answering "Lisp is pass-by-value" does not solve the whole problem
13:48:13
pjb
jmercouris: also, since the general relativity we know that we live actually in a 4-dimensional space, and we're interconnected 4-dimensional breads.
13:51:23
beach
I can whip something like that up in no time at all, but then there is the drudge: turning into HTML or something like that, figuring out where to put it. Insert references, emphasis, blablabla.
13:52:18
Bike
i've found markdown pretty good for writing without thinking about that stuff too much
13:53:27
jmercouris
this for example; https://nyxt.atlas.engineer/article/class-based-functional-configuration.org
14:10:57
engblom
I just got Emacs setup and want to begin coding. How I am supposed to load a package so I can access even the functions that are not exported from repl?
14:18:34
engblom
I mean, I have a project under ~/common-lisp/gpon (with gpon.asd in that directory and the source files under ~/common-lisp/gpon/src). Now when editing src/main.lisp I can not compile the whole file with C-c C-k because then it fails to compile, even thou (ql:quickload :gpon) works great and I can run the external functions after that. How do I correctly load a whole package in Emacs+slim, so I also can
14:22:28
beach
phoe: I went a bit overboard. That text could be split into two different parts with one referring to the other.
14:25:28
engblom
So what is the exact procedure that I should do to be able to send stuff over to Slime REPL from emacs? Is it first adding (in-package #:asdf-user), as jackdaniel suggested, then once (ql:quickload :gpon)?
14:26:29
phoe
when I want to hack on e.g. phoe-toolbox, I do (ql:quickload :phoe-toolbox) and then open up one of its source files
14:34:15
phoe
this way your REPL will jump into that package, and you will be able to freely access internal symbols of that package
14:36:43
engblom
phoe: Thanks! Now I think I will get an acceptable work flow. I get to test the stuff much faster, without having to export everything I write (except for what will need to be exported in the end product).
14:37:17
phoe
when you're working on code a given package, it's often beneficial to have the REPL in it exactly for this reason
14:37:53
phoe
when e.g. doing testing it's worth to jump out of that package, even if only to ensure that the tests are not using unexported functionality and that all symbols that should be exported actually are exported
14:55:27
engblom
I have been using cl-project for creating the project skeleton. Each time I create a simple project for experimenting I need to edit the asd file or I will not be able to compile with just asdf:make. Is there a better alternative for creating a project skeleton?
14:57:03
beach
I don't see the point, really. Projects are not created often, and they all have a different set of file, barring perhaps two such files.
14:58:33
beach
You need a my-project.asd file and packages.lisp file. The only thing that you can create by default is the name of the project in the ASDF file, the name of the package in the packages.lisp file, and a singe line in the ASDF file containing (:file "packages").
14:59:21
vms14
the nice thing of trying other stuff is that you learn new concepts and can apply them later
15:00:16
phoe
(quickproject:make-project #p"~/Projects/Lisp/foo") and then I modify everything else by hand
15:01:38
engblom
Yes. I with Clojure I just do "lein new whatever-name" for creating a libary skeleton and "lein new app" for making something that will even have a main function and everything ready for compiling something I can run. Lein even takes care of uploading the library to clojars so other can depend on it (in a similar way as with quicklisp).
15:03:15
vms14
engblom: taking lein as a reference, you could create a nice project builder that would be useful for other lispers
15:10:03
engblom
phoe: Right now I am doing some coding for my workplace and I picked to write it in lisp because I want to learn lisp. Previously I have been coding Clojure, but my motivation for switching from Clojure to Lisp is that programs written in Clojure are very slow to start up on Raspberry Pi. Rosewell will not work at all on Raspberry Pi.
15:13:43
pyc
engblom: Are you your own boss at your workplace? or are you working for an employer? curious how you gained the consensus to write your projects in Common Lisp.
15:17:47
jmercouris
there is not a lot of boiler plate in Lisp, no need to have a project builder beyond the scope of quickproject
15:18:46
engblom
pyc: No, I am not my own boss. This project is a smaller side project as I am not working as a developer.
15:18:59
phoe
this is a quickly hacked article, I will finish it later today - I need to run and do ELS stuff now
15:19:32
vms14
jmercouris: I guess the real reason we don't need boilerplate is the lack of libraries
15:20:38
phoe
beach: yes, and I mention that in the chapter while explaining why I coin a different name for that term
15:21:02
beach
phoe: Call-by-value means that the arguments to a function are evaluated before passed to the function. Nothing else. You can't claim Common Lisp is doing something else.
15:21:03
phoe
(mostly because the term is already abused by C++ which implies copying, and we don't do visible copying in CL)
15:22:57
phoe
I mean, I don't know how to solve the problem where I call C++ call-by-value and Lisp call-by-value and then they do different things
15:23:13
beach
I think it is a huge mistake to cater to people who don't respect terminology that has been standard for 6 decades.
15:23:37
phoe
I think it's a huge mistake to not cater to people who are in the huge majority and would simply like to understand how CL is different from C++
15:24:51
beach
call-by-value has absolutely no other meaning than the fact that arguments are evaluated before the function is called
15:25:01
phoe
yes, we do, a huge chunk of the programming world has already partially done that to the point where even Wikipedia mentions that the term is ambiguous
15:25:53
phoe
vms14: mostly because inter-human communication is a hard problem that is never solved and is never going to be fully solved
15:26:48
Odin-
phoe: He does have a point in that it's worth noting that the C(++) understanding is not by any means complete.
15:27:17
phoe
vms14: we have terms like foo that we first need to define and second need to redefine when there's other people who have their own definitions of foo
15:27:30
beach
I guess we can also say that Common Lisp is interpreted, because that's what the interaction means, right?
15:30:13
phoe
OK, updated https://gist.github.com/phoe/c48b34275cf40bece9dbc5e555555214 - should be a bit better now
15:31:45
Odin-
phoe: I suspect that part of the problem is that people now think of C as a low level language.
15:33:14
pjb
Actually lisp is also a low level language. If you remove all the macros, and use only special operators and functions… And macros, are just add-on in the standard library (CL package), or from other libraries…
15:34:36
pjb
try to use tagbody and things like (rplaca k a) vs (setf (car k) a) (ie no setf -> setq), and soon it'll feel like programming in assembler.
15:34:52
Odin-
phoe: If you think the C compiler and runtime libraries aren't doing fancy stuff for you, it becomes easy to assume that the way that system works is how things are by default and everything that works differently is doing extra work.
15:36:42
pjb
Odin-: now you can make a comparison of the low-levelness of C and Common Lisp, (and perhaps other languages), and come to the conclusion that it's a matter of libraries and of point-of-view, and that it doesn't mean much.
15:37:18
vms14
could try to explain why, and they could try to explain too, but no one will understand anyway
15:40:30
Odin-
pjb: So you'd prefer that I say "well, Lisp is low-level too" above "C isn't low-level"?
15:41:22
phoe
Odin-: they are doing fancy stuff under the hood, yes - but not in case of passing parameters
15:41:47
pjb
Odin-: well, forget about low-level. We can agree that C can be used more easily to write code for micro-controllers than lisp. There's even a C substandard for that: n1169