freenode/#lisp - IRC Chatlog
Search
17:23:53
samlamamma
You know, Lisp is really the ultimate CRUD-application builder. Just provide the definition of your data and Lisp can generate all the code to transfer it between your app, the database, the protobuf layer, what have you.
18:06:29
beach
ACTION learned a new acronym today: https://en.wikipedia.org/wiki/Create,_read,_update_and_delete
18:13:28
beach
Databases seem to imply copying, and copying is contrary to the semantics of Common Lisp, so I am trying to figure out ways of managing data without copying it.
18:21:03
shka_
beach: yeah, you see this is stuff used to build every single webapp, and since it is used to build every single webapp efforts has been made to make it painless even though it still sucks
18:23:49
shka_
at this point potential for the change is minimal, everybody wants to have database in a separate docker etc.
18:29:08
asarch
And when you write your own implementation, how do you know if it is 100% compatible with the standard?
18:29:40
jackdaniel
asarch: there are ansi-tests written by pfdietz, they are very useful when looking for non-conformities
18:40:38
p_l
beach: have you seen GemStone/S? While it's proprietary, the source should be interrogatable at runtime, and it's based about object persistence at language level, iirc
19:33:32
vms14
It's too soon for me to have changed, but I start to see how you change your mind gradually while learning lisp
19:35:04
vms14
I guess the first step is realizing everything is made of abstractions and the way you don't care about non-yet-defined things. But I cannot explain it well since I'm only having a little taste of common lisp
19:59:23
aeth
vms14: It's kind of the opposite of abstractions here. Almost every other language offers heavily abstracted syntax.
20:00:56
aeth
for foo[42] instead of (aref foo 42) and saving maybe half a second of typing and a few characters, you lose a lot, particularly the ability to conveniently define your own syntactic abstractions
20:02:18
aeth
Well, I mean, many languages are stuck with (aref (aref foo 42) 15) instead of (aref foo 42 15) because they're stuck with foo[42][15] instead of having a true foo[42,15] or whatever because that would require new syntax
20:02:28
aeth
So even in my simple example what seems harder winds up being more powerful because it's extensible
20:03:02
vms14
lisp not only lets me build, it also has a lot of builtin functions prepared just to create abstraction
20:04:51
vms14
I mean, since the first time I saw lisp in lisp books or tutorials, I saw lispers are making the pieces more little than what I usually see
20:06:24
vms14
in lisp one function also does one thing ( if the programmer wants ) but it does that thing using a lot of functions which usually are not builtin functions, but created by the programmer
20:07:56
aeth
You can write Lisp in any language. I certainly layer my trivial functions Lisp-style even in C
20:08:38
aeth
No, I mean layers of functions (though higher order functions is, of course, a Lisp feature)
20:08:41
aeth
You can e.g. do most of the input error checking in one function and then a function unencumbered by that noise that just implements the logic.
20:09:49
vms14
doing noob stuff like creating functions for declare a variable and sum that variable
20:09:51
aeth
You *can* do syntactic abstraction in C but don't. Lisp has many advantages over C there. Yes, at that point, just transpile and use s-expressions as your actual source.
20:11:06
vms14
but I guess I'll start with just the (read) function which gives me symbols and start parsing symbols
20:11:38
vms14
I need to learn how to parse, and I'll cry when things go more complicated, but it's just for fun and I'll learn by the way
20:12:12
aeth
vms14: oh please don't do that (adding implicit ()s around foo to make (foo) and then calling it), that's basically as safe as calling eval() in other languages
20:13:37
vms14
I'll start reading symbols and converting symbols to string when needed with (string symb)
20:41:26
vms14
I'd like to use common lisp as a parser sooner or later, so while I'm a noob I try to at least do noob stuff
21:51:29
makomo
just when i thought i ran into an ""issue"" with its property resolvers, edi has already thought of it https://edicl.github.io/cl-ppcre/#*property-resolver*
21:53:22
makomo
my usage was (let ((cl-ppcre:*property-resolver* ...)) (ppcre:scan <string> <string>))
21:55:38
makomo
also, a very cool late night regex trick: splitting using zero-width positive lookaheads -- use the regex "(?=<delimiter>)"
21:57:17
makomo
the cool thing is that you can use literally any regex for <delimiter>, including stuff like character properties. that way you can split on uppercase letters and such, without removing them
22:46:00
didi
What is the rationale for REDUCE calling FUNCTION with no arguments? I understand the situation (no initial value and empty sequence), but I've never encountered a situation where I wanted it to happen.
22:48:12
pjb
(defun cons* (&optional (a nil ap) d) (if ap (cons a d) '())) (reduce (function cons*) '(1 2 3 4)) #| --> (((1 . 2) . 3) . 4) |#
22:49:14
pjb
(defun cons* (&optional (a nil ap) d) (if ap (cons a d) 'ha)) (reduce (function cons*) '()) #| --> ha |#
22:49:56
pjb
didi: basically, the function without argument returns the neutral element for the operation, so that reduce can return something meaningful when you call it with an empty list and no :initial-value argument.
22:50:37
didi
pjb: I usually put the "neutral element" on :INITIAL-VALUE. Maybe I should rethink it.
22:50:40
pjb
Unfortunately, the function is not called with a singleton: (reduce (function cons*) '(1)) #| --> 1 |#
22:51:57
pjb
didi: as you can see, there's a semantic difference between the neutral element and :initial-value.
22:52:36
pjb
didi: yes. But the same differences exist with them: (reduce '+ '(0 0) :initial-value 42) #| --> 42 |# (reduce '+ '()) #| --> 0 |#
22:54:04
pjb
Then you can have any function and any list, and the function can take 2 mandatory arguments.
23:00:40
didi
I guess by always passing the neutral element to :initial-value I betray the black box that should be FUNCTION.
23:02:39
pjb
reduce should call (funcall f) always (funcall f (first list) (funcall f initial-value (funcall f()))) …
2:23:32
moldybits
is it possible for a method to specialize on two different types for the same argument? ie, that it has to be a subtype of both types specified, to be considered a match.
2:30:49
Bike
ofc you can just define a new class that has both as superclasses, and have your actual class be a subclass of that one
2:31:30
White_Flame
note to self: do not recompile with unfinished code (defparameter *tags* (loop ))
2:33:23
aeth
moldybits: If you must dispatch on types instead of classes, you can use a library like specialization-store, but this dispatch will be slower than even method dispatch is unless it can be inlined. https://github.com/markcox80/specialization-store/
2:33:58
aeth
There might be a few other ways to do it, other than the obvious manual way of having a function with a TYPECASE in it.
2:34:28
White_Flame
or the obvious manual way of having 2 defmethods which call the same shared function
2:36:24
aeth
White_Flame: That's an interesting idea for how to implement this behavior in a define-method extension to defmethod. Perhaps inlining that function.
2:36:38
aeth
White_Flame: Of course, perhaps the proper way to do define-method is to heavily MOP it.
2:44:10
moldybits
the method is object-open and the argument is an instance of door inhereting from object, openable-mixin, and lockable-mixin
2:46:49
moldybits
the problem is when something is lockable but not openable. the object-open method specializing on lockable-mixin will still match
3:06:51
moldybits
i probably shouldn't have lockable and openable be mixins. they could go into a list as properties.
3:07:48
moldybits
either i could have a lock in a list of properties, or i could have a locked-p slot, and check for the existence of that slot. hm.
3:07:50
aeth
moldybits: wouldn't (subtypep (type-of o) 'lockable-mixin) also work like this? (typep o 'lockable-mixin)
3:08:35
aeth
If that works (not sure) then you can just use typecase, and even though that will nest in more conditions, it could potentially be more efficient.
3:11:40
moldybits
i'm slowly reading through Keene's OOP in CL book, and i wanted to try applying CLOS to a text game.
3:11:46
aeth
moldybits: I wouldn't use slot-value... accessors are a better in just about every way afaik, including performance, surprisingly.
3:13:38
moldybits
hm. there are so many ways of implementing this, and i'm having trouble weighing them against each other.
3:14:17
aeth
moldybits: If you're always going to call SAY, I would have one SAY at the bottom and build it at the top. You can do this with multiple-value-binds and values. So (multiple-value-bind (status text) ...) and e.g. inside the conditional (values :success "opened ~A")
3:15:14
aeth
Then you'd just have one (say status text o) at the bottom and the flow is a lot cleaner
3:15:37
aeth
Combine that with with-accessors instead of slot-value and the function should be a lot more readable imo
3:17:09
aeth
Using lots of internal bindings also has the advantage that you can easily spin off helper functions if the function grows too big