freenode/#lisp - IRC Chatlog
Search
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
15:42:26
pjb
Odin-: coding for microcontroller in CL would involve, for the most practical way, writing a code generator and a compiler of a subset of lisp, like GOAL.
15:43:34
pjb
Odin-: but granted it's not strictly sensu a property of the language, more of the tools and the ecosystems. But they come with the language too, in part.
15:43:39
nij
vms14: someone may not like the answer but i think this is very true: http://www.winestockwebdesign.com/Essays/Lisp_Curse.html
15:44:26
nij
Imagine you have 20 people in your group, and you are the manager. Now imagine there are 40 groups like this in a team.
15:45:21
nij
So while lisp is better in theory, it might not be better in the eye of a project manager.
15:45:56
jackdaniel
historical data seems to indicate, that lisp may be very succesful in a corporate setting
15:46:08
pjb
nij: a project manager can easily manage the freedom of CL programmers, by defining packages to be used and forbidding other packages; and he could write the tools to check his rules trivially.
15:47:21
jackdaniel
nij: chicken and egg problem - nothing to do with the language. yet, there are capable cl programmers on the market
15:48:12
loli
nij types might offset that effect even more. From what I understand the LISP machine had types everywhere
15:48:14
Odin-
phoe: Which is the compiler arranging for something to be done in order to keep the semantics.
15:49:13
nij
I agree. I agree. I still believe there's some truth in Lisp Curse. But most likely, it might just because Lisp is not lucky enough.
15:49:26
Odin-
phoe: Which is my point - a lot of people seem to be under the impression that C's semantics come about without that.
15:50:03
loli
Might be the kind of people that are attracted to lisp. http://metamodular.com/Essays/psychology.html might help explain why?
15:50:05
phoe
but before I forget - is the stuff at https://gist.github.com/phoe/c48b34275cf40bece9dbc5e555555214 better now with regard to terminology?
15:50:06
Nilby
I was an impossible to control programmer before I used Lisp. Lisp just removes artificial barriers.
15:50:38
loli
I think the image system of CL in particular can offer a lot of great documentation and asssitant tools that should make corporate programming a lot easier
15:54:10
pjb
phoe: I would start with a paragraph or two about the fundamental difference: lisp is object/value based, while C/C++ are varable/type based.
15:54:12
nij
Btw, I'm reading LOL, and it says alambda isn't hygienic. I wonder if there's a hygienic version of it?
15:55:06
Odin-
phoe: I don't have an issue with it. I'd probably substitute 'The proper but unsatisfying answer' with something like 'In those terms, the somewhat unsatisfying answer'.
15:55:44
Nilby
nij: My story to far too lengthy, melodramatic, and not yet over. Perhaps I'll write my memoir when I can no longer write code, but more likely I'll die at a Lisp REPL.
15:55:55
pjb
phoe: 42 in lisp is an object; you can have references to it; variables don't store this object, but keep a reference to it. On the other hand, in C/C++, 42 only represent various bit patterns that can be stored in variables of different types, and that are interpreted, assuming those types to correspond to integer 42 or the floating point 42.0.
15:56:00
Odin-
phoe: Basically, allowing that we _are_ discussing it on C++'s terms while not conceding that those are necessarily correct.
15:57:16
pjb
phoe: declaring types in lisp doesn't declare the type of variables or slots, but the types of the objects that are bound to those variables or slots, and without a type declaration variables can hold objects of any lisp type; those lisp types are attached to the object, not the variables or slot that can refer them.
15:57:57
pjb
This is what gives the security in lisp: you cannot misinterpret bit patterns, or subvert them.
15:58:51
pjb
In the worst situation, in lisp, if you removed all the program and therefore all the variables, you'd be left with a heap, that you could scan to retrieve all the live objects and their data!
15:59:55
Odin-
The underlying hardware just usually has more specific support for particular operations on them.
15:59:56
pjb
The most you could do with a C heap, is to know the memory blocks allocated, but without the program and the typed variables, you couldn't know what type of object they represent (only guesses).
16:05:51
Nilby
I think C is the language that gives lispers the most trouble, because it dictates how we have to interface with things outside Lisp.
16:10:06
Odin-
Specifically, C is _specifically_ designed so that it doesn't have to deal with these issues at runtime. At all.
16:11:25
Odin-
(Which is one of the reasons it's much easier to shoot yourself in the foot using C than many other languages.)
16:12:58
Nilby
Except for things like the symbol garbage collection/tracing in dynamic linkers, runtime type information in C++,, etc.
16:16:04
aeth
You can actually do C-like abuse of the type system. You just have to pretend that you're talking to C when you're not, and use CFFI. https://gitlab.com/-/snippets/1830092
16:16:24
aeth
Not to mention that declarations are UB and SBCL with (safety 0) probably also permits such things instead of checking (but the solution is to never (safety 0)).
16:19:01
Nilby
Nice. I've see such code in implementations that can assume to know the float format too.
16:19:23
DGASAU
Nilby: while I could agree that C presents not the best IDL conventions, other languages provide worse IDL conventions.
16:21:59
DGASAU
In my experience, interfacing between any two different paradigms is possible only through something very reminiscent of C.
16:23:42
Odin-
There are plenty of things to complain about with C; the calling conventions are for the most part not near the top of that list.
16:26:22
DGASAU
All the rest usually boils down to "lets' launch XML-RPC/JSON-RPC/some-other-RPC servers and clients, perhaps bidirectional and asynchronous."
16:29:06
DGASAU
If you wish to experience what it feels, I suggest that you write something trivial on top of libpq.
16:31:26
shka_
i am seeing something unexpected with the combination of the dexador and alexandria:copy-stream
16:32:48
shka_
and then i simply use alexandria:with-output-to-file and alexandria:copy-stream to save the download into a file
16:33:33
DGASAU
Nilby: so far, the best approach in my opinion is proper IDL a la S-net, i.e. with non-recursive structures.
16:33:59
shka_
but sometimes, and this seems to happen just with the hltv, copy-stream for some reason blocks on what seems to be finish-output
16:36:01
DGASAU
Nilby: if you don't find it, tell me, and I'll probably find reference in some time.
16:37:17
DGASAU
Nilby: actually, it comes up on top in search output. Only it seems more elaborate than what I remember from the past.
16:42:44
nij
Does anyone happen to know if ambrevar will release the code of his "lisp repl shell"? https://ambrevar.xyz/lisp-repl-shell/index.html
16:45:34
Nilby
nij: Some the magic is at https://gitlab.com/ambrevar , but much of it is emacs/sly customization.
16:46:16
Nilby
shka_: I don't really know, but some servers keep the socket open, after trasmitting.
16:48:04
Nilby
nij: There's quite a lot of it in dotfiles and fof, but it's difficult to use other people dotfiles like that.
16:56:30
loli
I've found with inferior-shell I really like making quick scripts in CL, though the loading of CL as a standalone script is always somehwat painful if you don't ros it up
16:56:42
loli
yeah that's nice, I'm guessing you have undefined functions just search the bash path?
17:04:22
loli
the last feature you'd need to have a nicely working lisp shell on unix, is the ability to smoothly run stuff like ncurses windows, which it seems emacs currently can't easily
17:05:58
Nilby
You have to run it outside emacs to do ncurses, or use the thing that links a real terminal library into emacs.
17:09:12
loli
I've found for scripting that sometimes I have very short bash scripts, due to how annoying SBCL treats libraries when in shell mode
17:11:37
loli
so I have to do weird loading, that is often more annoying to figure out than otherwise
17:11:51
shka_
Nilby: i don't know, i suspect that this is somehow related to the dexador using connection pool but i am to tired to debug this right now
17:50:58
jcowan
Call by identity is good because it matches with the guarantee of putting something into a slot or variable: what comes out is eql to what went in.
17:51:59
jcowan
extending "slots" to include the car and cdr of a pair, the elements of an array, etc.
17:53:44
Josh_2
anyone had an issue with emacs where it occasionally pops up saying '<keypress> is not a valid command' meaning I have to hit the key twice? Very annoying
18:00:43
jcowan
pbaille: ##lisp is suitable for discussing all Lisps: CL, Scheme, Picolisp, you name it. It's also about the only channel where comparisons between different Lisps fits in.
19:21:52
theseb
Compilers in general strip the original high level source to an intermediate representation before barfing out assembly. Well since Lisp is a stripped down syntax that might be used for this intermediate representation, isn't it (sort of) true that compilers basically roughly just convert high level source to a lisp like lang and then implement that lisp source in assembly?
19:23:12
gigamonkey
Insofar as s-exps are a good way to represent ASTs and most compilers generate ASTs and then go from there, yes.
19:26:07
theseb
gigamonkey: to run lisp you need an evaluator...so i presume when people say they "compiled a program"...the executable literally has to implement an evaluation engine in assembly EVERY time?
19:29:11
gigamonkey
But if you take EVAL out of the language it doesn't actually change much and then you can compile a Lisp program down to assembly with no more ability to evaluate arbitrary Lisp.
19:50:08
Odin-
theseb: Well, you can think of the underlying processor's instruction set as the evaluation engine.
19:53:32
phoe
it's sorta tangential to the meat of the issue - how to pass parameters, what's copied, how to assign stuff