freenode/lisp - IRC Chatlog
Search
0:33:47
gilberth
Both will be executed, but on unlucky circumstances one thread will have a "stale" value for 'a'.
0:35:29
gilberth
Well, when I understand the problem correctly. You want that if one thread tries to increment by 1 and the other by 2 you want a guarantee (sp?) that 'a' is incremented by 3, right?
0:38:53
gilberth
This has nothing to with Lisp. This happens in any language. The problem is: To increment a variable, you read its value, do the addition and write back the result. While you do the addition the value could be changed by another thread.
0:40:15
tsizz
i don't really understand the difference is between static type checking from compiler vs. runtime
0:40:16
gilberth
So you need to guard access to the 'a' variable. For that you use a lock. You have a lock for that variable. Before entering the increment operation (reading, incrementing, write-back), you aquire the lock and get exclusive access.
0:44:57
aeth
cryptopsy: Swank is a way to communicate with a Common Lisp server over TCP, for interactive debugging development.
0:45:44
aeth
cryptopsy: So it's sort of like LSP if you're aware of it https://en.wikipedia.org/wiki/Language_Server_Protocol
0:46:49
cryptopsy
don't automatically assume i know what a SHOUT is, afterall i barely understand function
0:47:32
aeth
cryptopsy: So for historical reasons Common Lisp is "case insensitive" by default in that it upper cases everything it reads, so foo becomes FOO. This means that Lispers are usually used to entering 'foo and getting FOO back. So a lot of Lispers randomly upcase things, including some who say LISP, randomly upcasing Lisp itself.
0:49:46
aeth
It's actually sometimes useful to refer to functions (or macros) in upper case in prose, such as CAR and CDR and CONS, even though we always by convention write source code in lower case these days
0:51:10
bjorkintosh
aeth, lisp is old and hard of hearing and has a noticeable speech impediment, so it THOUTH.
0:52:09
aeth
cryptopsy: Every ugly part of software (and programming languages are just software) basically has to have a mini-history lesson because if it's ugly and everyone immediately notices it "historical compatibility" is probably the reason why it is the way it is.
0:53:03
aeth
The only thing worse than a mildly ugly feature is writing something that worked 10 years ago and no longer works today. Except a lot of people no longer hold that attitude, which is why in some ecosystems you have to rewrite your software every few years. What a mess.
0:54:18
aeth
cryptopsy: Well, Scheme is more consistent because it broke backwards compatibility with early Schemes
0:54:53
aeth
(and Racket itself broke backwards compatibility with Schemes a while back by making cons cells immutable)
0:55:55
aeth
cryptopsy: With Common Lisp, you can run LISP 1.5 (in this case LISP because they had no lower case on computers back then!) programs with minimal changes. It values backwards compatibility, so it has some rough edges that you either just have to accept or learn why it is the way it is
0:57:10
aeth
This also means it has some macros and functions that (almost) no one uses like PROG and RPLACA
0:57:19
cryptopsy
i wonder if the swank from the simpsons is the same swank as in lisp, the show wad some writers which were math grad students
1:01:49
aeth
cryptopsy: To understand SLIME (Emacs) or Slimv (vim) you have to understand the Common Lisp workflow, which is fairly unique. Really, only one other language that I know of (Smalltalk) really thinks like this. It's about running things in an interactive image. It is basically like the REPL you might have seen in Python or JavaScript, except considerably more advanced.
1:02:09
aeth
Lisp actually invented the REPL (read-eval-print-loop) and you can sort of get a primitive REPL just by doing (loop (print (eval (read))))
1:04:39
aeth
cryptopsy: Most programming languages think in the Unix way (usually because most programming languages are made for Unix and then later get ported to the other OSes) of having a text program that is compiled or interpreted, but essentially working at the file level.
1:05:16
aeth
Common Lisp doesn't really necessarily care about files. You use something like ASDF (and Quicklisp on top of ASDF) to make it care.
1:05:33
White_Flame
FORTH has a somewhat similar workflow to Lisp, except that there are more ordering issues on definitions
1:08:09
aeth
cryptopsy: There are implementation specific ways to get an implementation like SBCL to load a file and treat it like it's a Unix scripting language (except implementations like SBCL are natively compiled! so the compiler will have to run first!), but what people commonly do when developing is just work directly in the interactive image, usually through something like SLIME or Slimv to make the REPL friendlier to work with.
1:08:55
aeth
And if you're doing an advanced program the way to do an executable is to actually get an image and then save the image! In SBCL it's save-lisp-and-die.
1:09:28
aeth
The distinction is the latter approach will bundle the language runtime with the executable, and the former approach requires you to have the implementation installed locally.
1:10:56
aeth
When developing you just keep the interactive image running in the background, perhaps restarting it every now and then if things break or to make sure your program will work with a fresh image.
1:11:34
aeth
This "in the background" Lisp has to run a swank server so your IDE (or whatever else) can talk to it.
1:11:56
aeth
(It doesn't have to be swank, but if it's not swank, you'll probably have to write the server protocol yourself.)
1:15:05
aeth
cryptopsy: All of that gigantic wall of text explains the design, but if you want you can just see how someone interactively codes Lisp live for a web stream (in this case, using Emacs). https://youtu.be/aiJxkaxMBVE?t=555
1:17:21
aeth
Don't be intimidated by that video, though. He's more efficient at that sort of thing than most of us are because he does it for livestreams.
1:35:49
pjb
tsizz: the thing to understand in static type vs. dynamic type, is that in the case of static typing, the type is associated with the variable: any bit pattern stored in a variable of type T is interpreted according to the type T.
1:36:35
pjb
tsizz: on the other hand, with dynamic typing, the type is associated with the value. The value can be stored in any variable, it brings with it its type. So you can never make a typing error with dynamic typing, because you always know the type of the value you have.
1:38:54
pjb
tsizz: so when the variable is typed, you can blindly use the bit patterns stored as if they were of the type of the variable: this is fast, but if the bit pattern is invalid, this is catastrophic: you get crashes or worse like in C programs. The solution is to let the compiler prove that the bit pattern stored in typed variable are always valid, but this implies strong constraints on what you can do. cf. Haskell.
1:39:10
aeth
pjb, tsizz: And you can have both at the same time, such as how SBCL typically interprets type declarations (which can be given meaning by implementations)
1:39:42
aeth
It avoids the mess of something like Haskell or Java by... not really having the ability to get too elaborate in the types held by data structures, though. For the most part, you're holding T.
1:39:43
pjb
tsizz: on the other hand, when the values are typed, you can check their type at run-time and perform checks or select your behavior according to it. This is slower, but much safer!
1:41:48
pjb
tsizz: this extends to I/O too. For example, in C you can scanf("%d",&int_var); if you enter abc, or "hello" it breaks. (returns a status code). On the other hand, in lisp, you do (read), and the parser determines the type of the value in function of the syntax: 123 is an integer, 1.23 is a float, abc is a symbol, "hello" is a string, #(1 2 3) is a vector (a b c) is a list, etc.
1:42:08
pjb
tsizz: so you can read values of any type. Then you can check or dispatch at run-time. It's safer.
1:45:40
pjb
in OO languages, it's possible to use run-time dispatch, since object are dynamically typed. But some OO languages such as C++ allow for objects that are statically typed, and compilation-time dispatch. This has a lot of problems! You can assign an object to a variable typed by a superclass,and lose information! It's crazy.
1:48:24
aeth
pjb: CL can have compile-time dispatch, through several different libraries. e.g. https://github.com/guicho271828/inlined-generic-function/ and https://github.com/markcox80/specialization-store/
1:49:48
aeth
The difference, how you don't lose information, is that the tag is always there unless it's certainly safe to remove, e.g. double-floats in an array that holds the element-type double-float
1:52:50
aeth
And that's why you only see it for something like double-float. If it worked for your class (or even struct!) foo it could have a distinct subclass. double-float is just double-float.
1:56:10
White_Flame
even with subclasses, if the entire instance struct was inlined in the array space it could be done
2:02:38
aeth
White_Flame: I was told that the problem with having proper array-of-structs in CL *was* subclassing, but I can see two solutions. (1) don't inline the child structure-class's fields but leave room for them somehow or (2) don't allow child structure-classes to work in those arrays
2:02:56
seok
Not a problem though, I can use hunchentoot for development, then use woo on production linux server
2:03:45
kristof
can't find the logs so I don't know what cryptopsy said but I'm just using #!/usr/bin/env sbcl --script at the top of a small (1KLOC) lisp file I have
2:03:52
aeth
White_Flame: The other problem you get is the semantics of aref, though. CL is not a language where copying really is a focus, and you wouldn't even want the copy-foo of a struct, you'd want a custom copy-foo-into.
2:04:09
aeth
White_Flame: So to solve the latter you couldn't just use element-type, you'd have to use a different data structure
2:13:54
aeth
White_Flame: Can you define locatives? They're not on Wikipedia and it doesn't seem to be search-engine-friendly. (The modern search engine decides to show you completely irrelevant results instead of too-unpopular results or no results.)
2:14:55
White_Flame
but ideally it would be handled in the underlying runtime to be more transparent
2:15:30
White_Flame
but, while that would work for reading such an inlined object in an array, it wouldn't work for placing an object into the array, as you mention above
2:15:45
aeth
White_Flame: Well, it's easy to say that if you did (foo-ref your-data-structure 42) you'd just point to there with any reference. Setting is harder. I don't think setting really should be done at all. Just make the array-like data structure itself immutable, but its contents could potentially be mutable.
2:15:53
White_Flame
since that would be a copy and would have to involve updating all references or create a new object instance
2:17:26
aeth
What you'd want is a special kind of array that is adjustable, but also of a fixed size (so basically fill-pointer on a non-adjustable vector kind of logic), and a way to copy out and copy in.
2:18:25
aeth
So if it's an array of foobars, they will forever be foobars, not even a subclass of foobars. And if you wanted to remove element #42 you could do something like copy the last element into the 42nd position and shrink the array down by one. That could even be built in since that's probably the most straightforward way to do arbitrary removal here.
2:19:13
aeth
You would also be able to take a reference, since any helper functions would probably best work on that, such as functions that expect one argument, a foobar. No need to copy for that sort of thing.
2:19:50
aeth
But since it's immutable (foo-ref foo 42) works but (setf (foo-ref foo 42) (make-subclass-of-foo ...)) would not.
2:20:53
aeth
Now, there's immediately a difficulty here, though. If you delete 42 using the described deletion scheme, the index 42 now refers to a different element, which was previously the last element.
2:21:34
aeth
(And similarly if you have a live reference to the 42nd offset into the data structure)
2:22:33
aeth
You'd probably want to double index in practice (also makes it immune to sorting), but would you want this sort of double index thing to be built in or have to be managed manually?
2:24:23
aeth
It certainly *would* have to be done at the level of implementations, though, or at least partially.
2:27:30
aeth
Oh, I overlooked that if 42 is the last element, then a stale reference to 42 is even worse because it's now (potentially) invalid instead of just the wrong valid option you get from if you deleted 42 from the middle or if you sorted.
2:30:31
aeth
So I guess (aref foo 42) would have to use something locative(ish) if that's what a locative is. It'd have to know if foo got removed or moved, so the remove/move logic would have to be built into the data structure, too.
5:00:56
aeth
There's other criteria. Benchmark? Write a toy program in both and see which API feels better?
5:03:31
aeth
The license is definitely a good filter, though, I'll agree with that. I don't use anything LLGPL because it's a custom license not approved by the FSF or the OSI.
5:04:04
aeth
And you can't use any license more restrictive than the license you intend on using. AGPL is the (near) universal receiver, MIT/BSD has to be a lot more careful.
5:06:04
aeth
CL-WHO is BSD and Spinneret is MIT so essentially any program can use either (* not taking into account the unlikely event of software patents)
5:06:39
aeth
tsizz: the Wikipedia article seems to be fairly clear about it. https://en.wikipedia.org/wiki/S-expression
5:08:05
beach
tsizz: That might be because there are two meanings. One meaning is a Common Lisp data structure in memory made up of CONS cells and atoms. The other meaning is the textual representation of such a data structure.
5:08:27
aeth
I think generally the diagram used for s-expressions is box-style instead of that tree-style, though... i.e. [ * | --]->[ 2 | --]->[ 3 | \ ] for (* 2 3) with any additional nesting going on rows below.
5:09:33
tsizz
so S expression is any object or function in between paraentheses that can be broken down into cons cells and atoms?
5:10:32
beach
tsizz: Any Common Lisp data structure is made up of CONS cells and atoms. There is nothing else.
5:10:57
aeth
tsizz: Oh sorry I added to the confusion. S-expression is the notation we use to represent the cons cells.
5:11:08
aeth
tsizz: the box notation is an alternative representation, obviously a lot harder to type
5:11:50
aeth
tsizz: imagine if you had to draw this to program instead of '(42 69 613) https://commons.wikimedia.org/wiki/File:Cons-cells.svg
5:11:52
tsizz
thats what i said right? that s expression just easier way to write constant cons cells?
5:12:48
tsizz
beach: i meant instead of writting a lot of const cells u can write an easy s expression kind of
5:12:51
aeth
tsizz: the syntax becomes a linked list, which is then processed, which could create anything
5:14:00
beach
tsizz: You are in the wrong channel then. This channel is dedicated to Common Lisp, and the terminology may be different.
5:14:52
aeth
tsizz: (make-hash-table) is, at a certain stage of the program `(make-hash-table) which is roughly equivalent to (list 'make-hash-table) or (cons 'make-hash-table nil) but at runtime it's a function call that returns a new empty hash table, not a list.
5:15:49
beach
tsizz: Look in the glossary under "atom": http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_a.htm
5:15:50
aeth
and some things like #(1 2 3) or "123" are, at all times, never lists... they're atoms.
5:16:34
tsizz
someone tried to explain to me atoms are numbers, booleans, etc. then S expression are basically atoms or lists of atoms
5:18:01
tsizz
beach: im just confused as what the point of s expression is. if its a data structure like you said. it seems liek its a datatsructure holding a data structure
5:18:14
aeth
tsizz: yes, an atom is simply not a cons. http://www.lispworks.com/documentation/HyperSpec/Body/t_atom.htm
5:19:32
aeth
tsizz: There's essentially three stages going on. First you have a stream of characters. These are assigned meanings. Basically atoms or conses. And then this runs and becomes the program. So you can put a macro at either stage (the reader, or the s-expressions) to change the behavior of the earlier stages.
5:20:30
aeth
I think ( is a reader macro in Common Lisp. In fact, it looks like it is... http://www.lispworks.com/documentation/HyperSpec/Body/02_d.htm
5:20:55
Jachy
If you squint an S has a ( with a ) below it... but the s in s-exp stands for symbolic. It's just a format to represent expressions. In math you might have an expression like f(x, y) for a function call. With m-expressions you might see f[x;y]. With s-expressions, (f x y).
5:23:00
aeth
tsizz: The reason we care about if something is an atom or not is because of the stage when DEFMACRO works. The common kind of Lisp macro. A macro can take `(a b c) and turn it into something like `(setf b (* 2 c))
5:24:26
Jachy
If my text editor has (format t "Hello~%") in it, it's an s-expression, but it's not being evaluated. I can tell Lisp to evaluate it, though.
5:25:46
aeth
tsizz: Most programming languages only have strings or charcter streams to work with. This makes it hard to write programs that write programs, or to add new syntax. By writing (f 1 2) instead of f(1, 2) we have a nice, regular notation that makes it easy to add new syntax.
5:26:09
aeth
The regular notation is pretty important because we don't just have (f 1 2) we also have (+ 1 2)
5:26:28
aeth
Most languages don't do +(1, 2) they do 1 + 2. And now to extend the language completely you have to teach it both prefix and infix.
5:26:39
tsizz
mhm.. so an S expression is just any expression that fits the syntax of lisp basically..?
5:26:54
Jachy
You can do it that way, but you don't have to wrap it in a function. You can also run Lisp interactively from the console, it will prompt you for expressions to read, then evaluate, print the results, and loop back to the prompt. You'll see the phrase REPL for that behavior. You can also configure many editors to send the file contents directly to an already running Lisp process for evaluation.
5:28:18
tsizz
so s expression is any expression in lisp bc its anything that contains atoms or list of atoms and that is what everything in lisp is made out of excluding cons
5:28:41
aeth
tsizz: Well, there are other syntax elements to Lisps. In Common Lisp, you get #x42 as a representation of the number 66 in hex. That uses syntax, but not s-expression syntax
5:28:57
aeth
So atoms can have their own syntax, and they can be different in different Lisps (and other Lisp-like languages)
5:30:16
aeth
tsizz: s-expression syntax is the (a b c) as shorthand for (a . (b . (c . nil))) as well as that longer (a . b) etc. syntax
5:31:02
aeth
lists are cons cells, yes. (a . (b . c)) is also legal and that can be shortened to (a b . c)
5:31:54
tsizz
aeth: mhm but if atom is defined as anything not a cons cell, then a list shouldn't be an atom?
5:32:11
aeth
In Scheme, lists must end with '() which is their nil. In Common Lisp, dotted lists are lists, and the ones that end in nil are called proper lists. (This is a Common Lisp channel.) So in Common Lisp, lists and conses are essentially synonymous
5:36:25
aeth
'(a b c) is a proper list whose cdr is '(b c) whose cdr is '(c) whose cdr is '() or nil (both are valid representations of nil)
5:38:36
aeth
In Common Lisp, you could define listp like this: (defun listp (object) (or (consp object) (null object)))
5:40:18
aeth
Note that in Scheme/Racket list? uses the Scheme definition of list, which is proper list in Common Lisp. So (listp '(1 2 . 3)) is t in Common Lisp but (list? '(1 2 . 3)) is #f in Racket.
5:40:28
aeth
So if you're writing list? for your Scheme implemnetation it afaik has to walk the entire list
5:42:25
aeth
tsizz: In modern terminology, the thing created by (cons 1 2) is a cons, a cons cell, a cons pair, or a pair. Interchangably, really. Schemes tend to call them just "pairs" (but still create them with cons) and Common Lisp's glossary just calls them "conses"
5:44:57
aeth
Hmm, apparently they can also be called "NATSes", but I've never seen that before. Also, just plain "cells". https://en.wikipedia.org/wiki/Cons
5:46:27
beach
aeth: You should be more careful with words such as "is" and "equivalent" when you are talking to people who are learning the terminology.
5:46:29
aeth
Generally, you use ()s without quotes only in macros which in reality makes it just '() since the macro's arguments are essentially just quoted.
5:47:24
tsizz
aeth: mhm, but im confused why the distiniction of having to add '() to end of a list to make a proper list. like what for?
5:47:41
beach
But tsizz is not into evaluation yet, because he/she has not understood what an expression is yet.
5:48:08
aeth
tsizz: A proper list ends in '() but you normally don't see it. You only see its absence.
5:48:38
tsizz
beach: maybe i do haha my knowlede is a bit scattered. few weeks ago i had to do this hw and did it in racket in 2 days.
5:48:53
aeth
tsizz: '(a . (b . ())) is '(a b) and not having it, e.g. '(a . (b . c)) would make it '(a b . c)
5:51:49
aeth
in common lisp '(a . (b . '())) is (A B QUOTE NIL) instead of the (A B) you might expect
5:52:18
tsizz
but im still confused on why u have a properlist structure that is just a list that ends in nil
5:53:08
aeth
tsizz: that's so when you go over a sequence of conses, you can just look at the CAR to get all of the elements and stop when CDR is NIL
5:54:43
aeth
it's a cons, and it's a list (in Common Lisp, not in Scheme), but it's not a proper list. It's a dotted or improper list.
5:58:15
aeth
You usually do want that NIL at the end to terminate things, and having the existence of things that don't end in NIL is sort of a leaky abstraction.
6:00:28
aeth
Just remember that '(a b c) is really just syntactic sugar for '(a . (b . (c . ()))) or '(a . (b . (c . nil)))
6:12:37
aeth
tsizz: null isn't a number, it's the empty list. It's tested with null? in Racket and null or endp in Common Lisp
6:15:52
aeth
tsizz: When you iterate through a list, you start with '(a b c) then work on '(b c) then work on '(c) then work on '() updating with the cdr each time
6:16:15
verisimilitude
The end of a list being NIL is just a sentinel value, tsizz. There are some nice qualities that come about when the empty list is also the ending of a list.
6:16:28
verisimilitude
In Common Lisp, it's also the only false value; this is very convenient for manipulating lists.
6:18:05
aeth
tsizz: similarly you don't have '(1 2 3 4 '()) you have '(1 2 3 4) but iterating through it gives you '(1 2 3 4) then '(2 3 4) and eventually '() when no elements are left
6:19:47
aeth
tsizz: you're essentially moving through sublists because every list has a list as its cdr (which wouldn't be the case if lists didn't end in nil, btw)
6:23:06
aeth
tsizz: when you're iterating through a list, you normally care about the car and the cdr
6:23:29
aeth
tsizz: you're not iterating through values (unless you use something like map) you're iterating through sublists, so you have to take the car
6:25:21
aeth
I think that that will work but it's not tail recursive because the tail call is + not the function itself.
6:25:47
aeth
If you wanted it to be tail recursive you would have to build the value in another argument to make sure that the function's tail call is the function itself.
6:26:20
aeth
If you do recursion and can do tail recursion, yes, you should try to do tail recursion. In Common Lisp, it's rarer than Scheme because the optimization is not guaranteed.
6:31:49
Jachy
tsizz: You might want to go through the first chapter of this book https://mitpress.mit.edu/sites/default/files/sicp/full-text/book/book-Z-H-4.html#%_toc_start It's for scheme, but most of the lessons will carry back to common lisp.
6:31:55
aeth
tsizz: you have to pass it through and build it up through each iteration just like you're doing with the sublist. Except your answer is growing as the sublist is shrinking
6:32:33
aeth
tsizz: so (f (cdr list) (+ (car list) result)) and then at the end return result instead of 0
6:35:35
aeth
If you don't want the recursion, the do macro is equivalent to (a subset) of this sort of iteration in Scheme and near-equivalent (the edge case involves making closures) in Common Lisp.
8:00:14
splittist
I love the way search engines correct my searches for 'plump lisp'. Now I want to start a project called Botox.
8:05:05
aeth
They're better at being Ask Jeeves than Ask Jeeves ever was, but I don't want to ask natural language questions. I want to query specific terms that might be very niche.
8:11:48
aeth
If CL wasn't so niche it'd probably be very searchable because of its anti-symbolic naming conventions (except for arithmetic).
8:37:11
flip214
aeth: well, if you _know_ you're looking at standard CL stuff just bookmark http://www.lispworks.com/documentation/HyperSpec/Front/X_Mast_9.htm and be done ...
12:13:57
schweers
talx: in case you mean https://en.wikipedia.org/wiki/Cadence_SKILL, it is /a/ lisp dialect. This channel is dedicated to Common Lisp.
12:16:41
schweers
talx: no need to be sad. Common Lisp is around today and is a very good language with good, free implementations available.
12:17:26
runejuhl
I've only worked with it for a bit of debugging, and I'm happy for that.. just the idea of a `]` operator that closes all open braces gives me pain
12:20:23
schweers
In case someone wants to accuse me of arrogance: I’m sure I’ve uttered my fair share of bad ideas.
12:21:57
runejuhl
schweers: "In the second example, the "super right bracket." This simple device automatically enters enough right parentheses to correctly complete the current expression (in this case the procedure definition)."
12:22:19
runejuhl
schweers: from SKILL: A CAD System Extension Language, 1990, https://www.cs.york.ac.uk/rts/docs/DAC-1964-2005/PAPERS/1990/DAC90_266.PDF
12:24:35
runejuhl
here's a real example: https://github.com/cdsgit/cdsgit/blob/master/cdsgit-build/cdsgit.il