lainchan / λ

Let's design a lisp

Anonymous · 2014-12-16 19:25
Alright lain let's design a lisp. Why? well for fun. Besides, we all dislike *some* aspect of whatever lisp we are using so, why not get together and try to agree on a lisp with which most people can be happy? Who knows, if everything goes well we might even implement and make it lain's official lisp dialect. What features would make the perfect lisp? lisp-1 or lisp-2? (I'll vote for 1) typed? lazy? object system? hygienic macros enforced? continuations? what else? I'd too suggest that there be some facility to "glue" programs from other dialects for true portability. Though I can't think of a good way to do it now. Any ideas?
Anonymous · 2014-12-16 19:51
If we are going to make a new Lisp, instead of trying to make it perfect, why don't we make it interesting? What about a data-flow lisp?
Anonymous · 2014-12-16 20:20
>>4024 >why don't we make it interesting? why not? what do you mean by data-flow, like, sockets and soykaf?
Anonymous · 2014-12-16 23:00
Yes, I just had that very same impulse too. It should be a lisp-1, absolutely. Also, no #t or #f, just nil (= '() or (list)) and everything else.
Anonymous · 2014-12-17 05:28
Remove parentheses, use whitespace instead.
Anonymous · 2014-12-17 05:55
Lisp-1, typed, lazy. I'm pretty much fine with any other choices, but I think those three are fairly essential to having a clean language design. However, I am slightly in favour of enforcing hygienic macros. >>4024 Functional programming is already kinda dataflow programming, though. We define functions in terms of referentially transparent operations applied to parameters.
Anonymous · 2014-12-17 06:27
>>4023 You can add all of this to pre-existing Lisps. The only reason Lisp is still around is because it is so easy to change it into whatever is needed.
Anonymous · 2014-12-17 09:27
>>4024 >>4024 Let's embed a relational logic engine into the language's compiler. It gives fuarrrking fast code with logic predicates, pattern matching, reversible code execution, and CLOS style methods! :D
Anonymous · 2014-12-17 15:44
>>4038 use postfix notation instead of prefix and you've got yourself a forth-variant.
Anonymous · 2014-12-17 19:05
>>4033 Or, no, we use Church booleans of course. ((= 1 2) 3 4) -> 4 This only works if the language is lazy though, right?
Anonymous · 2014-12-17 19:26
>>4045 In a strict language, conditionals need to be a special form, yes.
Anonymous · 2014-12-18 17:58
>>4038 ;; parentheses (+ (f 1 2 3)) (+ (f 1 2) 3) (+ (f 1) 2 3) (+ f 1 2 3) ;; whitespace + f 1 2 3 + f 1 2 3 + f 1 2 3 + f 1 2 3
Anonymous · 2014-12-18 18:05
>>4052 That's taking whitespace-sensitive layout to a whole new level…
Anonymous · 2014-12-18 18:25
>>4052
Anonymous · 2014-12-18 22:07
>>4053 FORTH already does this, but is postfix notation 1 2 add 0 1 < if function else function2 then its been a while but its something like that. forth > lisp
Anonymous · 2014-12-18 23:22
>>4052 similar to haskell but more extreme on that matter Now what about, say, a function that takes a function and two arguments, but passed a function which takes some argument and returns a function and then the two arguments of the outermost function Such soykaf would mean mayhen
Anonymous · 2014-12-18 23:39
>>4052 what if we had only one space for each layer of parenthesis and assumed everything was left-associative? We could use some other character, like $ for example, to force right-association
Anonymous · 2014-12-19 00:33
>>4055 Stack based languages are the best. : palindrome? ( str – ? ) dup reverse = ; : factorial ( xs – n ) [1,b] 1 [ * ] reduce ; : sum ( xs – n ) [1,b] 0 [ + ] reduce ;
Anonymous · 2014-12-19 00:35
>>4042 >reversible code execution Racket already does that. #lang racket (define (current-continuation) (call/cc (λ (k) (k k)))) (define fail-stack '()) (define (fail) (if (null? fail-stack) (error "back-tracking stack exhausted!") (let ([back-track-point (first fail-stack)]) (set! fail-stack (rest fail-stack)) (back-track-point back-track-point)))) (define (amb choices) (let ([cc (current-continuation)]) (cond [(null? choices) (fail)] [else (let ([choice (first choices)]) (set! choices (rest choices)) (set! fail-stack (cons cc fail-stack)) choice)]))) (define (assert condition) (if (not condition) (fail) #t)) (let ((a (amb (list 1 2 3 4 5 6 7))) (b (amb (list 1 2 3 4 5 6 7))) (c (amb (list 1 2 3 4 5 6 7)))) ;(displayln (list a b c)) ; We're looking for dimensions of a legal right ; triangle using the Pythagorean theorem: (assert (= (* c c) (+ (* a a) (* b b)))) (assert (< b a)))
Anonymous · 2014-12-19 12:09
>>4062 the biggest over sight in forth imo is using how you define functions. the : is an operator that takes the argument after it, instead of before, it delays execution. blah blah. but if it was like: palindrom? : dup reverse = ; it would make sense in the english language as it is proper use of a semicolon.
Anonymous · 2014-12-19 13:02
>>4065 That doesn't seem to make the flow any less weird.
Anonymous · 2014-12-19 18:33
I was thinking about weird potential lisps the other day, and here's a snippe from my Org file. * DLLISP: Doubly-Linked-Loop Processing - Circular doubly-linked-list as the native data-structure - Left/right handed operator preference - "CAR" is NULL, which serves as the terminator for both ends of the loop. + Can be another value, as in an improper list, e.g. '(a . b), but special considerations must be made, as with any non-terminating sequence. + Should be lazy by default in this case.
Anonymous · 2014-12-19 18:50
>>4038 So you want to implement a python/whitespace* hybrid on top of Lisp as a DSL? * http://compsoc.dur.ac.uk/whitespace/
Anonymous · 2014-12-19 19:14
>>4067 As an example of what I mean, in Common Lisp using a standard singly-linked list, it would look something like this: `(#1=,(gensym) B C . #1#)
Anonymous · 2014-12-20 03:55
>>4067 Car is null? terminator in a circular doubly linked list? wtf are you talking about there m8? I like the idea of the DLL Lisp, have any idea of what kinds of things you could do with it?
Anonymous · 2014-12-20 09:46
>>4073 Process doubly-linked lists.
Anonymous · 2014-12-20 10:53
>>4066 Depends on your first (natural) language, if you spoke korean the word order would seem natural. Also http://www.computer-solutions.co.uk/chipdev/fph-1.htm Read example washing machine code at bottom, pretty easy.
Anonymous · 2014-12-20 17:57
>>4073 >wtf are you talking about there m8? A doubly linked list where both ends point to the same object in memory as the terminator or origin of each loop. >have any idea of what kinds of things you could do with it? Well, you could always find your way to the top of a tree structure, thanks to the bidirectional linkage, and looping constructs might be made a bit redundant in a few cases, but I don't think this sort of design is especially fruitful, more of just a fun thought experiment.
Anonymous · 2014-12-20 18:01
>>4079 I think the "wtf" is that you're saying you have an explicit terminator in a cyclic list.
Anonymous · 2014-12-20 18:07
>>4080 How is this a problem?
Anonymous · 2014-12-20 18:13
>>4081 it's just counterintuitive, as far as abstraction goes, there is no 'start' and 'end' to a cyclic list
Anonymous · 2014-12-20 18:28
>>4082 The terminator would be purely a linguistic construct, and stopping on it would only be convention. Plus, it makes things like addressing easy without having to resort to asking something like "who's got the lowest memory address?"
Anonymous · 2014-12-20 19:43
>>4083 But that would make it hard to have the reference point to an arbitrary element of the list. It wouldn't be too different to have a static pointer to the initial cons and work on it through a sort of modulo addressing. I'd instead suggest to set a 'mark' at the element pointed to initially when starting a computation.
Anonymous · 2014-12-20 20:18
>>4070 I can understand a doubly linked list, but why make everything circular? If I need to cycle, I'd rather make a circular list explicitly or just use some kind of promise/stream/generator.
Anonymous · 2014-12-31 04:44
I was reading K&R C and wondered if this would be a good idea: a low-level lisp with a minimal set of functions (quote, cons, car, cdr, lambda, define…) and loadable libraries basically, a lisp version of C. Of course conses would be a high-level facility, and I don't really know how low level control could be given to a lisp beyond what's already available…
Anonymous · 2014-12-31 04:54
>>4163 Writing macros in sexpr C doesn't sound too fun.
Anonymous · 2014-12-31 05:30
>>4166 well it sounds like making sexpr C++
Anonymous · 2014-12-31 05:32
>>4167 though there'd be no need to make a horrible design
Anonymous · 2015-01-03 20:21
>>4178 >>4179 Please don't bring this soykaf here.
Anonymous · 2015-01-03 21:42
>>4178 >>4179 bringing that to lainchan is the exact opposite of what we want I think you should lurk a bit more
Anonymous · 2015-01-04 01:11
>>4180 >>4181 Please don't respond to bait. Use the report button for off-topic posts.
Anonymous · 2015-01-05 18:11
>>4163 >Of course conses would be a high-level facility There are actually lisp machines that implement cons and cdr/car in their bytecode.
Anonymous · 2015-01-05 20:12
>>4189 yeah, but I mean it for von Neumann architectures and there ain't lisp macheens no more, as far as I know, other than legacy junk that few people even know about
Anonymous · 2015-01-06 17:19
>>4190 https://www.mail-archive.com/picolisp@software-lab.de/msg04823.html
Anonymous · 2015-01-06 18:10
>>4023 All variables should be dynamically scoped.
Anonymous · 2015-01-06 18:20
>>4201 Do you want to lose modularity? Because that's how you lose modularity.
Anonymous · 2015-01-06 19:03
>>4202 What about namespaces? It'll be just like newLISP!
Anonymous · 2015-01-09 07:35
>>4063 >reversible code Racket is great but I was thinking something like miniKanren. (ns woot (:refer-clojure :exclude [== record?]) (:require [clojure.core.logic.fd :as fd]) (:use [clojure.core.logic])) (defne triangleo [A B C X] ([[?A . ?At] [?B . ?Bt] [?C . ?Ct] [?X . ?Xt]] (fresh [a-sq b-sq c-sq] (squareo ?A a-sq) (squareo ?B b-sq) (squareo ?C c-sq) (fd/+ a-sq b-sq c-sq) (== ?X [?A ?B ?C]) (triangleo ?At ?Bt ?Ct ?Xt))) ([[_ . ?At] [_ . ?Bt] [_ . ?Ct] _] (triangleo ?At ?Bt ?Ct X)) ([[] [] [] []])) ;; find all triangles with sides ranging from 1 to 7 (run* [q] (fresh [a b c] (== a (range 1 8)) (== b (range 1 8)) (== c (range 1 8)) (triangleo a b c q)))
Anonymous · 2015-01-31 12:15
"PyLISP" ;; parentheses (+ (f 1 2 3)) (+ (f 1 2) 3) (+ (f 1) 2 3) (+ f 1 2 3) ;; whitespace + f 1 2 3 + f 1 2 3 + f 1 2 3 + f 1 2 3
Anonymous · 2015-01-31 12:18
Pylisp ;; parentheses (+ (f 1 2 3)) (+ (f 1 2) 3) (+ (f 1) 2 3) (+ f 1 2 3) ;; whitespace + f 1 2 3 + f 1 2 3 + f 1 2 3 + f 1 2 3
Anonymous · 2015-03-06 22:38
>>4544 Can we not? Significant whitespace is the bane of good design.
Anonymous · 2015-03-07 02:49
>>4544 >>5020 Check Wart for a Lisp with Python-like keyword args and significant whitespace. https://github.com/akkartik/wart
Anonymous · 2015-05-09 06:58
bump
Anonymous · 2015-05-09 11:50
>>5020 http://www.unlimitednovelty.com/2009/03/indentation-sensitivity-post-mortem.html
Anonymous · 2015-07-26 17:27
Bump
Anonymous · 2015-07-26 19:29
Can't see anything seriously wrong with the current ones. Implicit strong and static typing would be something new, I guess. Add to that runtime bounds checks within image. Then wrap it up and call it SafeLisp. I vote for Lisp-2.
Anonymous · 2015-07-27 01:37
I've only started looking into lisp so I can't really contribute, but if you don't call it eastern calculus I'll be very disappointed.
Anonymous · 2015-07-27 01:44
>>7939 Lisp is purely from the occident. It has naught to do with the orient.
Anonymous · 2015-07-27 04:33
>>7940 Just like all computer stuff?
Anonymous · 2015-07-27 17:17
>>7940 Even better, since that gives an excuse to look at mathematics as was developed in the east and use it as a basis for creating a distinct variant of lisp instead of just regular lisp with few minor changes.
Anonymous · 2015-08-15 00:12
>>4023 1 lisp-1 2 strong, static type system (possibly with a composable dynamic type parameterisation facility) 3 strict evaluation, because laziness can be easily implemented anyway, and syntax is not a limitation in a lisp 4 optional hygiene. I like Clojure's way 5. yes to continuations 6. type inference 7. stack-based read-macro system (i.e. within some specific trigger characters, a new DSL is active during read, which is activated by being pushed on a stack) 8. clojure-like: let syntax, concurrency facilities, hashmap syntax, destructuring 9. CL-like support for optional args, named args, rest args 10. parenthesis-avoiding operators: Haskell's $ (except it will apply till the end of the form), F#'s pipes, Clojure's ->
Anonymous · 2015-08-15 10:41
>>4065 That destroys the glory of Forth, which is being able to immediately act upon each individual token with no look-ahead. This is especially useful when it's the low level language on the chip; you essentially get a shell and interpreter for free. The way it is is ideal.
Anonymous · 2015-08-15 17:38
>>8553 >5. yes to continuations Continuations are a part of virtually every programming language. With first-class functions you can explicitly generate and pass around objects which act like continuations. Do you mean continuation reifying? In which case, do you support call/cc, delimited continuations, or both? I feel like there's good reason to only use delimited continuations.
Anonymous · 2015-08-15 17:52
Has anyone ever been far as implementing basic features any Lisp will need, such as tokenization or garbage collection? If so, upon what platform? If not, what strategies should be employed? Wouldn't it be better to get essential features working then decide what the language will look more like?
Anonymous · 2015-08-15 18:02
>>8582 lexing is a simple task for any language, and parsing for Lisps is pretty straightforward and can be done easily without a parser generator. The only problem would be special read tokens, which probably wouldn't be too bad if you were smart about how you designed your lexer. GC I've never done, but I've been reading about it lately. I think SICP goes over it in the last chapter, along with other low-level Lisp implementation details.
Anonymous · 2015-08-15 18:16
>>8582 >>8583 A lisp parser is extremely simple. Common Lisp style reader macros are easily invoked in cases as simple as when the character is encountered. It's a very basic algorithm: http://clhs.lisp.se/Body/02_b.htm
Anonymous · 2015-08-15 18:27
>>8583 >>8584 In other words, no. The devil is in the details. Such as: > An entire token has been accumulated. The object represented by the token is returned as the result of the read operation, or an error of type reader-error is signaled if the token is not of valid syntax. Great! So, now we just have to implement/decide upon a [hash table|AVL Tree|Red-Black Tree|Binary Sorted List] design to store the symbol table, because although Lisp processes lists, quickly looking up an item in a list is the job of hash or tree-like structure. The same goes for everything else to do with the language implementation. As a langdev myself, hand-waiving such implementation details doesn't instil much confidence.
Anonymous · 2015-08-15 19:00
>>8585 It's not hard. Most Common Lisp atoms don't have a printed representation that read must handle. You only need to account for symbols and numbers in read itself. Every other datatype is built from functions and reader macros that call those functions. The representations are made by dispatching print-object on the data. It's not complicated at all.
Anonymous · 2015-08-15 20:40
>>8585 >>8585 >So, now we just have to implement/decide upon a [hash table|AVL Tree|Red-Black Tree|Binary Sorted List] design to store the symbol table, because although Lisp processes lists, quickly looking up an item in a list is the job of hash or tree-like structure. Any of those data structures would take less than an hour to implement reasonably, although you really should use someone else's implementation and save yourself the headache. Deciding isn't important so long as you're able to change your decision later-- hide the implementation details in your code and you'll be able to switch the data structure underneath seamlessly. If you were an experienced langdev you'd be more concerned with language design at this point. Worrying about implementation details too early, especially for a high level language like a Lisp, is a waste of time. Parsing and lexing are very easy and well studied tasks anyway, and Lisp is less difficult to parse than a toy arithmetic implementation.
Anonymous · 2015-08-15 22:28
>>8592 > Any of those data structures would take less than an hour to implement reasonably, Having done so many times, I disagree. Otherwise: > although you really should use someone else's implementation and save yourself the headache. Wouldn't be true. I'm not saying that it's important to pick one of these now, I'm saying we haven't even done that despite how trivial it is to do so, as you point out. > If you were an experienced langdev you'd be more concerned with language design at this point. Nope. Lisp allows rapid incremental development. Are you saying such is not a good approach? At this point I'd be worried that 3/4th of a year has gone by and despite everyone telling me everything is so trivial to implement we don't have target implementation platform or a single feature written yet, not even a basic tokenizer. Every Lisp has many common elements which make it recognizable as a Lisp. That we don't have a single one of those operational is concerning. > Worrying about implementation details too early, especially for a high level language like a Lisp, is a waste of time. I disagree, in that I don't think it's too early to begin work immediately. It's not like we're inventing a whole new language paradigm that need be planned out in advance of implementation. Any sort of result would be nice, since the common opinion seems to be that everything about implementing Lisp is so easy/simple. So, where's the proof? > Parsing and lexing are very easy and well studied tasks anyway, The proof is in the pudding. If it's so easy, then where is our lexer? We should have one for every target implementation platform by now... considering the belief that interfacing most features into an interpretor takes "less than an hour to implement".
Anonymous · 2015-08-16 02:59
>>8596 You seem pretty confused. >Wouldn't be true. A 30 minute headache is still a headache, and other implementations may have more features, be more lightweight, etc. >Nope. Lisp allows rapid incremental development. Are you saying such is not a good approach? For language design it is a terrible approach. >Every Lisp has many common elements which make it recognizable as a Lisp. That we don't have a single one of those operational is concerning. Given that most of this thread has been a casual conversation I'd say you're taking things too seriously. Most people have conflicting ideas about what they want in a language, so before we settle on that designing a lexer and parser for one particular Lisp would be a waste of time. >It's not like we're inventing a whole new language paradigm that need be planned out in advance of implementation. We could be! We haven't decided yet. Even if we weren't, making careful decisions about basic aspects of the language early on is a good choice I think. >Any sort of result would be nice, since the common opinion seems to be that everything about implementing Lisp is so easy/simple. So, where's the proof? Chapter 4 of SICP describes an entire interpreter for Scheme within Scheme, and then modifies it for different scoping rules and logic programming. If you want to read how easy it is you can look there. > If it's so easy, then where is our lexer? >We should have one for every target implementation platform by now... ??? Which "target implementation platform"s are you referring to? We haven't decided upon anything. >considering the belief that interfacing most features into an interpretor takes "less than an hour to implement". Here's a decent lexer and parser in one line of Scheme: (define (read-lisp) (read))
Anonymous · 2015-08-17 04:21
How far can we go before it starts to look less "lispy"?
Anonymous · 2015-08-17 04:28
Replace: (loop for i from 1 to 100 do ...) With: (loop i 1 100 ...)
Anonymous · 2015-08-17 05:00
>>8596 I was under the impression that this was all casual discussion that wouldn't actually lead to anything being implemented. >>8611 Reader macros can do that. It should all boil down to lists and atoms at some point though. >>8612 You have to take into consideration that `for' is not the only possible opening loop clause. The current setup works to make the macro readable as if English while also eliminating ambiguity.
Anonymous · 2015-10-06 15:09
I can't justify just letting this thread die yet. Let's see if there's any more discussion.
Anonymous · 2015-10-06 16:49
>>10207 Did anyone even do anything? I read through the thread and don't really see much progress. Maybe we need some action instead of just discussion.
Anonymous · 2015-10-31 06:19
>>4023 Bump for existence