freenode/lisp - IRC Chatlog
Search
8:18:21
amazoniantoad
Hey guys. I'm trying to take two columns and generate a matrix from their multiplication. Could anyone show me how to do this? Currently I'm trying to do (elt (elt matrix i) j) and using setf to set the value. But instead of getting unique values for every cell I wind up getting the exact same row in the matrix
8:19:04
no-defun-allowed
Why are you using an array of arrays? Common Lisp has n-dimensional arrays.
8:19:34
no-defun-allowed
And are you talking about matrix multiplication, element-wise multiplication, or...?
8:21:32
no-defun-allowed
How do you get a 2D array from two 1D arrays? Something like O_i,j = M_i × N_j?
8:24:08
no-defun-allowed
Well, to make a 2 dimensional array, you can use (make-array (list columns rows)), and then (setf (aref <array> column row) value) to set an element of that array.
8:27:26
no-defun-allowed
(Using Petalisp, you could write (defun cross-multiply (a b) (petalisp:α #'* (petalisp:reshape a (petalisp:τ (i) (i 0))) (petalisp:reshape b (petalisp:τ (j) (0 j))))). I don't think Common Lisp is very nice for doing n-dimensional array work without some helper functions.)
8:29:14
phoe
I don't think amazoniantoad is a possible client for petalisp if he's still working on getting the basics of 2D arrays done - maybe in a few months, but not yet
8:29:45
no-defun-allowed
Writing a step between a JIT-compiling parallel array manipulation DSL and using big loops of (setf aref) is left to the reader.
8:46:08
no-defun-allowed
amazoniantoad: "element-wise" would probably refer to O_i = M_i + N_i, if I'm not mistaken.
8:56:37
pjb
Well, you can also use (map 'vector (lambda (x) (map 'vector (lambda (y) (* x y)) v2)) v1) which should be more efficient allocating temp storage, but still O(m*n) temp space.
10:13:30
flip214
Can a compiler macro (or normal macro) get the form(s) it's embedded in? SBCL only would work for that use case.
10:15:48
phoe
flip214: I don't think so. The only thing available is the environment, and that doesn't contain everything.
10:18:47
adlai
flip214: "The value of - is the form that is currently being evaluated by the Lisp read-eval-print loop." (obviously, doesn't work in files)
10:24:26
flip214
I've got a function that asks the user a question - and I'd like to determine whether the outer form wants a string, boolean, or number result
10:24:47
pjb
flip214: it cannot, and this is for the best. This is the best feature of lisp macros, not to be able to know anything about the outer form. This is what makes them secure!
10:25:41
pjb
flip214: however, there is macrolet (and symbol-macrolet), which can be used in the EXPANSION of an outer macro. (and also flet and labels).
10:26:32
flip214
pjb: yeah, and compiler-let, and similar stuff. I'm just wondering whether there's an easier way - #'<= in the outer form requires a number, string= a string, etc.
10:26:44
pjb
flip214: this let you design an outer macro, in which you can have access to a macro. The outer macro can arrange to give the information needed by the inner macro, even if comes from forms outside of the inner macro (but inside the outer macro, of course).
10:27:48
pjb
flip214: that said you are not allowed to shadow the fbinding of symbols in the CL package, or defining compiler-macros on them. So you have two ther reason why you won't be able to do that for <= or string=.
10:30:02
pjb
flip214: now, I don't think there's any guarantee about the environments for macro-expansion and compiler-macro expansion. I don't think you could conformingly pass information from a macro to a compiler-macro. This would have to be checked in the CLHS.
10:30:41
pjb
flip214: but once you have a wrapper macro, you don't really need compiler-macro, and this would allow you to do stuff on forms using symbols in the CL package as operators.
10:32:20
phoe
flip214: the outer form should pass the expected input type to the function, that's the cleanest way I can think of
10:34:59
flip214
phoe: Yeah, that's what I thought, too... I'd just like to avoid having my own code-walker, there are already too many of them ;/
10:35:41
flip214
I hoped that I there's an easy way to see what the outer function is - and then the expected type is easy...
10:36:35
phoe
flip214: if you want a true, absolute hack, use DISSECT at runtime to analyze the stack, figure out which function you were called from, and adjust the typecheck accordingly
10:38:56
flip214
LdBeth: most functions have input/output types already declared, and in the worst case I have to annotate the symbol
10:39:20
phoe
flip214: how about the symbol-macro trick then? you set a symbol-macro in the environment with the expected type that you can then macroexpand in the inner macro
11:10:01
flip214
LdBeth: the query function will only occur within AND, OR, <=, STRING=, and similar stuff. It's not general-purpose.
11:52:02
Bike
doing something different based on the return type sounds like a job for static typing. which is to say, might be in the wrong language here
11:55:08
flip214
Bike: why? a GF chooses a method based on the input type as well, so I'd see that as some kind of symmetry
11:56:51
Bike
if it actually chose a method based on the type, you could indeed have it do different things based on the output type. but that information does not necessarily exist in lisp.
12:14:04
Bike
despite the efforts of the best alchemists i can hire, i haven't yet restored my pineal gland to its ancestral power and so cannot read minds
12:14:28
Bike
anyway, things like apply and eval can mess up the concept pretty hard. even just calling something like that at the repl could be a type error for ambiguity
12:15:33
Bike
if you're only using this in specific contexts, you could have those contexts pass along an additional parameter expressing what kind of result is expected, sort of like COERCE
14:09:54
d4ryus
jmercouris: there is video from baggers about loop on youtube :) (search for 'Some Common Lisp Loop Macro Examples')
14:12:35
beach
I think what jmercouris is referring to is the traditional idea that Common Lisp lists behave like abstract data types, which they don't.
14:13:21
jmercouris
like I know what is going on underneath, I've read through all of gentle introduction
14:13:42
beach
jmercouris: At some point, you need concrete data types to implement abstract ones. Common Lisp lists give the tools you need to do abstract stuff.
14:14:24
White_Flame
and since hardware was constrained, you needed to play games with exact storage mechanisms so as not to blow up ram
14:14:40
jmercouris
I get what is going on, but it could just as easily have been written in a smarter way to silently handle the error
14:15:32
White_Flame
then the caller would have to do all sorts of extra work everyt time they wanted to use APPEND
14:16:06
phoe
if you want to avoid type errors, then you'll want a language that's weakly typed by default
14:17:00
Bike
nthcdr is extremely simply defined as doing cdr n times. why complicate it with whatever hiding you want to do?
14:17:13
beach
jmercouris: Again, the language is there to help the programmer find problems in the code. Not to hide them from him/her.
14:17:24
phoe
CL isn't weakly typed unless you decide to (optimize (safety 0)), at which point you can have all the append symbols to lists that you want
14:17:49
phoe
except then the standard says that you get what you want, which is undefined behaviour
14:18:02
Bike
because the system is set up so i can't fix problems because they're fucking invisible
14:18:07
beach
jmercouris: This is stuff you should know since (as I recall) you have been programming professionally for some time. It is not specific to Common Lisp.
14:18:48
jmercouris
still, using a language as a user, doesn't mean you understand the design decisions
14:18:54
Bike
lisp does do some implicit coercion stuff and i'm sometimes negative about that, but it's not as bad as in python or whatever, far as i can tell
14:18:57
beach
jmercouris: You should definitely avoid languages that silently hide problems in application code.
14:19:42
White_Flame
I think "functions should behave consistently and not randomly behave differently while trying to guess at what the user intends" is a reasonable design decision
14:19:46
phoe
so suddenly all code that depends on that must stop depending on that, or, hell, it can return :undefined to
14:21:02
phoe
"result---an object. This will be a list unless the last list was not a list and all preceding lists were null."
14:21:04
jmercouris
Well, there are a lot of people who seem to disagree with you guys, at the very least on accident :-D
14:21:32
White_Flame
that's because they never hit the problems of dealing with attempts at trying to guess user intent
14:21:59
phoe
I prefer my code to fail fast, and type errors in dynamic programming are exactly where programs should fail fast
14:22:29
White_Flame
I mean, by your rationale, "print foo" should work in python3, because it should guess tha tyou're using python 2 style
14:24:00
beach
jmercouris: As an example of making the language help you, it used to be the case that (setq <var> <form>) at the REPL would silently create variable <var> if it did not already exist. That is a terrible idea, because a spelling mistake in a variable will then go unnoticed.
14:25:24
flip214
I got around my type-derivation by building the reverse path for all forms in a global during compilation, so that a compiler-macro can find its current form and look up what's "above" it
14:26:27
beach
jmercouris: He formalized something known as "programming by contract" which is basically the idea of catching errors as soon as possible. Before him, there was a tendency to hide errors.
14:28:16
Bike
flip214: if this is a required part of the semantics you might want to make your function a macro instead
14:28:38
beach
jmercouris: If you want to be an excellent professional developer, these are things you should definitely know about.
14:30:03
flip214
phoe: the reversal is more or less trivial... and the compiler macro has a (&whole form) which is used in a GETHASH then
14:30:16
beach
I know it can be hard to motivate oneself to study these things, especially when one is "lost in a sea of mediocrity" as Dream Theater puts it.
14:31:21
jmercouris
what I like about this channel is that there are some smart people, and it can be motivating to learn from them
14:31:45
jmercouris
that's actually why I started with CL, I wanted to learn more and more thoroughly understand programming
14:31:55
beach
I totally agree. That's why I hang out here too. There are some very smart and some very knowledgeable people here.
14:35:04
Bike
i never really thought about the "design by contract" metaphor but it's pretty good. when you're explaining something to a friend taking shortcuts and being metaphorical and stuff makes sense since they know you and can guess what you mean and so on. with a contract it has to be interpreted by disinterested lawyers and judges, and a computer cares even less than those people
14:38:12
White_Flame
(and obviously doesn't have the intelligence or human empathy to perform it in the first place, even if it did have more data)
14:43:11
beach
Bike: Yes, reading his stuff at the time was an eyeopener for me. Before that, a program that crashed was considered the worst thing that could happen. After his writing, we understood that it was better for a program to crash (soon) rather than silently giving the wrong answer.
14:43:17
phoe
the collective wisdom of the people who talk here is massive and wonderful - I keep on leaving this IRC session more and more knowledgeable and wise even after years of sitting here
14:43:44
phoe
;; and silently hope that I contribute positively to it while I'm learning more Lisp, too
14:44:50
beach
Unix code, for instance, silently gave (gives?) the wrong answers. One of the rules that RMS established for the GNU project was to avoid that.
14:59:54
sjl_
re: setq autocreating variables and making typos unnoticed, this why I find defmethod not requiring a defgeneric to be annoying
15:05:38
beach
Interestingly, in the book "Object-Oriented Programming, The CLOS Perspective", one of the authors states that DEFMETHOD was meant to be the primary interface. I think that phrase shows the age of the book.
15:08:48
beach
If you misspell a function name in DEFUN, and try to call it with the intended name, you get an undefined function error.
15:09:53
beach
With a generic function, you often get the wrong answer, like when you intended to override an existing method specializing to a subclass.
15:11:09
splittist
Some intellisense with completion on defmethod names based on defgenerics already defined, perhaps?
15:11:54
dlowe
(defun foo-frobnicate (foo) ...) (defun bar-fornbicate (bar) ...) seems equally likely and bad.
15:12:59
splittist
dlowe: if you call BAR-FROBNICATE you get an undefined. If you call FROBNICATE with a BAR, anything could happen, depending on your object hierarchy.
16:38:38
vivit
Is there a way to express the initform of a slot in terms of other slots on the object?
16:44:31
vivit
Why do you need to specify the accesible slots when you call that function? Doesn't the class definition itself already have those?
16:46:16
Xach
vivit: if you specify the args, they are available as arguments, you can also work from the values in the instance already (in an :after)
16:46:20
beach
vivit: There is no such thing as an "accessible slot". To refer to a slot, you need to have an existing object. The object does not exist when the initform is evaluated.
16:46:26
jcowan
What are the use cases for returning zero values? I mean, it's an obvious generalization of more ordinary multiple values, but when would it make sense?
16:47:02
Xach
jcowan: some prefer it to returning nil to indicate "this function has no meaningful return value"
16:48:29
jcowan
So the main application is in a context when you don't care what values are returned, then.
16:49:48
Bike
technically it could also be useful in multiple-value-call, but i've never actually seen that
16:52:17
jcowan
I'm arguing against the position that in Lisp, a proper monad implementation should be extended from Haskell's one-arg-one-value functions to n-args-m-values. It makes little sense to pass zero values to the next element in a bind chain.
16:58:11
pjb
jcowan: one place you definitely want to return zero values, is in "commands". Ie. functions designed to be called on the REPL, as command, (they may ouput some text), but for which you don't want any result to be displayed to keep the REPL clean.
16:59:21
pjb
jcowan: other places, is when you don't want to leak an internal data. Since all expressions return some value, there's always a value returned by default from a function. Sometimes, you want to make sure that default value is not returned, so you add a (values) to return nothing.
17:00:20
pjb
jcowan: note that for commands, if you use a function that returns a big data structure, it may take a lot of time and screen space to print it. This is often when you will take the pain to add the (values) call.
17:01:25
Bike
really? i haven't done much haskell programming, but i thought with the semicolon syntax you could write values that weren't bound to anything
17:04:25
jcowan
And yet definers seem to mostly return nil, and they are the very essence of nothing-useful-to-return
17:04:51
jcowan
Bike: If you mean do-syntax, you can, but that all gets unpacked into calls on map and map-append
17:14:18
jcowan
I am just not convinced that generalizing monads to multiple args/values (multiple values are the dual of multiple args, passing more than one value to the continuation) is really worth the headache
17:14:40
jcowan
It is shaky to call anything returning multiple values a function (in the math sense)
17:22:20
jcowan
In Scheme, definitions are not expressions, just syntactic sugar that can only be used at top level or at the start of a let (vel sim.) block.
17:31:42
Bike
well multiple values are really just a kind of implicit tuple type. the sketchy part is more the implicit coercion of one of those tuples to the primary value in almost all contexts