IRC channel logs


back to list of logs

***michaniskin is now known as Guest6263
<nalaginrut>morning guilers~
***cluck` is now known as cluck
<nalaginrut>heya wingo
<wingo>greets nalaginrut :)
<nalaginrut>wingo: I saw someone ask potluck in ML ;-P
<wingo>ooh :)
<wingo>when would it be? 14th or 15th or so?
<nalaginrut>alas~I have to prepare it in 10 days, but I've no idea yet...
<wingo>i have been meaning to write a new bit of photo gallery software, maybe i could get a proto out by then
<wingo>then once the backend and service is done i could get help from someone to make it nice to use
<wingo>with js and such
<nalaginrut>maybe one of the easy way for me is to make guile-lua-rebirth playable, but maybe I should try a game with sly, which is more playable...
*nalaginrut used the wrong word since it's not easy at all...
<jmd>Whats the easiest way to chomp leading/trailing whitespace from a string?
<jmd>Thanks Andy
<jmd>I have a list of strings, all of the form ("key1=value1" "key2=value2" ...)
<jmd>and I want to convert it into a alist.
<jmd>I guess I should just use map ?
<nalaginrut>with string-split ;-)
<nalaginrut>of course, regex-split is cool too
<jmd>Too cool for me!
<jmd>Anyone know of a routine to pretty-print an alist?
<taylanub>jmd: `pp'?
<taylanub>jmd: never mind, thought I'm in #emacs
<taylanub>jmd: find guile-source/modules -name \\*.scm -exec grep pretty-print {} + # ice-9/pretty-print.scm:(define-module (ice-9 pretty-print) ... :)
<wingo>jmd: so i don't know if you know, but if you open the manual in info
<wingo>you can press "i" and then type pretty and hit tab and you get some possibilities
<wingo>or C-s and type pretty-print and keep typing C-s to search through the matches
<wingo>anyway an approach like that will be useful for you i think, many of your questions can be answered that way :)
<jmd>Theres a way of reading a scheme fragment from a file and then excuting it. How do I do it?
<please_help>(eval (read "the-file.scm"))
<mark_weaver>or 'primitive-load'
<jmd>But I need to define some things before it is evaluated.
<jmd>Like, the file contains say "(foo 2)"
<jmd>but foo is not defined in the file, but in the place I'm calling eval/load/primitive-load
<please_help>(eval (read (open "the-file.scm")))
<mark_weaver>please_help: that only handles a single top-level form
<jmd>ERROR: Wrong number of arguments to #<primitive-procedure eval>
<mark_weaver>jmd: 'load' and 'primitive-load' do the loading within (current-module)
<mark_weaver>that too :)
<mark_weaver>jmd: so, arrange to have those things defined in the module that is current when you run 'load' or 'primitive-load'.
<jmd>According to the manual I need to pass (interaction-environment)
<mark_weaver>the second argument to 'eval' is a module to evaluate it in.
<mark_weaver>e.g. (resolve-module '(jmd my-module))
<jmd>Anyway it still thinks foo is undefined.
<mark_weaver>jmd: which suggestion are you trying?
<jmd>I've tried all of them so far.
<jmd>But you didn't put in any suggestion delimiters, so I may have got some mixed up :)
<mark_weaver>I just tried with 'primitive-load' and it works as expected
<mark_weaver>why don't you show me precisely what you did with the 'primitive-load' attempt?
<mark_weaver>I did this at the REPL:
<mark_weaver>(define (foo x) (format #t "~s\\n" x))
<mark_weaver>(primitive-load "blah.scm")
<mark_weaver>where blah.scm contains "(foo 2)"
<jmd> (find-prop my-list (lambda (c) (define (capa x) (assoc-ref c x))
<jmd> (primitive-load "the-file") ))
<taylanub>maybe jmd wants `include'?
<jmd>And it says ERROR: Unbound variable: capa
<mark_weaver>taylanub: probably not, that would be spliced in at compile-time, not run-time.
<mark_weaver>jmd: ah, so you want it to have access to lexical (non-toplevel) variables.
<mark_weaver>'primitive-load' does not have access to non-toplevel variables, only top-level ones in the current module.
<mark_weaver>ditto for 'eval' and 'load'.
<mark_weaver>if you want it to have access to non-toplevel variables, then you need 'local-eval'
<mark_weaver>jmd: do you need to handle a file that contains top-level definitions?
<mark_weaver>also, do you need to handle a file that contains multiple top-level forms?
<mark_weaver>(e.g. where later expressions can refer to definitions made earlier in the same file?
<jmd>Now I'm confused ...
<jmd>What do I pass as the arg to local-eval ?
<mark_weaver>jmd: can you answer my last two questions please?
<mark_weaver>jmd: or if you just want to charge ahead, follow wingo's earlier suggestion :)
<jmd>I'm not sure that I understand your questions.
<mark_weaver>a top-level definition is something like (define bar 5) that's not wrapped with any other parentheses in the file.
<mark_weaver>do you need to be able to handle files that have those?
<mark_weaver>and then later refer to 'bar' ?
<jmd>I don't think so
<jmd>At least not at this stage.
<mark_weaver>okay, thanks. and the second question is: can we assume that there's only one top-level form? what I mean by that is that if there are any parens in the file, then the first open paren in the file has to be matched with the last close paren in the file.
<mark_weaver>sorry, that's not quite right, let me try again.
<mark_weaver>can the file contain more than one expression?
<jmd>No. It will contain only one.
<mark_weaver>okay, that simplifies things.
<mark_weaver>give me a minute.
<mark_weaver>jmd: in the example you pasted here, replace the call to 'primitive-load' with this: (local-eval (call-with-input-file "the-file" read) (the-environment))
<mark_weaver>you'll need to import (ice-9 local-eval)
<mark_weaver>see 'local-eval' and 'the-environment' in the manual for details.
<jmd>Works! (i think)
<mark_weaver>note that (the-environment) will capture more than just 'capa' in your environment. it will also capture 'c' (the lambda argument) and everything outside, including the top-level definitions in the same module.
<mark_weaver>it is essentially as if the contents of the file were put right in place of the 'local-eval' call.
<jmd>That might cause problems later. Is there a way to limit it to the environment of the lamba expression?
<mark_weaver>(assuming that the call to 'the-environment' is directly put in the second argument to 'local-eval')
<mark_weaver>jmd: is the set of definitions available to the imported files always the same?
<mark_weaver>jmd: then forget 'local-eval'. instead, make a module just for evaluating these things.
<jmd>I'll have to read up on how to do that.
<mark_weaver>and do the evaluations within that module
<mark_weaver>you create modules all the time with 'define-module'? there's nothing special about it.
<jmd>I don't think I've ever used that. But I will look it up.
<mark_weaver>jmd: I should clarify
<mark_weaver>when I asked "are they always the same" I meant not only "are the set of identifiers available always the same?", but also "are the values of those bindings always the same?"
<jmd>Well in this example, (define (capa x) (assoc-ref c x)) will always be the same, but c will change
<mark_weaver>there's an issue with top-level modules: currently, they can never be freed
<mark_weaver>jmd: ah, okay, nevermind then. better stick with local-eval here.
<jmd>ok. thanks for your help
<mark_weaver>np, happy hacking!
<mark_weaver>jmd: another thing to beware: that code I gave you reads only the first expression from the file. if there are any more, they will simply be ignored. this could be made more robust in various ways.
<jmd>Ok. I will bear it in mind.
<mark_weaver>jmd: here's how to improve that:
<mark_weaver>(define (read-file-as-one-expression port) `(let () ,@(list-ec (:port x port read) x)))
<mark_weaver>then replace the call to 'read' in my previous suggestion with 'read-file-as-one-expression'
<mark_weaver>you'll need to import (srfi srfi-42) for this
<mark_weaver>then, all of the caveats before go away.
<mark_weaver>it can even handle top-level definitions that will be available only within the file itself.
<mark_weaver>(though all of the definitions, if present, must be before the first non-definition)
<jmd>I ought to mention that I'm using Guile 1.8.7 for this job
<mark_weaver>basically, it wraps the contents of the file within (let () ...) and then evaluates that.
<mark_weaver>oh. ugh.
<mark_weaver>well, nevermind then. I'm not motivated to try to backport this.
<mark_weaver>(it would be a lot uglier)
<mark_weaver>(and guile 1.8 is long unsupported and buggy)
<jmd>It seems like only yesterday that I upgraded from 1.6
<mark_weaver>umm, the last guile 1.8.x release was in 2010
<jmd>And the first?
<mark_weaver>and the first 2.0 release in Feb 2011
<mark_weaver>I guess time goes fast when you're having fun :)
<please_help>So I want to generate indices for iteration in a list of rank K, where each bound in the K dimensions are known. Is the best way to do that the standard flat -> not-flat conversion?
<civodul>Hello Guilers!
<dsmith-w`>Wednesday Greetings, Guilers
***dsmith-w` is now known as dsmith-work
<lloda`>please_help: does array-index-map do what you want? see (help array-index-map)
<lloda`>either that or reshape a vector #(0 1 2 ...)
<lloda`>in guile-ploy that would be either (i. 3 4 5) or (reshape (i. (* 3 4 5)) 3 4 5)
***dje is now known as dje42
<please_help>lloda`: no, I just want to generate the indices, I don't want to set elements of another array (yet).
<please_help>I also can't reshape a vector nor multiply the indices together because that would require being able to generate the indices
<please_help>which is what I'm trying to do now
<please_help>I went with the usual math for now
<please_help>(floor [(x-prev)/(product of rest of reverse of dimensions)])
<mark_weaver>we also have 'floor/' which will be faster
<please_help>nice, thanks
<mark_weaver>sorry, floor-quotient
<mark_weaver>(floor/ returns both the quotient and remainder in a single operation)
<mark_weaver>(and there's also floor-remainder)
<please_help>floor-remainder? why?
<please_help>isn't that just remainder?
<mark_weaver>not quite
<mark_weaver>they do different things in the case of negative integers
<mark_weaver>the manual talks about this.
<mark_weaver>*negative numbers
<mark_weaver>we have a bewildering array of division operators, actually.
*mark_weaver goes afk
<lloda`>so you can use array-index-map! just to generate the indices, kinda
<lloda`>the args are (array-index-map! ra proc)
<please_help>lloda`, that's a huge waste in both memory and processing power though
<lloda`>wait, wait
<lloda`>for ra, you pass a reshaped 0-rank array
<lloda`>that only takes one position, no matter how the array is logically
<wingo>hehe, lloda` you are using "ra" as an abbreviation for array :)
<wingo>took me forever when i was first in the source to figure why that was happening
<wingo>must have been mentally mispronouncing it
<please_help>lloda`, then that doesn't address the problem at all, does it?
<lloda`>wingo: right, it's everywhere, it took me a while to see what that meant...
<please_help>let me rephrase the problem:
<mark_weaver>please_help: SRFI-42 can be used to generate the indices very nicely
<mark_weaver>something like (list-ec (: x 5) (: y 10) (: z 20) (list x y z))
<please_help>DEFINE: (add1 '(0 0 0) '(1 2 3) 1) ;=> '(0 0 1) | (add1 '(0 0 2) '(1 2 3) 1) ;=> '(0 1 0)
<mark_weaver>at least if the rank (K) is a constant
<please_help>yeah, and that's the problem
<please_help>rank is unknown in advance
<mark_weaver>so, given a list of the lengths along each dimension, you want a list of indices?
<mark_weaver>e.g. (2 2 2) => ((0 0 0) (0 0 1) (0 1 0) ...) ?
<please_help>Given a list of starting indices and the length of each dimensions, increment the indices correctly
<mark_weaver>I have a 'cartesian-product' procedure that's more general than this
<lloda`>yeah, that's ndgrid in matlab/octave
<please_help>Does it generate the full list of indices? That might be too large for my usage
<please_help>I might deal with things that can go 64 x 28 x 28 x 3
<lloda`>so please_help, do you need to generate the full list, or just take the indices and do things with them one at a time?
<please_help>just one index at a time
<lloda`>so, let me explain the array-index-map! solution in full :)
<mark_weaver>please_help: I'm not sure what semantics you want in the presence of the "starting indices" you're talking about.
<please_help>'(0 0 0) is the starting index
<please_help>'(64 28 28) is the dimension length
<please_help>let's make it, say, (2 5 10) though
<lloda`>step 1. define a dummy rank 0 array, (define dummy (make-array #f))
<please_help>so, '(0 0 0) + 1 => '(0 0 1); '(0 0 9) + 1 => '(0 1 0); '(0 4 9) + 1 => '(1 0 0); '(0 3 2) + 1 => '(0 3 3) (etc.)
<lloda`>step 2. define a shared array over the dummy, (define A (make-shared-array dummy (lambda i '()) 2 5 10))
<lloda`>now you have (array-dimensions A) => (2 5 10)
<lloda`>but this array doesn't take any space at all!
<please_help>but that's not useful to me
<lloda`>now you do (array-index-map! A (lambda (indices) ... #f))
<lloda`>and you do whatever you need with the indices, generated one a time...
<please_help>yeah that works though
<please_help>how does make-shared-array handle having more dimensions than the source array?
<lloda`>like this: (shared-array-increments A) => '(0 0 0)
<lloda`>the index on the actual array is computed as 0*i+0*j+0*k = 0
<please_help>that's weird but also useful
<please_help>thanks lloda`
<lloda`>you're welcome
<please_help>will there actually be a write or is that optimized away?
<lloda`>yeah there'll be a write :-/ we should have a proc that just calls with the indices.
<mark_weaver>please_help: will the rank be a compile-time constant? would it be sufficient to have a general syntax that can handle any rank, if that rank is known at compile-time for any given use of the syntax?
<mark_weaver>(a fully dynamic solution is also possible, just asking because the compile-time constant one could be simpler and more efficiently)
<please_help>yes, the rank is known at compile-time
<mark_weaver>oh, it's easy then!
<mark_weaver>and will the bounds be in separate variables that you specify, or do the bonuds have to be in a list?
<please_help>The bounds are basically specified by (array-dimensions the-arr) which returns a list. Avoiding extra conversions would be good.
<mark_weaver>give me a few minutes, I'll cook something up
<mark_weaver>so how about syntax like this: (iterate! <bounds> (i j k) <body> ...)
<mark_weaver>is that the kind of thing you're looking for?
<please_help>No, this requires knowing the rank at write-time
<please_help>(iterate! <bounds> var-to-which-an-index-list-is-bound <body> ...)
<mark_weaver>hmm, well, that makes it very awkward to access the indices in <body>, and will be much slower
<mark_weaver>maybe the thing is to operate on the result of array-contents?
<please_help>That's a problem with the way array-ref, make-array, etc. operate
<please_help>they should definitely accept a list instead of idx ...
<mark_weaver>will the indices be used in <body> in any way except to index the array(s)?
<please_help>in my specific use-case, no.
<please_help>(apply array-ref `(,arr ,@idx))
<mark_weaver>then how about using 'array-contents' to create flattened views of all the arrays and then operating on the flattened views?
<mark_weaver>should be simpler and faster
<mark_weaver>or I'd guess so anyway, lloda` would know better
<please_help>I hoped there was a mechanism to use the array-style indices, but of course, that works.
<lloda`>please_help, array-ref, etc. all accept a list. You just need to do (apply array-ref the-list).
<please_help>when the array is not contiguous
<mark_weaver>but creating all of those lists will be expensive
<please_help>lloda`: then it doesn't accept a list, does it
<lloda`>there's no difference
<please_help>is there no extra overhead from apply?
<mark_weaver>there's extra overhead in creating the lists that will be passed to apply
<please_help>and of calling apply to delegate as well?
<mark_weaver>that's going to mean a lot of allocation, and lots of work for the garbage collector
<mark_weaver>operating on the flattened lists avoids that
<lloda`>that list will be created anyway, since the implementation of array-ref takes a list. There's specialized versions for 1 and 2 indices but that's it. Anything over 2 will create a list
<please_help>is that why arrays accept idx ... instead of idx-lst?
<please_help>to avoid list creations?
<mark_weaver>please_help: 'apply' should be fairly efficient I think, it's creating the list for apply that's the problem.
<lloda`>if all you do with the indices is index an array, then you should use array-map, array-for-each, etc. and never create an index list :-/
<mark_weaver>please_help: yes
<mark_weaver>or one of the reasons, anyway. the syntax is also nicer and more convenient in the common case where the rank is known at write-time.
<mark_weaver>and not much worse in the other case
<mark_weaver>(and syntax can always be easily customized with 'define-syntax-rule')
<mark_weaver>(define-syntax-rule (my-array-ref array indices) (apply array-ref (list indices)))
<mark_weaver>(define-syntax-rule (my-array-ref array indices) (apply array-ref indices))
<mark_weaver>gah...(define-syntax-rule (my-array-ref array indices) (apply array-ref array indices))
<mark_weaver>but yeah, if you can otherwise avoid allocations in the inner loop, allocating those lists will kill your efficiency.
<lloda`>please_help, there's no way to do what you want to do with array-for-each or array-map! ?
<lloda`>avoid creating index lists that are used only for indexing
<mark_weaver>yeah, lloda`'s suggestions may well be the best way to go here
<please_help>I can't use array-map! because I need to know which "row" I'm on, for example.
<lloda`>that makes sense, it happens often :/
<mark_weaver>please_help: I asked earlier "will the indices be used in <body> in any way except to index the array(s)?" and you said "no".
<mark_weaver>if you need to know the row, then the answer should have been "yes" :-P
<lloda`>good catch mark_weaver ;p
*mark_weaver goes afk for a bit
<please_help>(array-ec (: idx the-first-k--2-dimensions) (array-almost-map (lambda (x) (/ x (reduce + 0 (row-of x)))) (matrix-for-index idx)))) basically
<please_help>yeah, sorry mark_weaver
<lloda`>so you iterate over the first k-2 dimensions and sum over the last 2?
<please_help>no, I produce x/(sum-of row-of x) for each element in the last 2 dimensions
<please_help>row being defined as the 1st dimension in the last 2 dimensions.
<lloda`>ok. and you want the result as a new array?
<please_help>In this case, yes
<please_help>though I can allocate the array first and then copy the elements
<lloda`>lots of opportunities for hm, improvement
<lloda`>my times in are 0.428965702 for the raw-Guile and 1.415675267 for the guile-ploy version
<lloda`>actually there's no reason to do a double loop (?), it's just sum over the last dimension...
<lloda`>simpler version
<lloda`>times are now 0.241278392 for the raw-Guile and 1.092403753 for the guile-ploy version
<jgrant>Guile's documentation reads very quirky to me at least much more-so than other GNU Documentation I've read, is this just on my end?
<mark_weaver>yes, it's a bit quirky
<jgrant>I mean it seems to fairly effectively convey information, just the way it accomplishes this is bit odd and/or unexpected to me. :^P
<davexunit>you can tell that large chunks are written by different people with different technical writing styles.
<davexunit>I really like the manual, though, despite the quirkyness.
<daviid>lloda`: where is guile-ploy hosted?
*paroneayea waves