freenode/#lisp - IRC Chatlog
Search
5:11:05
beach
asarch: I would like to know the specific feature you are looking for that you can't already do in CLOS.
5:21:50
beach
asarch: (defgeneric show (water)) (defmethod show ((water chocolate)) (format ...)) (defmethod show ((water coffee)) (format ...))
5:22:36
beach
asarch: And can you tell me what a "virtual function" allows that a generic function does not allow?
5:28:37
asarch
As you already know, virtual functions actually helps C++ to do the polymorphism stuff
5:29:46
beach
asarch: So the simple answer to your question is "no". But that doesn't mean that you can't do the things you can do in C++. It might mean that you don't need a special mechanism in CLOS whereas you do in C++.
5:30:10
beach
asarch: Which is why I wanted to know what particular characteristic of virtual functions you were looking for.
5:31:50
beach
For the record, I really dislike questions asked that way, i.e. "Does Common Lisp have the equivalent of the <mumble> feature in the <foo> language"? It presumes that 1) everyone knows the <foo> language. 2) that if <mumble> does not exist in Common Lisp, then Common Lisp is somehow inferior.
5:32:48
beach
I much prefer "What mechanism in Common Lisp would you use to solve the following problem...".
5:35:14
asarch
I guess that is the easiest way to ask things: "Can you do overload functions in Lisp?"
5:36:17
beach
"overloading" is typically a compile-time mechanism, whereas "generic dispatch" is a run time mechanism, so much more powerful.
5:38:27
loke
asarch: “overload” menas that you can have several functions with the same name. It does not imply that the choice of which implementation to call is actually chosen at runtime.
5:39:08
loke
asarch: In C++, if you have two functions: void foo(int) and void foo(char), that's overloading.
5:39:31
loke
asarch: But for the compiler to be able to choose which function to call, you have to know the type at runtime.
5:39:33
beach
asarch: Consider a method FOO in some language like Java or C++. It has two signatures, each with one argument. One signature has a DRINK argument and another has a COFFEE argument (COFFEE is a subclass of DRINK). Now do a DRINK d = new(COFFEE) and then x.FOO(d).
5:39:49
asarch
I thought: (defgeneric show (caffee) ()) and (defgeneric show (chocolate) ()) was actually the same :-(
5:41:06
loke
asarch: Here's another terminology tip for you: In C++ a “method” is a function that is attached to a class. In CLOS, a “method” is some actual code that _may_ be run when a generic function is called. The method is attached to the generif cfunction,. not to a class.
5:42:01
beach
asarch: So which method would be called in my example? The one with a DRINK argument, or the one with a COFFEE argument?
5:43:18
loke
Beach's statement sounded weird, until I replaced the word Drink with Beverage in my mind. :-) (drink being both a noun and a verb made me confused. I'm stupid :-) )
5:45:02
asarch
I was actually reading the pages of the CLOS book from the "Object-Oriented Programming in Common Lisp" book from Sonja E. Keene
5:45:51
beach
loke: The Swedish language is a mess (like most others), but in this case it would have allowed us to distinguish between the verb and the noun, yes.
5:56:23
beach
asarch: Most object-oriented language do a run-time dispatch only on X and not on the argument of the method. Which method will be called in such a situation is resolved at compile time, so the answer is "wrong" in this case. CLOS has multiple dispatch, so it does not have that problem.
5:58:50
beach
It is interesting to me that there are lots and lots of programmers out there, using one of these languages professionally, to produce code that runs in applications that I might have to use, and who do not know this fact.
6:06:39
asarch
I even bought the "The Art of the Meta Object Protocol" book when I was learning to use the web development framework from Perl: Catalyst
6:07:38
asarch
When I was working as an English teacher, all I wanted was a web application to keep all the related stuff for my students
6:11:03
beach
What is taught by a typical 5-year masters program (according to the Bologna system) is simply not enough to program professionally. But industry does not know that. So either we need to train industry to continue educating the programmers after they start working, or we need to define some kind of doctoral-level teaching program that should then be a requirement for working in industry.
6:11:49
beach
Stuff like this (overloading, single/multiple dispatch, etc) should be part of such a training program.
6:12:59
aeth
people have strong opinions about paradigms, and those strong opinions change with fashion, and the fashions change too quickly for programs to keep up
6:13:15
mange
beach: Maybe I misunderstand you. Are you saying that people should get a PhD before programming in industry?
6:14:23
aeth
mange: I think what beach is saying is that masters degree programs teach the wrong thing
6:15:21
beach
mange: It would not be a PhD, but some other doctoral-level program. A PhD is a research-oriented program, so that might not be well adapted to this situation.
6:16:11
beach
Yeah, but my estimate is that it would take at least 2 years after a masters degree, so a doctoral-level program would be possible.
6:17:35
beach
And, of course, as a Lisper, I consider it totally unacceptable for anyone who will program professionally not to have knowledge about Common Lisp, CLOS, MOP, etc. If for no other reason, to avoid re-inventing the wheel and being able to compare to what they are forced to use.
6:17:36
MichaelRaskin
I think the industry has recently discovered that what they want is trainable in one year (_instead_ of 5-year program). They don't care much for anything to work when they cannot define «working» code even postfactum
6:19:24
beach
The big mistake in academia is to think that industry NEEDS what it WANTS, which results in our teaching programs being a disaster.
6:19:52
MichaelRaskin
I think no amount of training programmers will help industry that doesn't care about correctness in specs _and_ defaults to not letting programmers talk to users directly and regularly
6:20:17
mange
Yeah, I think the bigger problems are in the the industry's priorities, rather than training.
6:22:44
beach
asarch: x WOULD be used for dispatch (that's what single dispatch means). But the point of the example is that the run-time value of d is NOT used for dispatch.
6:25:30
aeth
I don't think formal education is what you would want for programming training. perhaps my experience is skewed, but that tends to be research-oriented.
6:41:46
xificurC
I have a masters from something called maths & management, does that disqualify me from being a good programmer? :(
6:41:47
beach
What current post-graduate programs teach is beside the point. All I am saying is that people who program professionally often need way more knowledge than they get from a typical masters program. And since people working in industry are largely ignorant about such knowledge (which is why the don't WANT what they NEED), academia would have to be the place to define such a doctoral-level teaching program. Not that it would be easy,
6:41:47
beach
given that most university professors are ignorant too when it comes to that kind of knowledge.
6:42:35
beach
xificurC: There are excellent programmers out there with absolutely no formal training.
6:43:48
beach
But, and this is the point, most programmers receive their only training in some university program (at most 5 years, more often shorter). For them to be excellent, they need more training.
6:44:24
beach
They are not going to do enough self study to become good, and the company they are working for is not going to train them either.
6:46:37
shrdlu68
Perhaps an economic model can explain this? The programmers in company X only need to be as good as they ought to be to have some advatage over company Y.
6:47:12
xificurC
beach: my note was only written to let you further drive your point. Not that it wasn't true
6:48:02
White_Flame
beach: wait, you would consider understanding C++-family OO dispatch to be doctoral level?
6:48:28
xificurC
imho studying n years has no point when one doesn't enjoy the field and does self training
6:49:17
beach
White_Flame: I asked the same question to several masters-level students about to graduate, and they had no clue.
6:49:54
loke
beach: When I interview candidates for jobs that require programming experience, I make a point of trying to figure out how they learned it, and what drives them.
6:50:04
beach
White_Flame: There is just not enough about programming-language implementation taught in these programs.
6:50:19
loke
If the only practical programming projects they worked on was school projects, it's usually a red flag.
6:51:42
White_Flame
it's not the end of the world to expect them to learn on the job, if they seem like good learners otherwise
6:51:45
loke
White_Flame: Right, but if you're interestd in the topic, there is no reason why you wouldn't be working on personal projects.
6:54:13
asarch
I remember my next question: reflection and type introspection. Does Common Lisp support those features?
6:55:08
White_Flame
the only weakness with introspection is structures; everything else is fine with reflection & introspection
6:55:54
White_Flame
but there are usually non-standard ways included to fully introspect structs if you want to; normal class-based objects are fully introspectable
6:56:29
White_Flame
however, you generally don't need to introspect much because macros can create whatever metadata you need directly
6:57:04
pillton
asarch: There is also a difference between a type and a class. Types denote sets in common lisp and classes denote representation.
8:37:41
xificurC
uiop:run-program says :interactive makes the subprocess inherit the current output and that it can be different from *standard-output*. Why and how?
8:39:16
jackdaniel
as of why and how (regarding uiop interfaces), sometimes answer is: because it could; in a very hacky way involving internal implementation interfaces. just a general observation of a regular user who tries to make sense of some of these
8:40:57
xificurC
jackdaniel: it says e.g. in SLIME it would behave differently if it just used *standard-output*. Are you saying SLIME is using one of those hacky ways?
8:43:35
jackdaniel
I don't know what is this "current output" in your description, but if it is the lisp implementation process stdio, then SLIME has nothing to do with it (slime binds *standard-output* to a gray stream; uiop may want something with a descriptor, that is stdout)
8:44:40
jackdaniel
for instance ECL allows accessing these things with exported symbols in EXT package (like ext:+process-standard-output+)
8:45:41
xificurC
jackdaniel: I'm just reading the docstring: https://gitlab.common-lisp.net/asdf/asdf/blob/master/uiop/run-program.lisp#L507
8:46:44
jackdaniel
yes, I saw these monster docstring once or twice. that probably means, that it does what I have mentioned - tries to access process stdio
8:48:12
xificurC
jackdaniel: I started using it thinking it's one of those libraries that helps to write portable code
8:49:42
jackdaniel
I won't start rant on it, because there is a lot of work and testing put to it, I just happen disagree with a lot of things in this library (and some of decisions which stand behind these things)
8:51:30
jackdaniel
imho docstrings should provide short contextual reminder (for a person who has read the documentation having lengthier discussion of the interfaces)
8:56:21
shrdlu68
Could you link to the docs for the ~@ directive? I only know of @ as a modifier to other directives...
9:05:01
specbot
Tilde Newline: Ignored Newline: http://www.lispworks.com/reference/HyperSpec/Body/22_cic.htm
9:05:39
beach
"Tilde immediately followed by a newline ignores the newline and any following non-newline whitespace[1] characters. With a :, the newline is ignored, but any following whitespace[1] is left in place. With an @, the newline is left in place, but any following whitespace[1] is ignored."
9:07:52
beach
Yeah, using it means you don't have to ruin the overall layout of your code. Plus, Emacs is not always happy when there is text in column 0 that is not the beginning of a top-level form.
9:55:25
jackdaniel
I remember debugging this kind of issue in usocket (someone put there indifferent closing of the descriptor what caused problems, you may check closed issues for details)
9:56:47
jackdaniel
(also, if the descriptor is valid again - because someone in the meantime opened something else - you kill randomly in your process)
10:21:32
theemacsshibe[m]
Sometimes drakma doesn't pick up on text files (such as those put out by matrix servers). Is there a way to force it to put out a utf8 string? :external-format-in didn't work.
10:33:21
theemacsshibe[m]
Wait actually I think the docs said DRAKMA:DECODE-something does it, I'll have to check.
10:34:46
theemacsshibe[m]
DECODE-STREAM might take some work to process a vector, but flexi-streams has vector to stream conversion.
10:49:36
shangul
It says I have undefined variables(nm and mn) in the function main: https://apaste.info/aHXq
10:52:38
jackdaniel
shangul: defvar creates a special binding globally, if you put it in runtime mn and nm are not available when function is compiled
10:52:55
jackdaniel
if you want to introduce variables in the "main" function scope, you should use let operator
10:53:35
minion
shangul: please see pcl: pcl-book: "Practical Common Lisp", an introduction to Common Lisp by Peter Seibel, available at http://www.gigamonkeys.com/book/ and in dead-tree form from Apress (as of 11 April 2005).
10:53:51
beach
shangul: Or, in case you really want to share the variable globally, use DEFVAR at the top-level and SETF to assign to it.
10:55:32
beach
shangul: Yes, but the way you programmed it, it re-creates the variable each time you execute the function. That's not good style. The good style is to create the variable at compile time as a top-level form, and to assign to it inside the function.
10:56:11
jackdaniel
shangul: one of defvar characteristics is that it doesn't alter already existing bindings. so if you evaluate (defvar *nm* 3) and after that (defvar *nm* 4) *nm*'s value will be still 3
10:56:31
jackdaniel
also it is worth remembering, that global bindings should be put in earmuffs, like that: *variale*
10:56:38
beach
shangul: Worse, in this case, the variable is actually not created until the function is executed the first time, so the use of an un-created variable is what gives you the warning.
10:58:27
jackdaniel
(defun main () (let* ((mn (list 1 2 3)) (nm (reverse mn)) (format t "~a ~a~%" mn nm))
11:17:28
jackdaniel
shangul: except that it is fairly idiomatic. mind that indentation is very important
11:20:17
beach
shangul: Line 19 is not indented properly, and the format is not inside the LET* as far as I can see.
11:21:11
xificurC
shangul: another thing I would hope is idiomatic is to either have the if on one line or have the then and else part on separate lines, as I have done
11:22:00
xificurC
you had (if test #\newline then else), that's hard to read. Either (it test then else) or (if test #\newline then #\newline else)
11:23:20
xificurC
shangul: machines don't care, you can write everything in 1 line and will read the source code fine. You and people reading your code however will need to reason about your code. Indenting correctly makes reasoning simpler.
11:27:51
xificurC
shangul: you had "(ask-max-3 prompt) input-string)))". That's tricky to me :) I can read (if ... (ask-max-3 prompt) input-string) because I see the if will be a one-liner. But when the then gets its own line I expect the else to get its own too. Remember that an if's else is optional
11:29:05
xificurC
shangul: your format in main got into the bindings part of let*. I don't think that even compiles, does it? :)
11:29:47
shangul
<beach> shangul: Line 19 is not indented properly, and the format is not inside the LET* as far as I can see.
11:30:40
xificurC
shangul: yes but let is (let ((var1 val1) (var2 val2) ...) code-here-that-sees-var1-var2-...)
11:31:17
xificurC
shangul: you wrote (let ((var1 val1) (var2 val2) code-here-that-sees-var1-var2) nothing-here)
11:32:38
xificurC
shangul: that's only the initial feeling :) Once you and your brain get used to it it's easier to read than put-your-language-here
11:34:18
xificurC
shangul: it's much easier to write lisp in emacs with paredit/smartparens/lispy, or some other editor with equivalent tooling
11:35:00
shangul
xificurC, I'm using emacs and I used to work with C_children_languages + a little 8086 assembly
11:36:00
xificurC
shangul: C_children_languages is a very loose term, would you include java there? How about javascript? I'm not sure what makes a language C's child
11:37:11
shangul
xificurC, mostly C#(it's Java's clone), Python, C and less than these: Lua, C++ and Perl
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