freenode/#lisp - IRC Chatlog
Search
17:56:41
jcowan
Is there a way to make class instances evaluable as opposed to applicable, so that when eval is handed one, it calls some code that gives the value of the instance?
18:01:30
specbot
Self-Evaluating Objects: http://www.lispworks.com/reference/HyperSpec/Body/03_abac.htm
18:01:33
pfdietz
A form that is neither a symbol nor a cons is defined to be a self-evaluating object. Evaluating such an object yields the same object as a result.
18:02:50
pfdietz
One must be careful putting such things into forms, since if they do not have load forms they can't go in binary files.
18:02:55
beach
selwyn: And I can totally see how drmeister made the choice to write a Common Lisp implementation that interoperates with C++ rather than taking on the task of rewriting all the libraries he needs for his molecule design.
18:05:03
pfdietz
One should not, for example, put function objects into forms, but rather use (function <function-name>).
18:05:42
pfdietz
I consider this a defect of the language, and would like things like functions or environments to be able to be put in binary files.
18:07:11
jcowan
Being able to output an arbitrary closure so that it can be applied at the other end, for some value of "end"
18:07:13
beach
Sometimes, one needs to put functions into forms, for example for computing a discriminating function out of effective methods.
18:07:51
beach
jcowan: I don't see that. The lexical environment is long gone by the time you have a closure.
18:08:15
pfdietz
The place this came up for me was in implementing mutation testing for Common Lisp. I want to be able to replace definitions of functions, even if they are in nontrivial lexical environments.
18:09:22
pfdietz
So I want to keep that lexical environment around in some form, so I can plug mutated versions of the function into it.
18:10:11
jcowan
Wrapping your function definition in a hand-created let does the job, but you have to have the information necessary to create that let, hence reification
18:10:44
beach
pfdietz: That idea is kind of contrary to the one of "minimal compilation". You would need to mutate the source before it is minimally compiled.
18:11:55
pfdietz
I lean in this direction: require the ability to query the lexical environment, so one can, when compiling the original function, record the necessary information. Then, when the function is mutated, use that information to synthesize something that behaves like that environment.
18:12:47
pfdietz
For example, if there is a (let ((x ...)) (defun foo ...)), when foo is compiled information would be stored that would let one access x. Accessor and settor thunks.
18:14:03
beach
Trucler is a library that supplies lexical environments in way defined by a complete protocol.
18:14:21
pfdietz
Well,I'm fine with doing it in a single lisp implementation (read: sbcl), but portability could be nice.
18:15:08
beach
As it turns out, heisig has written an SBCL implementation of the protocol, using SBCL native lexical environments.
18:16:50
beach
Cleavir version 2 uses the Trucler protocol, but Cleavir clients can choose to use the reference implementation or an implementation-specific one.
18:17:43
beach
But since SICL is a new implementation, it does not have any historical baggage when it comes to its lexical environments, so it may as well use the reference implementation.
18:21:13
pfdietz
jcowan: wrapping the function in a hand-created let will not do the job, since I want to be able to access the same lexical variables, which may be shared with other functions.
18:21:52
jcowan
Boxes and assignment conversion fix that problem, then all the let variables are immutable.
18:40:14
jcowan
Hmm, does any CL still implement *evalhook*? That would do the job, though at considerable expense.
18:46:28
MichaelRaskin
Well, one can just code-walk the corresponding top-level form, find the function definition and replace it
18:52:55
jcowan
the hook function could identify an evaluable instance, call its evaluator, and return the result.
19:03:44
no_gravity
I don't know much about Lisp. But I was under the impression it can change its own behaviour.
19:05:21
Shinmera
I don't know what that means. In Common Lisp every value has a type. This type may only be known at runtime, so it is dynamically typed, but the type is nevertheless a strong one.
19:06:28
no_gravity
When you say "every value" - is that similar to "every varible" in other languages?
19:10:22
aeth
Idiomatically, we'd use two LETs and it would never rebind the old a. Literally, you can just use a setq or setf.
19:11:21
pfdietz
Unless you've given that variable a type declaration, in which case that would be invalid (and a lisp like SBCL would check for it)
19:11:33
aeth
no_gravity: As long as there wasn't an attached type declaration to the binding, in which case it's implementation specific
19:12:41
aeth
Strong typing afaik means that it's not an autocoercive language like those that try to make sense of: 1 + "hello"
19:13:02
pfdietz
In practice, if you've done something stupidly wrong, like have a program where + is applied to a non-number, an implementation like sbcl will warn you when code would cause a runtime error due to type incompatibility.
19:14:20
Shinmera
I assume he means non-null types and other static reasoning you can do about code if you have static typing and non-null types
19:15:50
Shinmera
no_gravity: Do you have any intention of learning Common Lisp, or are you just trying to use us to not have to read up on basic programming language terminology?
19:19:02
pfdietz
Also, types are richer than in many statically typed languages. For example, the type T holds all values.
19:19:15
no_gravity
pfdietz: Interesting. How do you define a function in lisp? Say this one: function f($name) { echo "Hello $name" }
19:24:10
pfdietz
(some type errors are caught at compile time, in practice, since the compiler typically does some type propagation then and can detect many problems)
19:29:00
jcowan
it's obvious that (+ 1 "foo") is ill-typed, so the compiler can transform it into code that raises an exception
22:31:34
fiddlerwoaroof
Also, when you start doing a bunch of ~* directives, consider ~@* which lets you jump to a specified argument
22:33:02
fiddlerwoaroof
Finally, I wrote a little library that lets you generate format strings in a more readable fashion, at the expense of concision: https://github.com/fiddlerwoaroof/format-string-builder
22:37:48
fiddlerwoaroof
i.e. the numeric argument specifies which argument to jump to, with 0 being the first argument
22:39:31
fiddlerwoaroof
the format invocation should have been: (format t "~1@* ~a ~0@* ~a" :foo :bar)
22:42:10
fiddlerwoaroof
I wonder if beach's sicl could be used for sandboxed lisp execution in minion
22:42:33
fiddlerwoaroof
it'd be cool to be able to ask minion to evaluate a form and print the result
22:47:02
aeth
vms14: Imo, using format for everything, while possible (at least once you mix in "~/package::foo/"), is probably not the best thing as far as readability goes. It's like regexp for everything.
22:47:27
aeth
vms14: Well, at least one format call. Even just breaking things up to 5 or so formats with things like loop mixed in can help with readability
22:48:07
aeth
It works as expected, it's just that you need to always include the package prefix (or else it assumes cl-user, which is weird) and this means you can't use / in package names (which is increasingly common)
22:50:42
fiddlerwoaroof
First you learn to write reader macros and then you learn not to write reader macros :)
22:50:51
aeth
In practice, unless you actually want it configurable with : and @ you basically just do this: (defun foo (stream argument &rest rest) (declare (ignore rest)) ...)
22:51:43
aeth
vms14: I mean, I think we've all been there before with some features of some programming languages, where we learn it, push it to its limits, and then realize that we can't read it the next day, and eventually decide moderation is best, like all things.
22:52:20
aeth
At least to me, it's a lot plainer to use multiple write-foo/prinfoo/format instead of trying to fit everything in one format
22:52:27
fiddlerwoaroof
So, the more you change the syntax with reader macros, the worse your editing experience gets
22:53:30
aeth
vms14: because it's a stream (with a few extras for FORMAT that might not apply to the rest), you can basically mix and match except for (format nil ...) where you're generating a string with the return value (but even there you could concatenate)
22:53:33
fiddlerwoaroof
https://github.com/fiddlerwoaroof/objc-lisp-bridge/blob/master/demo-app.lisp#L93-L99
22:54:20
fiddlerwoaroof
I find these square-brace macros make the ffi part a lot nicer-looking (because it papers over a lot of the ffi noise)
22:54:59
aeth
vms14: Personally, even if I'm 100% using FORMAT, I would keep it to one line, even though one super format string can technically do more, except perhaps for a fairly trivial ~{ ~} usage (but even that I'd mostly use to e.g. turn '(1 2 3) into "1, 2, 3" instead of doing that for lines)
22:55:20
vms14
I'd be happier with M expressions than with S expressions just because {} or [] is faster than write ()
22:57:15
fiddlerwoaroof
It's a really cool idea: when you press shift by itself, it enters a paren, when you push it with another key it inserts a capital
22:58:43
fiddlerwoaroof
This improves every language I write :) and, I use a repl with LINEDIT all the time
22:59:08
fiddlerwoaroof
(and recently, I've been using the Lispworks IDE about 25% of the time I write lisp)
23:02:50
fiddlerwoaroof
Also, Lispwork's application delivery features are extremely well-done and a joy to use
23:10:49
fiddlerwoaroof
I don't know much about NetBSD, but threads work on FreeBSD, so it might be easy to make them work on NetBSD too
3:03:41
matzy_
(note that I gave up on haskell because the installtion process alone on linux was insane)
3:04:26
matzy_
i thought quicklisp was a bit outdated the first few times i used it, but hey, it gets the job done
3:33:36
ahungry
Some would view the lack of version pinning in ql as a problem, but I like that it changes the implicit contract between packagers and users from "Hey, we're going to push BC breaks all the time and just do a major version bump", to something more like "we avoid breaking BC at all costs"
4:03:53
aeth
ahungry: Which would be perfectly fine, but that means that in any higher order function, it should be expected to use keyword arguments with &allow-other-keys so there's no future breakage and there's no real way to enforce that except maybe generating a random nonsense key
4:04:44
aeth
If I'm unclear: if your API expects a function somewhere (even in a macro, not just higher order functions) it should use keywords, and the user should expect to have to use &allow-other-keys so future updates don't break it
4:11:04
aeth
I suppose another alternative is to use one struct/standard-object/list/hash-table/whatever for that