libera/commonlisp - IRC Chatlog
Search
21:19:49
pjb
We can use such literal lisp data to represent programs: (if (= a b) (princ "equal") (princ "different"))
21:20:39
pjb
We can write programs called interpreters or compilers, to evaluate such programs. There's CL:EVAL, CL:COMPILE, and CL:COERCE that can convert S-expressions representing programs into lisp execution or compiled lisp functions.
21:21:09
pjb
To represent a function we use the data syntax: (lambda (a b) (if (= a b) (princ "equal") (princ "different")))
21:21:24
pjb
And we can compile it: (compile nil (quote (lambda (a b) (if (= a b) (princ "equal") (princ "different"))))) #| --> #<Anonymous Function #x302008B990DF> ; nil ; nil |#
21:21:41
pjb
We can then call this function: (let ((fun (compile nil (quote (lambda (a b) (if (= a b) (princ "equal") (princ "different"))))))) (funcall fun 1 2)) #| different --> "different" |#
21:22:13
pjb
Here the s-expression is a literal (as denoted by the quote operator); but you can also build it with your own programs.
21:22:27
pjb
Oh! Note that the program (let ((fun (compile nil (quote (lambda (a b) (if (= a b) (princ "equal") (princ "different"))))))) (funcall fun 1 2)) is also a S-expression!!!
21:23:28
pjb
This works because the lisp system contains a REPL and a file compiler and file loader that will read those S-expressions, and pass them to CL:EVAL automatically: (LOAD "file.lisp") or (COMPILE-FILE "file.lisp"), or the REPL.
21:23:46
pjb
the REPL is a Read Eval Print Loop that is the basis of interaction with the lisp system.
21:24:15
pjb
When you type a S-expression in the REPL, it is first READ, ie the text you type is converted to a lisp data structure (a list if it starts with "(").
21:24:42
pjb
THen this lisp data structure is passed to CL:EVAL which will interpret it, and return the result. The result is passed to PRINT which prints it.
21:26:05
pjb
rendar: Smalltalk blocks are like lisp anonymous functions. They can be written in S-expression as: (lambda (parameters…) (let ((local) (variables) …) body expressions result))
21:26:49
pjb
So you can write (defmethod ifThen ((test T #| generalized boolean |#) thunk) (if test (funcall thunk)))
21:28:09
pjb
and since we represent lisp program sources as lisp data, you can use S-expressions to write all lisp programs.
21:28:57
pjb
In almost all other languages, the source is defined as a text file, ie a string of characters.
21:29:26
pjb
But in lisp, the source is lisp data (cons cells, atoms, numbers, strings, etc). This is what is processed by EVAL or COMPILE.
21:29:45
pjb
Only this lisp data can be read with CL:READ, from the S-expression form (which is also a textual representation).
21:30:13
pjb
And since there's also a printer CL:PRINT to print S-expressions, we can print and read and print back code (or data).
21:31:14
pjb
Now, there are some types of lisp objects that don't have a readable print syntax. Eg. packages: *package* #| --> #<Package "COMMON-LISP-USER"> |# It starts with #< which cannot be read.
21:32:36
pjb
But for you own classes of objects, you can define a method on the PRINT-OBJECT generic function to print them readably.
21:33:07
pjb
For example, CCL does this for random states: *random-state* #| --> #.(ccl::initialize-mrg31k3p-state 1662898282 955392070 420261365 823417203 431141722 953184299) |# It uses the #. syntax which reads a form and evaluates to read the object.
21:34:02
pjb
rendar: yes, and no. The thing is that the grammar is trivial. There's a lexical analysis which is specified in the chapter 2 of CLHS, as the "lisp reader algorith", and all the rest of the syntax is defined as reader macros and dispatching reader macros.
21:34:30
pjb
The lisp reader algorithm knows only how to read symbols, integers, ratio and floating point numbers.
21:35:53
pjb
We can give a coarse grammar for S-expr, but this is only what lisp does by default, with the default reader macros. You can install your own reader macros, and change that syntax.
21:36:23
pjb
rendar: AFAIK nope. There's a copyright on the web site. IIRC gcl had the authorization to make a copy in info format.
21:37:10
pjb
rendar: the ANSI/ISO organization will sell you for dear money a PDF of the standard, which is a bad scanning of a paper printout. It's not worth paying for it, unless you need it for legal reasons.
21:38:19
pjb
atom ::= integer | ratio | float | string | structure | … . all literal lisp object syntaxes specified by the reader macros.
21:38:56
pjb
rendar: I like ccl. sbcl is liked by a lot of people because it generate fast code, but it has the inconvenient of having a new release each month!!!
21:39:18
pjb
rendar: abcl is nice if you want to run on the JVM. ecl is nice if you want to embed it with C applications.
21:40:03
pjb
rendar: I find clisp nice for newbies, since it contains an interpreter, and some niceties, (but a lot of people don't like it because it has new releases each 10 or 20 years, and compiles to a VM).
21:48:59
pjb
rendar: note that you may prefer to read some book or lisp tutorial before reading the CLHS, since the later is not pedagogical at all (it's a language reference).
0:53:40
Roy
I was over on #programming and discussing what we on #programming talk about and said how I hate OO, but like CLOS and multi-dispatch.
2:19:04
nij-
People have also been arguing that trigonometry doesn't help when you buy groceries, therefore it's useless.
3:18:37
nij-
beach > Is it true that any language that has throw/catch + dynamic variables can implement a conditions system as powerful as Lisp's?
3:21:26
Bike
the way the condition system works, handlers are executed during signaling, but signal can just return normally.
3:21:35
beach
nij-: The power of the condition system is not due to any complicated implementation technique. It comes from implementing the right abstractions. Otherwise, the condition system is quite simple.
3:21:36
Bike
so you need to be able to run code in its original context, like its lexical environment.
3:22:27
Bike
it is possible, sorta. i think the windows C++ exception handling do... something like it. "funclets". i haven't looked into it much.
3:26:42
Bike
the resumptive quality is critical to how lisp conditions work and it's not common in other languages. if you don't allow handlers to resume, your implementation can just unconditionally jump up the stack frames and there ya go.
3:48:08
nij-
But Bike was answering "nij- > Why do we need first class functions?" which might be hard to answer though..
3:51:34
nij-
But I'm aware it's not always an easy task.. I often found it hard to explain something I know well too :(
3:57:19
beach
The point, though, is that when you design a language, you should include the low-level primitives that allow you to build powerful, yet simple, high-level mechanisms.
4:04:52
Bike
the basic nature of exceptions or conditions or whatever is that you have a function F call a function G, and G transfers control to F in some way other than returning normally.
4:05:26
Bike
in most languages that's one way: G does an abnormal exit and you're back in a "handler" in F. but in lisp the handler can decide G is actually doing fine, and control can resume in G somewhere.
4:06:12
Bike
because of this, it has to be possible for the handler code to run without permanently exiting G.
4:06:37
Bike
the simple way to do this, which implementations generally do, is to have the handler be a first class function that the signaling code in G just calls normally.
4:10:52
nij-
It makes more sense! Thank you, Bike. However, why can't the handler be a non-first class function? After all, the signaling code G can call a non-first-class function.
4:14:21
beach
nij-: If it is not a first-class function, it would have to be invoked by name, like (handler ...), but the name is not known statically.
4:15:18
beach
nij-: The handler must be looked up in the dynamic environment, i.e., the call stack. And then, it must be possible to manipulated like any other value, like (funcall (find-handler ...) ...) which requires a first-class function.
4:16:43
beach
nij-: An entity that is first class is one that can be the value of a variable, can be passed as the argument to a function, and can be returned as the value of a function call.
4:18:57
nij-
That's what I understand. Ah I see.. otherwise you need to refer by name which is not so convenient.
4:20:18
nij-
--- Is there a bug in the examples of this CLHS page? http://www.lispworks.com/documentation/lw70/CLHS/Body/f_invo_1.htm
5:02:49
beach
nij-: The examples have several problems. They are not normative, so I suspect they were not as well scrutinized as the normative parts.
8:35:43
Shinmera
jackdaniel: Does ECL have any functions to convert floats to/from their bit/integer versions? Asking since float-features lacks support for those conversion functions under ECL at the moment.
9:04:08
rendar
i'm creating a little lisp interpreter in python, which supports coroutines and async computation. I was thinking, if i have a function which needs the results of 2 websites, e.g. `(my_fn (get_url a.com) (get_url b.com))` i could run those 2 get_urls function concurrently, in the underlying python.. is this concurrently running a thing in modern lisp?
9:06:42
hayley
The lparallel library would let you do something like (parallel-let ((x (get-url "a.com")) (y (get-url "b.com"))) (use x y)) which is longer, but makes explicit what runs concurrently. _Could_ you run get-url concurrently in your language semantics?
9:07:55
rendar
now, i think i have to explicitly differentiate the function that can return immediately, and the functions that must be awaited, such as get_url
9:09:37
hayley
Perhaps not for get-url specifically, but can't arguments to a function be mutable, and you'd thus have shared state if I did e.g. (let ((x (make-something))) (concurrently (f x) (f x)))?
9:12:42
rendar
it will fire 2 http requests, and will process one when one finished, but that's all happening into one thread, those are coroutines..
9:14:10
hayley
I use Leslie Lamport's definition of "concurrency", where two things happen "concurrently" if one does not strictly occur before or after the other. If one is only processed when the other finished, those tasks do not appear concurrent.
9:15:56
rendar
just work is fired concurrently, and results are grasped concurrently, but everything is happening into 1 single thread
9:18:09
hayley
The issue with shared state is one involving concurrency, not if the tasks actually run in parallel or not.
9:18:53
hayley
(The latter, still, is useful on multi-core computers i.e. most of them, but this is an interpreter written in Python, so, yeah.)
9:19:23
rendar
hayley, well, that 'x' in your example of before could be read/write before/after of one of the get_url() depending on the website time response, for instance