freenode/#lisp - IRC Chatlog
Search
1:34:26
Prof_Birch
Is lisp good for rapid prototyping an application before you are sure of exactly how you want to approach the problem?
1:35:21
Prof_Birch
I am hearing it's good for prototyping in a DSL kind of way, but I wasn't sure if it is actually good for prototyping in a general use of the word
1:37:31
Prof_Birch
I have ADHD, so it can be a bit hard for me to lay out exactly what I intend to do before hand, even if I have a general or somewhat planned idea
1:38:02
Prof_Birch
I *think* lisp could be a good choice for me to lay my ideas out, and play with them to express what I mean before I code it in something like Java
2:10:56
pierpa
unless there's a customer paying you to deliver something in some other language, I mean.
2:14:33
Prof_Birch
Hey, I'm here to ask questions and break stereotypes I read online. So feel free to enlighten me
2:15:27
Prof_Birch
I assume the answer will be yes, since I'm on the lisp channel, but is it really all that? I hear whispers online, but nobody I know uses it
2:17:46
akkad
yeah, it's a language. if you put the features into context of when they were made. it's magial
2:20:22
akkad
if you mean as a family of languages. CL might be seen as a little more strictly limited wrt innovation.
2:20:51
Prof_Birch
I don't know enough about Lisp to pick a flavor, and elisp didn't seem suited for general programming
2:21:09
Prof_Birch
I figured learning the basic syntax would be the place to start, and CL was the dominant one as far as I could tell
2:21:25
akkad
don't feel like you need to limit yourself. once you get a lisp down, the rest are much easier to grok typically.
2:22:08
beginner_supreme
I sort of like to look at (and validate my desire to study CL) as being a very very fast python with the freedom to extend it as I want/need.
2:22:24
Prof_Birch
I'm just searching for a language that can help me build programs that are just on the edge of my mind, I can't seem to pin it down but I'll know what it is when I see it
2:23:27
aeth
Prof_Birch: SBCL is gradually typed, if you don't mind relying on the not-entirely-portable behavior of type declarations.
2:23:46
Prof_Birch
I'm not worried about portable. and I barely get paid at all. I'm a bit of a hobby programmer
2:24:37
beginner_supreme
Someone in the #clnoobs room showed me how type declarations are not even necessary most of the time. Compilers like SBCL have great type inference.
2:25:20
aeth
beginner_supreme: There are two places where the lack of type inference will hurt your performance: numbers and sequences. This is because there's a kind of generic function (but not defgeneric generic) for numbers and sequences, like + and map
2:27:06
beginner_supreme
Right, but for things like using (elt) instead of (aref) - these are inconsequential as far as I'm aware. elt would just be expanded to an aref if the type is inferred to be an array
2:27:39
aeth
But it probably won't infer the type is an array if you use sequence operations on it and the array is passed in as a variable instead of created within the same function
2:28:16
aeth
Arrays have the added overhead of bounds checking when the dimensions are unknown, but the dimensions can be encoded within the type.
2:32:08
beginner_supreme
I had that internal debate before too, but decided to stick to CL. It's just easier to work with in my opinion
2:32:56
aeth
The problem with Haskell is that you have to be inventive to keep purity. CL doesn't care about mutability so you can take your mutable algorithms and data structures with you into CL.
2:33:09
Prof_Birch
I know, the problem is I don't always know what I am thinking clearly (Hence ADHD)
2:33:34
beginner_supreme
Haskell requires placing all your mutability and imperative style into constructs called Monads, which are a bit difficult for most to grok
2:33:52
Prof_Birch
that I can put down what I am thinking, and tinker. Java and python didn't do that so well. It always ended up with me rewriting my program and making no progress
2:34:26
Prof_Birch
I like the idea of perl, but I would also like to go back and read what I wrote at some point
2:35:37
beginner_supreme
In CL, when you are writing something in a spaghetti or repetitive way, you might realize "Oh this... I can write a macro for this... to keep the code size down... and focused on what I want to write."
4:33:18
beach
jeosol: It is not reserved for Europeans. We have many participants from all over the world. US in particular, but also Japan and some other places.
4:34:48
jeosol
I have finished my challenge code so I am fully in invested in CL for now. I am planning to start presenting my work soon.
4:34:50
beach
Usually, you can wait until much later, but this time ELS is held jointly with the <programming> conference, so there will be many people who need rooms.
4:36:04
jeosol
I would never have been able to do it without CL. For example, the macro facility was exception and of CLOS which my codes uses a lot.
4:36:47
jeosol
also look forward to get jobs where I can hack CL. I almost got one with some US defense guys, but security clearance issues.
4:37:03
jeosol
thanks for the link. I will look it up and start making plans. These things go by quickly.
4:37:37
jeosol
But then, I will need EU work visa right? I will be in Barcelona for the Challenge conference, so I may try to see if I can visit them.
4:42:03
rme
I understand that Spain can be rather troublesome, but why not talk to RavenPack anyway?
4:42:09
beach
jeosol: I know of at least 5 US-of-Asians who, once installed in the EU never looked back.
4:43:59
beach
rme: Oh? That would be very surprising. Sure, if you are an unskilled person from Africa, I can imagine a few obstacles, but if you have an offer of a skilled job, I don't see the problem. But maybe you know better than I do.
4:47:30
jeosol
I normally joke that "blessed is S/he who hacks lisp for a living ...". There are a few companies there have adverstise and look for CL as part of their stack, but then they want other languages too JS, Java,...
4:47:55
jeosol
that's good actually. I will start developing some contact. Conference is in September
4:48:17
aeth
jeosol: If you have European ancestors you might actually be able to get European citizenship. Depends on the country. Italy is the easiest.
4:48:56
rme
beach: I can't quite make a move to Bordeaux (or anywhere in France) work out just on my own. I'm talking to some potential employers, though.
4:50:51
beach
jeosol: The great advantage of going to ELS is that you will be able to put a face on many of the #lisp participants.
4:51:13
aeth
Personally, I think I could get Italian (1/4) or Hungarian (1/16??) citizenship if I tried. For the latter I would have to learn Hungarian, though.
4:55:26
jeosol
beach: yes, good point. Nothing like meeting people and discussing in person and finding common grounds and collaborative projects.
4:56:24
jeosol
I did plan to come this here, write my paper on building a very large project/application with CL.
4:57:17
jeosol
when I started, my code was barely running stable, issues, but after questions here and comp.lang.lisp, it is running smoothly, and runs for days and weeks without issues now.
4:58:31
jeosol
beach: on the conference bit, I think the collaboration is something that would be useful. For example, I have talked about picking up CLML for machine learning/AI but waiting to sort out the licence issues and get a go-ahead
5:01:05
aeth
I cannot easily break 10k. Every time it looks like I might get close, a new macro pops up.
5:01:59
jeosol
There are a few reasons for the productivity, lisp being one of them. I type fast, and because I can reach any file and function from within emacs, all those things help. Also, my code is essentially a document because I use long
5:02:49
jeosol
variable names which my be hard for many. The variable names and function names convey meanings. So with the code reading like a document, it was much easier to write along.
5:04:01
jeosol
I won't recommend writing it the way I did, I was also writing to code as a hobby (April 2016), then a challenge came up Feb 2017, so I decided to make the code be able to solve that challenge. Deadling was a month ago.
5:05:01
jeosol
But I must say, I have enjoyed working on the project and can't imagine if I can get to code CL and get paid for it. hmmm
5:06:46
jeosol
but one thing I would say is that, my code quality gets better with time. When I learnt the basic things I needed, I just started writing and replacing code as I go forward and using better idioms, or techniques to improve efficiency. But my focus was
5:09:18
jeosol
I would say it is a platform because the code base contains optimization engine, statistics, proxies. So application area is for optimization problems where scare resource have to be allocated to maximize some objective function.
5:15:05
jeosol
A presentation may be able to help explain things better. Hence beach suggestion to come to ELS
5:16:43
jeosol
I was hoping to reproduce some examples using CLML library and make changes to the code if necessary. I am trying to resolve with the library owners to avoid any issues.
5:19:31
shachaf
Is there something in Lisp which is like progn, but where each statement can be a sort of macro that acts on the rest of the block?
5:21:03
shachaf
I'm thinking about a language feature for a different language. But I thought maybe Lisp people would've thought about something like this.
5:21:22
makomo
what does it mean "but where each statement ... acts on the rest of the block" though
5:22:05
makomo
maybe something along the lines of this, but i don't know if that's what you're looking for: https://fare.livejournal.com/189741.html
5:22:22
shachaf
I guess it would mean that (progn (a) (b) (c)) can turn into something like (a '(progn (b) (c))) if a is a particular type of macro.
5:23:55
shachaf
OK, that looks similar. Though I'm thinking that in the common case the things in the progn block are just evaluated as regular expressions.
5:25:15
makomo
i'm not sure if it's possible to do what you want, i.e. for A to act on the whole progn
5:25:42
makomo
you could for example invent your own PROGN-like thing that will be a macro that will codewalk the body and looks for A's :D
5:26:12
shachaf
Right, that's what I was thinking. I was wondering whether something like that existed.
5:26:51
shachaf
It's also similar to https://common-lisp.net/project/cl-monad-macros/monad-macros.htm (or Haskell's do notation)
5:28:02
shachaf
And I suppose also to continuation-passing style, or first-class continuations in languages that have them.
5:29:38
makomo
shachaf: you might want to look at the implementation of contiuations in On Lisp. i don't know how complete it is, but it could come in handy as an example
5:32:09
shachaf
But continuations are opaque functions and I'm curious about applications that do more syntactical macro-style things.
5:39:30
aeth
You could try looking at various utility libraries to see if any do something similar to what you're talking about
5:39:58
shachaf
(And also I'm thinking about this in the context of some sort of low-level language that doesn't have closures.)
5:53:28
fiddlerwoaroof
shachaf: you might look at f-exprs in the kernel language, among other places
6:35:52
MichaelRaskin
shachaf: I think this is sometimes implemented under names like nest or something like that
8:06:43
fiddlerwoaroof
You need to use the git version of slime, because emacs changed the signatures of some functions
8:33:20
xificurC
I'm reading LOL and gained a yet again little bit better understanding of lexical and dynamic bindings and closures. However I'm failing to understand one example the author gives: he says this doesn't create a new lexical closure: (let ((temp-special 'whatever)) (lambda () temp-special)). Note that temp-special was defvar'd before, i.e. made speci
8:34:19
xificurC
so if it doesn't create a lexical closure I would expect this to clobber the variable: (defvar *x* 1) (loop for i from 1 to 10000 do (sb-thread:make-thread (lambda () (let ((*x* 10)) (incf *x*)))))
8:34:32
jmercouris
I'm having a weird error says "COMPILE-FILE-ERROR while coming "cffi-toolchain" https://gist.github.com/284f9800691c84683301e12d68256b06
8:36:58
jmercouris
do not try to imagine what is happening in machine code, that will make you wrong a lot
8:37:24
xificurC
jmercouris: yes I read that and the sentence is ambiguous (to me at least). A special declaration in the let's scope or in toplevel?
8:39:27
jmercouris
and if you try to guess what it is doing, you are only going to confuse yourself and cause problems when you try to optimize "cleverly"
8:40:30
xificurC
jmercouris: ok forget the machine code then. In the example above, is the leted *x* dynamic or lexical?
8:42:46
White_Flame
the standard says that dynamic bindings are scoped to a function and everything it calls, which is necessarily thread-local on all implementations I've seen
8:43:46
beach
xificurC: It doesn't clobber the global value of the variable, because you bind it before incrementing it.
8:44:53
White_Flame
it's a compile-time decision on whether or not the variable is declared special, that determines what LET does
8:45:32
beach
xificurC: The tradition is also that each thread gets its own binding, and that they share the global value.
8:46:19
White_Flame
they can also be done via (defun foo (*x*) ...) which also establishes a dynamic binding for *x* using what's passed in
8:46:46
beach
xificurC: (defparameter *x* 0) (defun ff () (print *x*)) (defun gg () (let ((*x* 1)) (ff)))
8:49:03
White_Flame
a common machine code implementation is that when looking up the value of a special variable, first it checks the threadlocal table. If there's no binding there, it checks the global symbol-value of the symbol
8:50:21
White_Flame
and again, that choice is compile-time, depending on whether or not the referred variable is/was declared special or not
8:51:24
xificurC
ok, so in (defparameter *x* 0) (let ((*x* 100)) CODE-HERE) everyone using *x* at runtime will see the leted value, which is what dynamic binding is all about. The threading version works because specials can also be in a thread-local storage
8:52:48
xificurC
I still don't understand the sentence "the standard says that dynamic bindings are scoped to a function and everything it calls" though
8:53:14
White_Flame
(progn (let ((*x* 100)) ...*x* is seen as 100 here and in called functions...) ...*x* is back to normal)
8:55:41
White_Flame
(let ((*print-circle* nil)) (format t ...)) will cause FORMAT to see a new value of *print-circle*, for instance, but any other thread won't, nor will anything in the current thread outside the LET
8:56:08
White_Flame
specifically, outside the dynamic extend of LET, ie when it's active on the call stack and hasn't exited yet
8:57:34
xificurC
White_Flame: ah so I can imagine "if it's not on your call stack you can't see it"?
8:58:18
White_Flame
if a special binding has entered, then everything in the thread will see that new binding (unless another inner binding overrode it)
9:01:08
beach
xificurC: I know of no Common Lisp implementation that does it differently with respect to threads. Without threads, it is standardized behavior.
9:02:09
xificurC
beach: what other implications are there from this requirement? You're saying threads aren't mentioned but I don't see what else benefits from this behavior
9:02:47
beach
xificurC: As White_Flame pointed out, you can alter the behavior of things like FORMAT without passing an argument to them.
9:03:21
xificurC
beach: yes but if the binding wasn't thread-local it would still apply the same way
9:03:45
beach
xificurC: yes, but if the binding were a lexical binding, it would not behave that way.
9:03:59
White_Flame
" The effect of binding a dynamic variable is to create a new binding to which all references to that dynamic variable in any program refer for the duration of the evaluation of the form that creates the dynamic binding. "
9:04:51
xificurC
beach: yes that's the point of dynamic binding, I get that. I'm asking what other benefits are there from the fact that the binding is connected to the stack
9:05:46
xificurC
if it was altered in a global table that is shared across threads you would still have the same behavior with the FORMAT example
9:07:10
xificurC
White_Flame: so the standard doesn't mention threads but the requirements it imposes necessitate thread locality. And I don't see what other benefits are there from those requirements, i.e. why aren't threads mentioned
9:07:49
White_Flame
and threads aren't mentioned because they basically weren't invented at the time that the tech they were consolidating was created.
9:07:57
beach
xificurC: You are right. There are no other benefits to special variables than the fact that they allow dynamic bindings and that this is a unique property of Common Lisp.
9:08:37
beach
xificurC: A few minutes ago, you did not understand the mechanism of dynamic binding, so it is natural that we try to check that you now do.
9:09:19
White_Flame
the main benefit of special variables is side-band context, either global or scoped
9:09:25
xificurC
beach: I imagined it to work *not* thread safe, e.g. with a shared global table. But my test in sbcl proved me wrong
9:10:18
beach
xificurC: You also imagined something else, i.e. that (let ((*x* 1)) (incf x)) would alter the global value of *x*, which is not the case.
9:11:26
beach
So we are just making sure that you understand the benefits of special variables, even when there are no threads involved.
9:11:47
xificurC
I just imagined it to be something like (setf tmp *x*) (setf *x* 1) (incf *x*) (setf *x* tmp)
9:12:30
White_Flame
or (let ((old-x *x*)) (setf *x* 1) (incf *x*) (setf *x* old-x)) to be a little more idiomatic
9:12:44
shka
xificurC: essentially, each new binding to special variable shadows old binding for everything that comes after it on stack
9:12:58
beach
xificurC: Yes, and that won't work if there is an error and a non-local transfer between the save and restore.
9:13:21
beach
xificurC: Dynamic bindings are guaranteed to be undone in case of a non-local transfer of control out of the dynamic scope.
9:14:34
xificurC
I already understood and used the benefits of specials. I didn't understand why a let over it is thread safe.
9:14:56
xificurC
You guys said the standard requires it to behave in a way which is basically always implemented in a thread safe manner.
9:15:19
White_Flame
because "for the duration of the evaluation of the form that creates the dynamic binding" is interpreted that way
9:16:19
White_Flame
and scopes happen to be thread-local, by interpretation of that "during" description
9:19:17
xificurC
I was thinking "if I were to implement CL and read that line would the thread-safetiness be clear to me from that sentence?"
9:19:57
beach
xificurC: It's the only sane way of doing it. Otherwise, a thread could not count on the value of its own variables.
9:20:09
White_Flame
because the actual "time during which ... a binding ... is defined" is technically global, but unpredictable outside a thread
9:21:17
White_Flame
I think LOL is an interesting exercise, but I don't like the data-hiding of the way it uses closures
9:22:02
xificurC
beach: yes but you really have to think of threads to get a surprising effect from it when keeping it in a global table
9:22:53
White_Flame
a dynamic binding in a single threaded environment has well-defined boundaries. a global-trampling dynamic binding in a multithreaded environment loses those well-defined boundaries, while thread-local retains them
9:23:18
White_Flame
yes, but it also means you can't change them at runtime easily, which is very non-lispy
9:24:20
White_Flame
ie, if you create an object whose implementations are lambdas floating in hidden closure variables, then redefine the functions in the source code, the existing objects will nto be updated. If they were plain DEFUNs or DEFMETHODs, then the source code could change the behavior dynamically
9:24:30
beach
xificurC: In many respects, standard objects are strictly more general that closures, at least for SICP-style data hiding.
9:25:36
beach
xificurC: Since CLOS is so powerful, it is usually better to use standard objects than closures for data hiding.
9:26:41
jmercouris
beach: that sounds like a terrible idea, but I haven't done it, so I can't be sure
9:26:55
White_Flame
bad for debugging & development, in particular. You should still use well-defined interfaces and not just directly trample data, but explicitly barring ALL access is counterproductive in an interactive environment
9:28:24
White_Flame
having to pollute all your objects with logging functions, for instance, is a massive ugly nuisance, as opposed to letting your logger peek in as deeply as it needs to
9:28:59
jmercouris
even in OOP languages that have private members, they usually allow introspection and reflection
9:29:06
xificurC
but the world is a hostile place and the devs will try to kill your objects, you have to encapsulate!!! /s
9:32:46
xificurC
I always imagine the CL mascot from land of lisp just watching the programmers, year after year, implementing half-assed versions of what already exists for 50 years, scratching its head thinking just wtf is going on in other people's minds
9:34:00
makomo
White_Flame: i see your point about LoL. how would you for example "solve" the following problem: i had an object that you could (un)register callbacks with, and it would call these functions when a particular thing happened. the callbacks were taken as function objects.
9:34:46
makomo
White_Flame: now, when you pass in a function into this registration, such as #'SOMETHING, and later on redefine SOMETHING, you're still left with the old version of SOMETHING attached to your object
9:35:05
White_Flame
makomo: but I woudl probably define a struct or defvar to hold it (depending on scope) instead of just closuring it
9:35:52
makomo
White_Flame: since i wanted the benefit of interactivity/redefinition, i went with storing a symbol and then looking up it's symbol-function :D
9:35:54
White_Flame
makomo: right, because that's a _configured data object_, not just default class-style code
9:36:18
White_Flame
and yeah, symbols are the right way to do it if you want global redefinition of all instances to be possible
9:36:23
makomo
White_Flame: hm right, so it's not really a problem then, because you explictily did it that way
9:37:26
makomo
but i think LoL is a great book. it's an awesome lesson in macrology and a good brain strecher :-)
9:39:05
xificurC
makomo: I did a few years back but I didn't understand all of it. Reading it now (1/3 in maybe) and getting more from it
9:41:23
xificurC
I remember when I was reading it the first time someone here complained that defmacro! isn't safe when called in a nested fashion
9:42:34
makomo
xificurC: for example, sbcl processes the comma inside a backquote as a STRUCT i think
9:43:08
makomo
so codewalking the thing will give you a struct which is an atom (and also not a symbol)
9:44:56
makomo
the project aims towards a portable codewalker, but "portable" in the sense of using heuristics/specializing for different implementations, i think
9:59:26
jmercouris
I have no idea which system is defining this package, so I can't imagine how to fix it
10:02:13
jmercouris
when dropped into the restarts screen, is it possible to execute any arbitrary lisp in the image?
10:02:38
makomo
jmercouris: you can execute lisp code within any of the frames. press "e" in the slime window
10:07:41
TMA
jmercouris: but (find-package '#:static-vectors) returns #<PACKAGE "STATIC-VECTORS"> after (ql:quickload "static-vectors")
10:24:04
TMA
jmercouris: there is a problem with "static-vectors" on sbcl/freebsd then. I cannot help you further, I do not use freebsd. Sorry.
10:34:47
makomo
jmercouris: this seems to be the code https://github.com/cffi/cffi/blob/master/toolchain/bundle.lisp#L213
10:40:18
makomo
my idea was that the errors you got are because OS-COND wasn't defined as a macro or something
10:45:12
jackdaniel
downlaod prefered asdf (if you use sources, make will produce asdf.lisp file), and call (load (compile-file "asdf.lisp")) before quicklisp/setup.lisp is called
10:46:20
jackdaniel
QL first checks, if ASDF is already loaded (if so, it does nothing), after that it calls (require 'asdf) (that gives you asdf bundled with implementation). if this yields nothing (errors that module is not found), it loads asdf 2.26 which is bundled with quicklisp as a fallback
10:47:15
shka
is it sufficient to wrap defclass in optimize for safety 3 in order to ensure that i won't get the wrong type?
10:49:54
White_Flame
I would think it is highly dependent on when/where CLOS dispatch is recompiled, and if slot accessors are inlined somehow
10:52:11
jackdaniel
if you really want to load custom ASDF - I think yes. but maybe I have confused things (as Xach's veto would suggest)
10:52:37
jackdaniel
shka: I think he was referring to my sloppy explanation of ql algorithm of ensuring ASDF
10:53:43
jmercouris
jackdaniel: I was under the impression that sbcl --load quicklisp.lisp will already handle this?
10:54:23
jackdaniel
because QL calls require for asdf module, which is bunded with the implementation (if no asdf is loaded beforehand)
10:56:13
jackdaniel
I have a trust issues with ASDF upgrade mechanism, but in principle you should be able to load ASDF on top of existing ASDF
10:56:29
jackdaniel
because Quicklisp does call require ASDF for you (as I have pointed out *twice* already)
11:54:41
shka
jmercouris: when i started programming in C++ i had this very old machine with athlon 3200+ and 2GB of RAM