I always feel that for lisp-like languages it's just not a good idea to make them statically typed. Their power is derived from macros and the fact that code is data and the other way around. For statically typed languages, they only feel ergonomic to me if they have highly specialized syntax and if they really leverage the type-system (which is often in conflict with macros and runtime flexibility).
BLisp: A Statically Typed Lisp Like Language
21–30 of 51 posts
Re: BLisp: A Statically Typed Lisp Like Language
#22Earlier quoted context omitted.
What are the bugs? I am not familiar with lisp
Not OP so there might be others, but the two that I see are: * most crucially, x isn't actually spliced in, meaning that the macro always literally expands to (+ x x). For example, (+ (double 2) 5) just expands to (+ (+ x x) 5), which will either crash if x is undefined or do something unexpected if x is. * Even if x were spliced in properly, it gets evaluated twice. That's wasteful at best, and if x has some kind of…
Make that three bugs. The macro is called "double," but the numeric result is square.
Re: BLisp: A Statically Typed Lisp Like Language
#23Re: BLisp: A Statically Typed Lisp Like Language
#24In any case, it looks neat, I think the intersection of static types and Lisps is a space that needs more experimentation with, so I'm happy to see that.
I hope eventually it gains more effects as well, with only Pure and IO, you can't do much of the cool things that effect systems bring.
Re: BLisp: A Statically Typed Lisp Like Language
#25Why require Pure to be an annotation - why not make that the default without annotation - no effects? (Same as in Haskell)
Re: BLisp: A Statically Typed Lisp Like Language
#26Re: BLisp: A Statically Typed Lisp Like Language
#27Since the point of s-expression syntax/homoiconicity is macros, I'm surprised to not see any mention of them in the feature list linked here. Does BLisp support macros? If so, what kind? Also, is there an example of the type inference working?
Another reason for "code as data" is to enable (safe) remote code execution via RPC. For example you may want to query a database with a custom filter predicate function. If you pass one of BLisp's `Pure` functions across the wire, the database could execute the function with relative safety (compared with using `eval` with a string, or whatever). I find it frustrating that almost all popular languages lack any safe…
Re: BLisp: A Statically Typed Lisp Like Language
#28Earlier quoted context omitted.
What are the bugs? I am not familiar with lisp
Not OP so there might be others, but the two that I see are: * most crucially, x isn't actually spliced in, meaning that the macro always literally expands to (+ x x). For example, (+ (double 2) 5) just expands to (+ (+ x x) 5), which will either crash if x is undefined or do something unexpected if x is. * Even if x were spliced in properly, it gets evaluated twice. That's wasteful at best, and if x has some kind of…
(defmacro double (x)
(let ((temp (gensym))
`(let ((,temp ,x))
(+ temp temp))))
This way, when you write (double (parse-integer (read-line)) it would expand to (let ((#:uniqueName123 (parse-integer (read-line)))
(+ #:uniqueName123 #:unique_symbol_123))
This guarantees that that the macro will not accidentally refer to some outside variable, and that it's argument will only be evaluated once (so that we don't read two lines of input in this example).To explain a little bit what is going on: normally if you want to have an s-expression as a piece of data, you can use the quote special form - (quote (a b c)), usually shortened to '(a b c), returns a list containing three symbols (think of these as special strings), "a", "b", "c". If you want instead to evaluate a variable named "a", you can use the ` syntax, together with , and ,@. That is, `(,a b ,@c) will produce a list containing the value of a variable named "a", the symbol "b", and the value of a variable named "c", spliced in. If a is '(1 2 3) and c is '(4 5 6), `(,a b ,@c) will return the 5-element list ((1 2 3) b 4 5 6). Depending on how this is used further, b itself may be evaluated or just printed as is.
So, when expanding the macro, x will be initialized to the form provided as argument to double (not the value of that form). Then, temp will first be assigned a value that is produced by gensym, which generates a unique symbol; then, we'll return a list that represents some Lisp code binding the form represented by x to a variable whose name is the value returned by gensym, and then using this same variable name in a call to +. Finally, if this macro was "called" from regular lisp code, the expression it returned will be compiled or interpreted.
The macro could also be called from a special form like macroexpand-1, which would just return the list returned by the macro, without evaluating it; or macroexpand, which would do the same but recursively until there are no more macros in the expansion.
Note: a symbol is basically a string that can be used as a Lisp identifier, and is registered as such in the Lisp runtime. It is a separate type from string, but you can create a string from a symbol, or try to create a symbol from a string (which fails if the string is not a valid Lisp identifier).
Re: BLisp: A Statically Typed Lisp Like Language
#29Re: BLisp: A Statically Typed Lisp Like Language
#30Since the point of s-expression syntax/homoiconicity is macros, I'm surprised to not see any mention of them in the feature list linked here. Does BLisp support macros? If so, what kind? Also, is there an example of the type inference working?
Another reason for "code as data" is to enable (safe) remote code execution via RPC. For example you may want to query a database with a custom filter predicate function. If you pass one of BLisp's `Pure` functions across the wire, the database could execute the function with relative safety (compared with using `eval` with a string, or whatever). I find it frustrating that almost all popular languages lack any safe…