Jump to content

torstenanders

Members
  • Posts

    489
  • Joined

  • Last visited

Everything posted by torstenanders

  1. What is the opposite of chordize? Sorry for asking that, but I cannot find it. (function-I-am-looking-for 'c4e4g4) => '(c4 e4 g4) BTW, the following could be useful as well (currently nil is returned) (pitch-to-midi 'c4e4g4) => '(60 64 67) Thanks! Best, Torsten
  2. Fair enough. In order to avoid further complicating OMN, it makes sense to stick to unique symbols and to avoid "numbers as symbols" etc. Good point also that these attributes can be piece-specific simply by adding their "registration" to the score file :) Thanks for your help! Best, Torsten
  3. It is great that we meanwhile have user-defined attributes, but I sometimes like to add some ad-hoc text to the score without the need to first define them -- without any impact on the playback. This can be useful, e.g., to add rehearsal marks, various expressions and playing techniques, chord symbols, fingerings, or details for live electronics control. Beyond that, I like adding analytical information to the resulting score to inform later manual revisions, e.g., labelling motifs and perhaps even their transformation, adding custom chord and scale names etc. Doing this with user-defined attributes is kind of OK, but it could be more convenient to add certain texts to single notes, without announcing it to the system in general first. Therefore, I defined a little function that does just that. However, this function currently works only in a few cases. We can add multiple integers or floats above a note, without registering them first (useful, e.g., as parameters for live electronics). `(q ,(text-attribute -7 2 3.14 1000)) ; try notating this note => (q -7+2+3.14+1000) Here is the actual definition. (defun text-attribute (&rest args) "Convenient addition of arbitrary text directly the the score. Function transforms an arbitrary symbol, number or string or a list of symbols, numbers and strings into a an articulation symbol that is implicitly registered and can directly be added to an OMN note." (flet ((text-attr (x) (let ((s (format nil "~A" x))) (list (intern s) s)))) (merge-articulations (apply #'add-text-attributes (mapcar #'text-attr args))))) The definition depends on some other function I shared here before, but include again for convenience. (defun merge-articulations (arts &key (empty-articulations '(- default))) "Merges list of OMN articulations to a combined attribute. Args: arts: a list of OMN articulations empty-attributes: articulations to ignore in a combination. Examples: (merge-articulations '(ten ponte ubow)) => ten+ponte+ubow (merge-articulations '(- stacc)) => stacc" (intern (reduce #'(lambda (a1 a2) (format nil "~A+~A" a1 a2)) (mappend #'(lambda (art) (unless (some #'(lambda (a) (eq art a)) empty-articulations) (list (symbol-name art)))) arts)))) I would like to use the above scheme more generally, but that does not work yet. Here are a few examples that cause problems, but that I would like to see work. These examples are correctly translated into the corresponding symbols, but when trying to notate them OMN parse fails. ;; Works when symbol is registered separately, but seemingly cannot be registered "behind the scene" `(q ,(text-attribute 'espressivo)) ;; With a single expression like above, it could be argued that they can be registered explicitly with add-text-attributes, but for more specific texts this does not necessarily make sense, as they may be used only once `(q ,(text-attribute "like a whisper")) ;; Rehearsal mark (NOTE: individual letter symbols can cause confusion and should likely be avoided, e.g., "F" is understandably misunderstood by systemas dynamic mark) `(q ,(text-attribute "A")) `(q ,(text-attribute "r A")) ; rehearsal mark trying to avoid confusion with dynamic marks ;; Indications for live electronics -- using purely numbers might be OK to a certain degree `(q ,(text-attribute "delay 100ms")) `(q ,(text-attribute 'delay 100)) ;; Chord symbols need to be distinguishable from note names, hence the underscore here (could also be a space perhaps) `(q ,(text-attribute "C_7")) Strangely, on my system the following is turned into a second quarter note, even though the symbol test is unbound and not registered as a user attribute. `(q ,(text-attribute 'test)) Other applications might cause principle problems with what OMN expressions the system can parse. For example, if we use single numbers (useful, e.g., for fingering instructions) then these are misinterpreted as note durations. `(q ,(text-attribute 1)) `(q ,(text-attribute 1/4)) Single floats cause errors again. `(q ,(text-attribute 3.14)) Janusz: Is there perhaps a way to make some more of the examples above working? Also, I hope that there is no problem in calling add-text-attributes several times with the same symbol? I guess you store the total of all symbols in some data structure (e.g., a hash table) that prevents having them added multiple times? Thanks! Best, Torsten
  4. I thought we better have a function zipping articulations for us, in particular if there are articulation lists of different length. The function definition is below. Here is a usage example. Apologies to all string players that this does not necessarily make sense musically :) (make-omn :length '(1/8 1/8 1/16 1/16 -1/16 1/8 1/8 1/8 1/8) :articulation (zip-articulations '(default stacc stacc default) '(ubow dbow) '(ponte)) :swallow NIL :flat T) => (e ubow+ponte nil stacc+dbow+ponte s stacc+ubow+ponte nil dbow+ponte - e ubow+ponte nil stacc+dbow+ponte nil stacc+ubow+ponte nil dbow+ponte) Janusz: as with the dynamics function, this function does also not yet handle nested lists. Best, Torsten ;;; TODO: support nested lists -- somehow store nesting structure, then process flattened list and apply nesting back (defun zip-articulations (&rest arts) "Expects lists of articulations and combines them to a single list of merged articulations. Shorter lists are circled to the length of the longest. Example: (zip-articulations '(default leg leg default) '(breathy))" (let ((max-length (apply #'max (mapcar #'length arts)))) (mapcar #'merge-articulations (matrix-transpose (mapcar #'(lambda (xs) (circle-repeat xs max-length)) arts))))) (defun circle-repeat (pattern n) "Circle through elements in pattern (a list) until n elements are collected. NOTE: only supports flat list so far." (let ((l (length pattern))) (loop for i from 0 to (- n 1) collect (nth (mod i l) pattern)))) ; (circle-repeat '(bb4 g4 f4) 20)
  5. Fine by me to make it part of OM if Janusz and whoever decides this agree, but in this case there is still the handling of nested lists missing. Best, Torsten
  6. Thanks! Should be fixed now. (defun simplify-dynamics (dynamics) "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic). Example: (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)) => (pppp< < < < < < < < < < < < ff> > > > > > pppp) " (append (list (first dynamics)) (loop for (d1 d2 d3) on dynamics when (and d2 d3) collect (cond ((or (and (cresc-p d1) (dim-p d3)) (and (dim-p d1) (cresc-p d3))) d2) ((or (and (cresc-p d1) (cresc-p d3)) (and (not (member d2 '(< >))) (not (member d3 '(< >))) (not (member d2 *one-note-dynamic-symbol*)) (not (member d3 *one-note-dynamic-symbol*)) (< (get-velocity d2) (get-velocity d3)))) '<) ((or (and (dim-p d1) (dim-p d3)) (and (not (member d2 '(< >))) (not (member d3 '(< >))) (not (member d2 *one-note-dynamic-symbol*)) (not (member d3 *one-note-dynamic-symbol*)) (> (get-velocity d2) (get-velocity d3)))) '>) (t d2))) (last dynamics)))
  7. Found a little bug, here is a revision. (defun simplify-dynamics (dynamics) "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic). Example: (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)) => (pppp< < < < < < < < < < < < ff> > > > > > pppp)" (append (list (first dynamics)) (loop for (d1 d2 d3) on dynamics when (and d2 d3) collect (cond ((or (and (cresc-p d1) (cresc-p d3)) (and (not (member d2 '(< >))) (not (member d3 '(< >))) (< (get-velocity d2) (get-velocity d3)))) '<) ((or (and (dim-p d1) (dim-p d3)) (and (not (member d2 '(< >))) (not (member d3 '(< >))) (> (get-velocity d2) (get-velocity d3)))) '>) (t d2))) (last dynamics)))
  8. OK, I now defined the necessary auxiliary functions and almost finished the function. What is still missing is support for nested lists that retains the nesting structure. Janusz, you did this in several OMN functions already, it might be more easy if you add that yourself :) Best, Torsten (defun cresc-p (dyn) "Example: (cresc-p 'p<) => T" (and (velocityp dyn) (let ((str (symbol-name dyn))) (equal (subseq str (1- (length str))) "<")))) (defun dim-p (dyn) "Example: (dim-p 'f>) => T" (and (velocityp dyn) (let ((str (symbol-name dyn))) (equal (subseq str (1- (length str))) ">")))) ;;; TODO: support nested lists -- somehow store nesting structure, then process flattened list and apply nesting back (defun simplify-dynamics (dynamics) "Removes intermediate textual dynamic indicators from longer hairpins (e.g., generated by velocity-to-dynamic or gen-dynamic). Example: (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)) => (pppp< < < < < < < < < < < < ff> > > > > > pppp)" (append (list (first dynamics)) (loop for (d1 d2 d3) on dynamics when (and d2 d3) collect (cond ((or (and (cresc-p d1) (cresc-p d3)) (and (not (eq d2 '<)) (not (eq d3 '<)) (< (get-velocity d2) (get-velocity d3)))) '<) ((or (and (dim-p d1) (dim-p d3)) (and (not (eq d2 '>)) (not (eq d3 '>)) (> (get-velocity d2) (get-velocity d3)))) '>) (t d2))) (last dynamics)))
  9. Here is some application example for the above functions. (setf my-rhythm '(1/8 1/8 1/16 1/16 -1/16 1/8 1/8 1/8 1/8)) (setf arts-1 (pattern-map '(((1/8 1/8) (leg stacc))) my-rhythm :otherwise '(default))) (setf arts-2 (pattern-map '(((1/8) (tasto))) my-rhythm :otherwise '(ord))) (mapcar #'merge-articulations (matrix-transpose (list (flatten arts-1) (flatten arts-2)))) => (leg+tasto stacc+tasto ord ord ord leg+tasto stacc+tasto leg+tasto stacc+tasto)
  10. EDIT: OK, I now this this myself: (defun merge-articulations (arts &key (empty-articulations '(- default))) "Merges list of OMN articulations to a combined attribute. Args: arts: a list of OMN articulations empty-attributes: articulations to ignore in a combination. Examples: (merge-articulations '(ten ponte ubow)) => ten+ponte+ubow (merge-articulations '(- stacc)) => stacc" #| ; can be uncommented when articulationp works (assert (every #'articulationp arts) (arts) "All values to merge must be OMN attributes: ~A.~%" arts) |# (intern (reduce #'(lambda (a1 a2) (format nil "~A+~A" a1 a2)) (mappend #'(lambda (art) (unless (some #'(lambda (a) (eq art a)) empty-articulations) (list (symbol-name art)))) arts)))) (defun disassemble-articulations (art) "Splits a combined OMN articulations into a list of its individual attributes. Example: (disassemble-articulations 'leg+ponte) => (leg ponte)" #| (assert (articulationp art) (art) "Value not OMN articulations: ~A.~%" art) |# ;; split-string seems to be part of OMN (mapcar #'intern (split-string (symbol-name art) :separator "+")))
  11. Dear Janusz, Are there some functions to merge or disassemble articulation symbols, as shown below? (merge-articulations '(leg ponte)) => leg+ponte (disassemble-articulations leg+ponte) => (leg ponte) This would be useful when algorithmically generating or processing articulations, like chordize and friends are for algorithmically working with chords. Do you perhaps have such functionality already somewhere anyway, e.g., for generating this MusicXML output? Thanks! Best, Torsten
  12. Seemingly, length-map cannot handle the symbol - as an otherwise value. (length-map '(((1/6) (stacc))) '((-1/6 1/6 1/6) (1/4 1/4) (1/6 1/6 1/6) (1/4 -1/4)) :otherwise '(-)) => ((stacc stacc) ((length-map '(((1/6) (stacc))) '((-1/6 1/6 1/6) (1/4 1/4) (1/6 1/6 1/6) (1/4 -1/4)) :otherwise '(-)) (length-map '(((1/6) (stacc))) '((-1/6 1/6 1/6) (1/4 1/4) (1/6 1/6 1/6) (1/4 -1/4)) :otherwise '(-))) (stacc stacc stacc) ((length-map '(((1/6) (stacc))) '((-1/6 1/6 1/6) (1/4 1/4) (1/6 1/6 1/6) (1/4 -1/4)) :otherwise '(-)))) Possible workaround for now: (replace-map '((ord -)) (length-map '(((1/6) (stacc))) '((-1/6 1/6 1/6) (1/4 1/4) (1/6 1/6 1/6) (1/4 -1/4)) :otherwise '(ord))) Best, Torsten
  13. Below is a first attempt. What I am now missing to further improve it are functions that basically parse the OMN dynamics symbols to be able to tell whether some symbol expresses a crescendo or diminuendo. For example, something like the following. (cresc-p 'pp<) => T or (parse-dynamics 'pp<) => (pp <) Do you already have any such functions? (Without such functions, we could also have a lot of further cond clauses, but that would be unnecessary long and error prone.) Best, Torsten (defun simplify-dynamics (dynamics) "Removes intermediate textual dynamic indicators from longer hairpins. Example: (simplify-dynamics (pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp))" (append (list (first dynamics)) (loop for (d1 d2 d3) on dynamics when (and d2 d3) collect (cond ((and (eq d1 '<) (eq d3 '<)) '<) ((and (eq d1 '>) (eq d3 '>)) '>) (t d2))) (last dynamics))) #| (simplify-dynamics '(pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp)) => (pppp< < ppp< pp< < < < mp< mf< < < < ff> > mf> mp> p> ppp> pppp) |#
  14. I would like to algorithmically generate dynamic markings with dynamic indications like mp plus hairpins. The code snippet below shows vector values created with custom envelopes that I would like to translate, and the function velocity-to-dynamic almost does that for me already (vector-to-velocity is primarily there to translate a vector into a list). (velocity-to-dynamic (vector-to-velocity 0.1 0.7 #(0.0 0.07936508 0.15873016 0.23809525 0.31746033 0.39682543 0.4761905 0.5555556 0.63492066 0.71428573 0.79365087 0.8730159 0.952381 0.9259259 0.74074066 0.5555556 0.37037033 0.18518525 0.0))) My problem is that velocity-to-dynamic creates lots of intermediate dynamic indications, where instead I would prefer a long hairpin connecting only the extreme dynamic indications. Instead of (pppp< < ppp< pp< < p< < mp< mf< < f< < ff> > mf> mp> p> ppp> pppp) I would like to get something like the following result, which is much clearer for the performer. (pppp< < < < < < < < < < < < ff> > > > > > pppp) Would it be possible to revise velocity-to-dynamic accordingly, or should I better roll my own? Thanks! EDIT: On second thought, a separate function would likely be better, because that can then be used for all functions that generate hairpins, e.g., also gen-dynamic. Best, Torsten PS: A remaining problem would be how to handle rests, where hairpins will be interrupted. A possible solution could be to keep the output of velocity-to-dynamic as is, and instead be able to specify that the final score generation leaves out intermediate dynamic markings as those shown above, but keeps them for rests. However, that might be tricky to implement. Leaving the proper handling of rests to users and instead to simplify the output of velocity-to-dynamic with a new function is much simpler.
  15. I see, thanks. Having sticky attributes makes sense, of course. I am creating these attributes algorithmically -- I will write some function that adds the ordinario attribute where necessary for my purposes here. EDIT: no function was necessary -- just added ord. to every stacc in this case was sufficient :) Best, Torsten
  16. Thanks for coming back so quickly. Seemingly this does not work reliably -- the source file can be in the Navigator, but the definition is still not found. Anyway, the problem I have with the Navigator is that what it shows and the actual files and folders on the HD are not necessarily in sync. I understand that this gives users some flexibility to arrange their project, but I end up again and again manually making sure my files and the Navigator are in sync (e.g., after adding or moving files). Anyway, this has low priority :) Best, Torsten
  17. In the example below, the tongue slap is shown in the first bar in the score, but not the last. What am I missing? Thanks a lot! ((e g4 mp slap) (-e) (s e5 p stacc g5 stacc) (3h fs4 mp slap 3q slap)) Best, Torsten
  18. The Opusmodus editor (Hemlock) supports finding the source for definitions: point the cursor, e.g., on a function name and press M-. (on a Mac, the meta key is the alt key). This works nicely, e.g., for everything loaded via quicklisp, asdf and the sources of CCL itself (if the pathname is set up correctly, e.g., by adding the following to your extensions). Obviously, it cannot work for any Opusmodus definitions, because the sources are not available to us. (setf (logical-pathname-translations "ccl") '((#P"ccl:**;*.*" #P"/path/to/your/local-ccl-installation/ccl/**/*.*"))) However, looking up sources conveniently this way does *not* work for Opusmodus extensions loaded automatically from ~/Opusmodus/Extensions. Could please be fixed? This is a lower priority bug, but it would be very good to keep such reports somewhere on record. Opusmodus should have some bug reporting facilities for that. Keeping such messages somewhere in the forum makes the impression that they are easily forgotten, and therefore there is less of an incentive to report bugs :) Best, Torsten PS: Even if Opusmodus is not an open-source system, it would be good to learn from literature such as The Cathedral and the Bazaar by Eric S. Raymond (wikipedia): "Treating your users as co-developers is your least-hassle route to rapid code improvement and effective debugging."
  19. I would like to algorithmically process rhythms that contain grace notes. The function omn turns grace notes into 0 lengths, which is useful. (omn :length '((acc 1/8 1/8) 1/2 1/4)) However, I have difficulties translating them back after whatever processing of the rhythm. The function make-omn turns 0 lengths into the symbol z, but this symbol is not supported by snippet preview. (make-omn :length (omn :length '((acc 1/8 1/8) 1/2 1/4))) What am I missing here? Best, Torsten PS: Apologies for submitting so many messages.
  20. Thanks for coming back. Pretty much all Opusmodus functions calls are traced (https://en.wikipedia.org/wiki/Tracing_(software)) in the listener, when they are called. (Apologies if the link is over the top, just want to clarify.) Example, which causes a trace of rnd-pick. (loop repeat 10 collect (rnd-pick '(1 2 3))) I understand that this can be very useful for debugging, in particular if further information is shown like the function arguments etc., but I would like to disable it by default. Is that possible perhaps? BTW: Below is the definition of a very similar tracing function, that allows to control which functions are currently traced, or to switch of tracing globally. Best, Torsten (defvar *dbg-ids* NIL "Identifiers used by dbg") ;; was once named debug, but symbol debug is already defined in common-lisp (see opimize) (defun dbg (id format-string &rest args) "Print debugging info if (DEBUG ID) has been specified" (when (member id *dbg-ids*) (fresh-line *debug-io*) (apply #'format *debug-io* format-string args))) (defun start-debug (&rest ids) "Start debug output on the given ids." (setf *dbg-ids* (union ids *dbg-ids*))) (defun stop-debug (&rest ids) ; was once named undebug "Stop debug on ids. With no ids stop debugging altogether." (setf *dbg-ids* (if (null ids) NIL (set-difference *dbg-ids* ids)))) #| ; demo (defun test (x) (tu:dbg 'test "test") (list x x)) (tu::start-debug 'test) (loop repeat 10 collect (test 1)) (tu::stop-debug) |#
  21. Ah, brilliant -- thank you! Below this message is the corrected function for those interested. The following works now as expected. (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3) :seed 4321) The definition of map-neighbours is still in the other post above. > To stop the endless print in the Listener you could add DO-VERBOSE marco Thanks. I would prefer disabling such tracing globally -- I would only need it for debugging. Is that perhaps possible? Best, Torsten (defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil)) "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. Note: currently only plain length values, and no OMN supported. Args: divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen. set (length or list of lengths): only specified lengths are subdivided. ignore (length or list of lengths): specified lengths are *not* subdivided. lengths must be list of lists. For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular. Example: (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3))" (assert (and (listp lengths) (every #'listp lengths)) (lengths) "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths) (rnd-seed seed) (append (map-neighbours #'(lambda (bar1 bar2) (if (length-notep (first bar2)) ;; subdivide last note of bar (append (butlast bar1) (length-divide ; random control whether subdivision happens (rnd-pick '(0 1) :seed (seed)) (if (listp divide) (rnd-pick divide :seed (seed)) divide) (last bar1) :set set :ignore ignore :seed (seed))) bar1)) lengths) (last lengths)))
  22. Below is a function for creating durational accents on the beginning of bars. Many musical styles pay careful attention to how their rhythmic language expresses accents. Certain rhythmic events are perceived as stronger emphasised than others. Such accents do not need to be forced by a performer, e.g., by a dynamic accent. Instead, music theorists identified various musical factors that express accents. Durational accents (expressed by inter-onset intervals) are particularly effective. They are caused by relatively long durations following one or more shorter durations. The function definition is below. Here are two demo calls, showing multiple solutions. (durational-accent '((1/4 1/4 1/4) (1/4 1/4 -1/4) (1/4 1/4 1/4) (1/2 -1/4))) => ((1/4 1/4 1/4) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4)) => ((1/4 1/4 1/8 1/8) (1/4 1/4 -q) (1/4 1/4 1/8 1/8) (1/2 -1/4)) (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3)) => ((1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -q) (1/2 1/4) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4)) => ((1/2 1/12 1/12 1/12) (1/4 1/4 1/8 1/8) (1/2 -q) (1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -1/4)) => ((1/2 1/8 1/8) (1/4 1/4 1/4) (1/2 -q) (1/2 1/12 1/12 1/12) (1/4 1/4 1/12 1/12 1/12) (1/2 -1/4)) NB: Unfortunately, I did not get the seed argument working. I tested rnd-seed and friends with a simpler function, and everything seemed to work fine there, but I could not find what stops it working for the durational accents. Janusz: can you perhaps see what I am missing here? Best, Torsten (defun durational-accent (lengths &key (seed nil) (divide 2) (set nil) (ignore nil)) "Adds durational accents on first notes of bars by subdividing the last note of the preceding bar. `lengths' must be a list of length lists (multiple bars). If a bar starts with a rest, then it cannot carry a durational accent, and hence its preceding note is never subdivided. Note: currently only plain length values, and no OMN supported. Args: divide (integer or list of integers, default 2): specifies into how many equal note values notes preceeding a durational accent are subdivided. If list of integer, subdivision is randomly chosen. set (length or list of lengths): only specified lengths are subdivided. ignore (length or list of lengths): specified lengths are *not* subdivided. lengths must be list of lists. For now simpler version: accents only supported leading to strong beat at beginning of bar, but metric structure does not need to be regular. Example: (durational-accent (gen-repeat 2 '((h q) (q q q) (h -q))) :divide '(2 3)) BUG: arg seed not working." (rnd-seed seed) (assert (and (listp lengths) (every #'listp lengths)) (lengths) "Given `lengths' ~A is not a sequence of bars (a list of lists).~%" lengths) (append (map-neighbours #'(lambda (bar1 bar2) (if (length-notep (first bar2)) ;; subdivide last note of bar (append (butlast bar1) (length-divide ; random control whether subdivision happens (rnd-pick '(0 1) :seed (seed)) (if (listp divide) (rnd-pick divide :seed (seed)) divide) (last bar1) :set set :ignore ignore)) bar1)) lengths) (last lengths))) ;; aux def (defun map-neighbours (func list &optional n) "Applying `func' to consecutive sublists of `list'. The number of arguments expected by func implicitly specifies the number of consecutive elements to which the function is applied. This can be overwritten by the optional `n'." (let ((n2 (if n n (length (ccl:arglist func))))) (loop for l on list when (>= (length l) n2) collect (apply func (subseq l 0 n2))))) #| (map-neighbours #'(lambda (x y) (list x y)) '(1 2 3 4 5 6)) => ((1 2) (2 3) (3 4) (4 5) (5 6)) (map-neighbours #'+ '(1 2 3 4 5 6) 3) => (6 9 12 15) |#
×
×
  • Create New...

Important Information

Terms of Use Privacy Policy